为什么我的NPC胶囊不会徘徊?

时间:2018-02-28 14:19:29

标签: c# unity3d

这是我第一次尝试制作类似于" AI"的东西。基本上,我想要的只是一个胶囊偶尔在世界上选择一个位置,通过光线投射来查看路上是否有任何障碍物,如果没有,则移动到该位置。

我的第一次尝试如下,除非没有WaitForSeconds产量和isWandering去抖动。这个版本的胶囊以锯齿状移动,非常缓慢地移动到一个点。我的理论是,这可能是由机器人试图徘徊"多次同时进行去抖动。

我也曾尝试使用更高/更低的npcSpeed,但无济于事。这是我的代码:

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

public class npcController : MonoBehaviour {

    CharacterController control;
    Vector3 movement;
    bool isWandering = false;

    public float npcSpeed = 3f;


    void Start(){
        control = GetComponent<CharacterController> ();
    }

    void Update(){

        if (Random.Range (1f, 10f) > 8f && isWandering == false) {
            isWandering = true;
            Wander ();
        }

    }

    public bool IsWanted() {
        return true;
    }

    IEnumerator Wander(){

        int randX = Random.Range (1, 10);
        int randZ = Random.Range (1, 10);
        float moveDistance = Mathf.Sqrt (randX ^ 2 + randZ ^ 2);
        float moveTime = moveDistance / npcSpeed;

        Vector3 check = new Vector3 (randX, 0, randZ);

        RaycastHit hit;

        if (!Physics.Raycast (transform.position, check, moveDistance)) {

            transform.LookAt (check);

            control.SimpleMove (Vector3.forward * moveTime);

            yield return new WaitForSeconds (moveTime);

            isWandering = false;

        }

    }

}

我想要移动的GameObject是一个带有CharacterController和npcController脚本的游戏。

编辑:为了确认,锯齿状的移动不是由任何帧丢失引起的。游戏一直以170fps以上的速度运行

2 个答案:

答案 0 :(得分:1)

你不能通过它的名字来调用一个协程。你必须使用StartCoroutine(Wander());,这应该为你开始枚举。

答案 1 :(得分:0)

由于你的去抖动,Wander()只会被调用一帧,所以你的玩家只能移动一帧。在你的计时器运行之前它不会被再次调用,这可能是你为什么会出现紧张的动作。然而,你需要进行相当多的返工,因为如果你改变它以便在isWandering==true期间每一帧都调用Wander(),则yield语句将“堆叠”。而你可能会得到一些不必要的结果。你可以在这里不使用协程来获取计时器,而只需在isWandering == true时移动你的角色。

int randX, randZ;
float moveDistance, moveTime;
Vector3 check;
void Update()
{
    if (Random.Range(1f, 10f) > 8f && isWandering == false)
    {
        randX = Random.Range (1, 10); // movement parameters are set once here
        randZ = Random.Range (1, 10);
        moveDistance = Mathf.Sqrt (randX ^ 2 + randZ ^ 2);
        moveTime = moveDistance / npcSpeed;
        check = new Vector3 (randX, 0, randZ);
        isWandering = true;
    }
    if (isWandering) // Wander every frame while true
        Wander();
}

float timer;
void Wander()
{
    timer += Time.deltaTime;

    if (timer < moveTime) // move until timer exceeds movetime
    {
        RaycastHit hit;
        if (!Physics.Raycast (transform.position, check, moveDistance)) 
        {
           transform.LookAt (check);
           control.SimpleMove (Vector3.forward * moveTime); 
        }    
    }
    else
    {
        timer = 0; //reset timer and debounce
        isWandering = false;
    }
}