可以';不要让我的敌人在一个范围内随意移动.Unity3D

本文关键字:一个 范围内 Unity3D 移动 随意 敌人 我的 可以 | 更新日期: 2024-09-08 07:04:07

嗨:我正在制作一个FPS,并在3D中进行一些生存。我有一个动画模型,代表我的敌人。如果我在射程内,我可以让他向我靠近。如果他离得足够近,他就会停止移动(和动画)。现在我正在努力实现流浪行为。

我的想法是这样的:敌人从起始位置开始。他检查玩家是否在范围内,如果为true,则FollowPlayer()如果为false,则MoveAround(),这意味着他在实际位置的某个范围内计算一个随机位置,旋转到该位置,然后移动到该随机位置。到达随机位置后,他应该等待X秒,直到下一步行动。MoveAround()方法是一个Coroutine,但我无法使它工作。这是脚本:

using UnityEngine;
using System.Collections;
public class EnemyAI : MonoBehaviour {
public float rotationSpeed;
public float moveSpeed;
public float maxSpeed;
public float minRange;
public float maxRange;
public float moveRange;
Animator anim;
CharacterController controller;
// Use this for initialization
void Awake (){
    anim = GetComponent<Animator> ();
    controller = GetComponent<CharacterController> ();
}
void Start () {
}
// Update is called once per frame
void FixedUpdate () {
    FollowPlayer ();
    StartCoroutine(MoveAround ());
}
void FollowPlayer(){
    Vector3 playerPos = GameObject.Find ("Player").transform.position;
    Vector3 lookDir = playerPos - transform.position;
    Vector3 moveDir = lookDir;// * moveSpeed;
    moveDir *= Time.fixedDeltaTime;
    if((Vector3.Distance(transform.position, playerPos) <= maxRange) && (Vector3.Distance(transform.position, playerPos) > minRange) ){
        Vector3 previous = transform.position;
        transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation (lookDir), rotationSpeed * Time.fixedDeltaTime);
        controller.Move(moveDir);
        float velocity = ((transform.position - previous).magnitude) / Time.fixedDeltaTime;
    //  Debug.Log("velocidad: " + velocity);
        previous = transform.position;
        anim.SetFloat ("speed", velocity);
    }
    if(Vector3.Distance(transform.position, playerPos) < minRange){
        controller.Move(Vector3.zero);
        Debug.LogWarning("hey");
        anim.SetFloat("speed",controller.velocity.magnitude);
    }
}
IEnumerator MoveAround(){
    Vector3 playerPos = GameObject.Find ("Player").transform.position;
    Vector3 randomPos = Random.onUnitSphere * moveRange;
    randomPos = new Vector3 (randomPos.x + transform.position.x, transform.position.y, randomPos.z + transform.position.z);
    Vector3 lookDir = randomPos - transform.position;
    Vector3 moveDir = lookDir;
    moveDir *= Time.fixedDeltaTime;
    Debug.Log ("Player Pos: " + playerPos);
    Debug.Log ("Random Pos: " + randomPos);
    Debug.Log ("Look Dir: " + lookDir);
    Debug.Log ("Move Dir: " + moveDir);
    if(Vector3.Distance(transform.position, playerPos) > maxRange){
        Debug.Log("Moving the enemy");
        Vector3 previous = transform.position;
        transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation (lookDir), rotationSpeed * Time.fixedDeltaTime);
        controller.Move(moveDir);
        float velocity = ((transform.position - previous).magnitude) / Time.fixedDeltaTime;
    //  Debug.Log("velocidad: " + velocity);
        previous = transform.position;
        anim.SetFloat ("speed", velocity);
        Debug.Log("Enemy moved");
        yield return new WaitForSeconds(2f);
        Debug.Log("waiting the first 2 seconds");
    }
    Debug.Log ("arrived at destination");
    yield return new WaitForSeconds(2f);
    Debug.Log ("COroutine final");
}
void OnDrawGizmosSelected(){
    Gizmos.color = Color.green;
    Gizmos.DrawWireSphere (transform.position, maxRange);
    Gizmos.DrawWireSphere (transform.position, minRange);
}
}

注意:地图应该是平的,但如果代码适用于具有可变高度的地图,那就太好了。我用字符控制器移动字符,这是正确的方法吗?

可以';不要让我的敌人在一个范围内随意移动.Unity3D

您在每帧(实际上是每一个物理帧,更频繁)调用MoveAroundFollowPlayer。你实际上想做一些更像这样的事情:

void Start()
{
    StartCoroutine(Move());
}
IEnumerator Move()
{
    while (true)
    {
        if (nearPlayer)
            yield return StartCoroutine(FollowPlayer());
        else
            yield return StartCoroutine(MoveAround());
    }
}

这样,你只有在上一次移动完成后才能开始移动。如果您想检查每帧的位置,它仍然有效,但您的检查将在MoveAroundFollowPlayer内部进行。因为每一帧启动协同程序都会完全违背协同程序的目的。如果您有想要运行每一帧的逻辑(无一例外),请直接将其放入UpdateFixedUpdate中,而不使用协程。

编辑:要澄清的是,你的方法最简单的错误是,如果你的协程需要4秒才能运行,那么你会在任何时候都有每个方法的4/Time.fixedDeltaTime个实例在运行,可能会相互争斗。我认为您不希望400个独立的MoveAround函数同时运行。:)