C# Can';不要让我的敌人在一定范围内随意移动。Unity3D

C# Can';不要让我的敌人在一定范围内随意移动。Unity3D,c#,random,unity3d,artificial-intelligence,C#,Random,Unity3d,Artificial Intelligence,嗨:我正在制作一个FPS,里面混合了一些3D的生存场景。我有一个代表我敌人的动画模型。如果我在射程内,我可以让他向我靠近。如果他离得足够近,他就会停止移动(并设置动画)。现在,我试图实现一种流浪行为 我的想法是这样的:敌人从起始位置开始。他检查玩家是否在范围内,如果为真,则跟随玩家(),如果为假,则移动(),这意味着他在其实际位置的特定范围内计算一个随机位置,移动到该位置,然后移动到该随机位置。到达随机位置后,他应等待X秒,直到下一步。我使用的MoveAround()方法是一个协同程序,但我无法

嗨:我正在制作一个FPS,里面混合了一些3D的生存场景。我有一个代表我敌人的动画模型。如果我在射程内,我可以让他向我靠近。如果他离得足够近,他就会停止移动(并设置动画)。现在,我试图实现一种流浪行为

我的想法是这样的:敌人从起始位置开始。他检查玩家是否在范围内,如果为真,则跟随玩家(),如果为假,则移动(),这意味着他在其实际位置的特定范围内计算一个随机位置,移动到该位置,然后移动到该随机位置。到达随机位置后,他应等待X秒,直到下一步。我使用的MoveAround()方法是一个协同程序,但我无法使它工作。以下是脚本:

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);
}
}
使用UnityEngine;
使用系统集合;
公共类EnemyAI:单一行为{
公众浮标轮换速度;
公共交通速度;
公共浮动最大速度;
公共浮动范围;
公共浮动最大范围;
公众浮动范围;
动画师;
字符控制器;
//用于初始化
无效唤醒(){
anim=GetComponent();
controller=GetComponent();
}
无效开始(){
}
//每帧调用一次更新
无效固定更新(){
FollowPlayer();
start例程(MoveAround());
}
void FollowPlayer(){
Vector3 playerPos=GameObject.Find(“Player”).transform.position;
Vector3 lookDir=播放者角色-变换位置;
Vector3 moveDir=lookDir;//*moveSpeed;
moveDir*=Time.fixedDelatime;
if((向量3.距离(变换.位置,播放者)最小范围)){
Vector3 previous=transform.position;
transform.rotation=Quaternion.Slerp(transform.rotation,Quaternion.LookRotation(lookDir),rotationSpeed*Time.fixedDeltaTime);
控制器。移动(moveDir);
浮动速度=((transform.position-previous).magnity)/Time.fixedDeltaTime;
//Log(“velocidad:+velocity”);
previous=transform.position;
anim.SetFloat(“速度”,速度);
}
if(矢量3.距离(变换.位置,播放者)最大范围){
Log(“移动敌人”);
Vector3 previous=transform.position;
transform.rotation=Quaternion.Slerp(transform.rotation,Quaternion.LookRotation(lookDir),rotationSpeed*Time.fixedDeltaTime);
控制器。移动(moveDir);
浮动速度=((transform.position-previous).magnity)/Time.fixedDeltaTime;
//Log(“velocidad:+velocity”);
previous=transform.position;
anim.SetFloat(“速度”,速度);
调试日志(“敌人移动”);
产生返回新的WaitForSeconds(2f);
Log(“等待前2秒”);
}
Log(“到达目的地”);
产生返回新的WaitForSeconds(2f);
Debug.Log(“COroutine final”);
}
void OnDrawGizmosSelected(){
Gizmos.color=color.green;
Gizmos.DrawWireSphere(transform.position,maxRange);
Gizmos.DrawWireSphere(transform.position,minRange);
}
}
注意:贴图应该是平面的,但是如果代码用于具有可变高度的贴图,那就太好了。
我正在用字符控制器移动字符,这是正确的方法吗?

您正在调用
MoveAround
FollowPlayer
每一帧(实际上是每一个物理帧,更频繁)。实际上,您想做更多类似的事情:

void Start()
{
    StartCoroutine(Move());
}

IEnumerator Move()
{
    while (true)
    {
        if (nearPlayer)
            yield return StartCoroutine(FollowPlayer());
        else
            yield return StartCoroutine(MoveAround());
    }
}
这样,您只能在上一个移动完成后才开始移动。如果您想检查每一帧的位置,它仍然有效,但您的检查将在
MoveAround
FollowPlayer
内部进行。因为每一帧都启动协同路由完全违背了协同路由的目的。如果您有希望运行每个帧的逻辑(无例外),请直接将其放入
Update
FixedUpdate
,而不使用协同程序


编辑:澄清一下,你的方法最简单的错误是,如果你的协同程序运行4秒,你将有
4/次。FixedDelatime
每个方法的实例在任何时刻运行,可能会相互冲突。我认为您不希望400个单独的移动函数同时运行。:)

我可以看看你的调试日志吗?为playerPosSure添加一个:当我击中Play时,敌人设置为(50,0,50)。然后这是第一个控制台日志:·玩家位置:(0.6,0.0,31.7)·随机位置:(50.5,0.0,48.0)·外观方向:(0.5,0.0,-2.0)·移动方向:(0.0,0.0,0.0)·移动敌人·移动敌人必须尝试您发布的内容,但我的FollowPlayer方法不是协同程序,所以我应该将其更改为IEnumerator方法吗?我还尝试将调用FollowPlayer协同程序的行更改为:仅调用方法本身。好的,第一点是:您说过“敌人从起始位置开始。他检查玩家是否在射程内,如果为真,则FollowPlayer(),如果为假,则移动(),”。“Check/If/Then”逻辑显然是重复的,但您希望多长时间重复一次?我编写的代码假设这两个方法都是协同路由,并将一直运行,直到它们决定完成为止。如果
FollowPlayer
不需要是协同程序