Episode 03

发布时间 2023-03-22 21:08:46作者: Felix-Fu

Enemies——敌人

Enemy

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

[RequireComponent(typeof(NavMeshAgent))]

public class Enemy : MonoBehaviour
{
    NavMeshAgent pathfinder;
    Transform target;

    void Start()
    {
        //追踪Player
        pathfinder = GetComponent<NavMeshAgent>();
        target = GameObject.FindGameObjectWithTag("Player").transform;
        StartCoroutine(UpdatePath());
    }

    void Update()
    {

    }

    //不在Update里面使用SetDestination()防止计算开销过大
    IEnumerator UpdatePath()
    {
        float refreshRate = .25f;//0.25s计算一次
        while (target != null)
        {
            Vector3 targetPosition = new Vector3(target.position.x, 0, target.position.z);
            pathfinder.SetDestination(targetPosition);
            yield return new WaitForSeconds(refreshRate);
        }
    }

NavMeshAgent:[Unity - Scripting API: NavMeshAgent](file:///D:/Unity/2021.3.11f1c2/Editor/Data/Documentation/en/ScriptReference/AI.NavMeshAgent.html)

StartCoroutine(IEnumerator):启动协程

NavMeshAgent.SetDestination():跟踪目标

IEnumerator:IEnumerator类的函数就是协程的主体,IEnumerator是迭代模式的迭代器;一般的函数都是从运行到return结束,所有代码一次性运行完毕,这个协程的函数会在每次循环的时候到yield return这里停止,然后下一帧开始下一次循环。yield return null就是无返回值,达到每帧运行的这种模式,代码中使用 WaitForSeconds设定迭代时间间隔,达到间隔时间计算。

Projectile

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Projectile : MonoBehaviour
{
    //设置渲染层级
    public LayerMask collisionMask;
    float speed = 10;

    public void SetSpeed(float newSpeed)
    {
        speed = newSpeed;
    }

    void Update()
    {
        float moveDistance = Time.deltaTime * speed;
        //判断是否发生碰撞
        CheckCollisions(moveDistance);
        //Projectile移动
        transform.Translate(Vector3.forward * moveDistance);
    }

    void CheckCollisions(float moveDistance)
    {
        Ray ray = new Ray(transform.position, transform.forward);
        RaycastHit hit;

        if (Physics.Raycast(ray, out hit, moveDistance, collisionMask, QueryTriggerInteraction.Collide))
        {
            OnHitObject(hit);
        }
    }

    void OnHitObject(RaycastHit hit)
    {
        print(hit.collider.gameObject.name);
        Destroy(gameObject);
    }
}

RaycastHit:储存发射射线产生的碰撞信息,成员函数有:

  • point:射线与碰撞器的交点坐标
  • collider:与射线发生碰撞的物体的碰撞器
  • distance:射线起点到与碰撞物体交点的坐标

bool Physics.Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int layerMask,QueryTriggerInteraction ):

  • 参数start:射线的起点
  • 参数ray:射线
  • 参数hitInfo:储存被射线碰撞到的物体信息
  • 参数maxDistance:射线的最大距离
  • 参数layerMask:射线检测的图层,用int十进制转化为二进制判断,(十进制)2->(二进制)10,表示检测第一层
  • 参数QueryTriggerInteraction :查询是否忽略is Trigger(触发器),忽略使用QueryTriggerInteraction.Ignore,检测使用QueryTriggerInteraction.Collide

拓展: