这是我第一次尝试制作类似于" 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以上的速度运行
答案 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;
}
}