如何在 Unity 中冻结敌人的 Ai 位置?
How Can I Freeze Enemy Ai Position In Unity?
我正在 Unity 中制作 FPS 游戏,我的玩家的一项能力是 'freeze' 任何敌人。目前我已经尝试了 3 种方法:
- 使用Rigidbody.Constraints
- 将目标路径点设置为敌人当前位置。
- 正在重置路径。
我用waypoints让我的敌人在地图上巡逻。
敌人移动代码:
public class EnemyControls : MonoBehaviour
{
NavMeshAgent agent;
private Rigidbody rb;
[SerializeField] Animator animator;
bool isPatroling;
public GameObject waypoints;
int waypointIndex;
Vector3 target;
float xWanderRange;
float zWanderRange;
private float freezeDur = 1.5f;
void Awake()
{
agent = GetComponent<NavMeshAgent>();
animator = GetComponent<Animator>();
}
void Start()
{
animator.SetBool("isPatroling", true);
waypointIndex = 0;
UpdateDestination();
}
void Update()
{
// checking if ai has reached destination or last waypoint.
if (waypointIndex == waypoints.transform.childCount - 1 && agent.remainingDistance < 0.5f)
{
xWanderRange = Random.Range(-10.0f, 10.0f);
zWanderRange = Random.Range(-10.0f, 10.0f);
// checks that the distance is big enough to move enemy.
if ((xWanderRange < -5.0f || xWanderRange > 5.0f) && (zWanderRange < -5.0f || zWanderRange > 5.0f))
{
Vector3 targetPosition = new Vector3(xWanderRange, 0, zWanderRange) + transform.position;
NavMeshHit hit;
if (NavMesh.SamplePosition(targetPosition, out hit, 1.0f, NavMesh.AllAreas))
{
agent.destination = hit.position;
}
}
}
else if (agent.remainingDistance < 1.0f)
{
// Debug.Log("Reached destination");
IterateWaypointIndex();
UpdateDestination();
}
}
void UpdateDestination()
{
target = waypoints.transform.GetChild(waypointIndex).position;
agent.SetDestination(target);
}
void IterateWaypointIndex()
{
waypointIndex++;
if (waypointIndex == waypoints.transform.childCount)
{
waypointIndex = 0;
}
}
public void StopEnemy()
{
// make enemy destination their position.
// agent.destination = transform.position;
Debug.Log("freeze enemy");
agent.ResetPath();
animator.SetBool("isPatroling", false);
// Invoke("UpdateDestination", freezeDur);
}
}
你试过的方法哪里出了问题?我会在那里放一个 isFrozen
位,然后在 Update
步骤上保释,例如:
public class EnemyControls : MonoBehaviour
{
private bool isFrozen = false;
// stuff
void Update()
{
if(isFrozen)
{
return;
}
// more Update stuff
}
// more stuff
public void StopEnemy()
{
// make enemy destination their position.
// agent.destination = transform.position;
Debug.Log("freeze enemy");
isFrozen = true;
animator.SetBool("isPatroling", false);
// Invoke("UpdateDestination", freezeDur);
}
float timer = 0;
bool isFrozen = false;
void Update()
{
if(isFrozen){
timer+= Time.deltaTime; //If isFrozen is true, ten add time to our timer
if(timer > freezeDur){ // If the timer reaches freezeDur then unfreeze and reset the timer.
isFrozen = false;
timer = 0;
}
return; //finally return statement so you will not execute code below this loop so the agent wont be able to move untill he is unfrozen.
}
// checking if ai has reached destination or last waypoint.
if (waypointIndex == waypoints.transform.childCount - 1 && agent.remainingDistance < 0.5f)
{
xWanderRange = Random.Range(-10.0f, 10.0f);
zWanderRange = Random.Range(-10.0f, 10.0f);
// checks that the distance is big enough to move enemy.
if ((xWanderRange < -5.0f || xWanderRange > 5.0f) && (zWanderRange < -5.0f || zWanderRange > 5.0f))
{
Vector3 targetPosition = new Vector3(xWanderRange, 0, zWanderRange) + transform.position;
NavMeshHit hit;
if (NavMesh.SamplePosition(targetPosition, out hit, 1.0f, NavMesh.AllAreas))
{
agent.destination = hit.position;
}
}
}
else if (agent.remainingDistance < 1.0f)
{
// Debug.Log("Reached destination");
IterateWaypointIndex();
UpdateDestination();
}
}
public void StopEnemy()
{
// make enemy destination their position.
// agent.destination = transform.position;
Debug.Log("freeze enemy");
//agent.ResetPath();
animator.SetBool("isPatroling", false);
agent.destination = transform.position; //Set the destination to its current position to stop the NPC
isFrozen = true; //Set this to true to check in update (Needs refactoring dont use Update too much. Try coroutines?
// Invoke("UpdateDestination", freezeDur);
}
请参阅上面的 //Comments
以了解我的更改说明。祝你好运!
我正在 Unity 中制作 FPS 游戏,我的玩家的一项能力是 'freeze' 任何敌人。目前我已经尝试了 3 种方法:
- 使用Rigidbody.Constraints
- 将目标路径点设置为敌人当前位置。
- 正在重置路径。
我用waypoints让我的敌人在地图上巡逻。
敌人移动代码:
public class EnemyControls : MonoBehaviour
{
NavMeshAgent agent;
private Rigidbody rb;
[SerializeField] Animator animator;
bool isPatroling;
public GameObject waypoints;
int waypointIndex;
Vector3 target;
float xWanderRange;
float zWanderRange;
private float freezeDur = 1.5f;
void Awake()
{
agent = GetComponent<NavMeshAgent>();
animator = GetComponent<Animator>();
}
void Start()
{
animator.SetBool("isPatroling", true);
waypointIndex = 0;
UpdateDestination();
}
void Update()
{
// checking if ai has reached destination or last waypoint.
if (waypointIndex == waypoints.transform.childCount - 1 && agent.remainingDistance < 0.5f)
{
xWanderRange = Random.Range(-10.0f, 10.0f);
zWanderRange = Random.Range(-10.0f, 10.0f);
// checks that the distance is big enough to move enemy.
if ((xWanderRange < -5.0f || xWanderRange > 5.0f) && (zWanderRange < -5.0f || zWanderRange > 5.0f))
{
Vector3 targetPosition = new Vector3(xWanderRange, 0, zWanderRange) + transform.position;
NavMeshHit hit;
if (NavMesh.SamplePosition(targetPosition, out hit, 1.0f, NavMesh.AllAreas))
{
agent.destination = hit.position;
}
}
}
else if (agent.remainingDistance < 1.0f)
{
// Debug.Log("Reached destination");
IterateWaypointIndex();
UpdateDestination();
}
}
void UpdateDestination()
{
target = waypoints.transform.GetChild(waypointIndex).position;
agent.SetDestination(target);
}
void IterateWaypointIndex()
{
waypointIndex++;
if (waypointIndex == waypoints.transform.childCount)
{
waypointIndex = 0;
}
}
public void StopEnemy()
{
// make enemy destination their position.
// agent.destination = transform.position;
Debug.Log("freeze enemy");
agent.ResetPath();
animator.SetBool("isPatroling", false);
// Invoke("UpdateDestination", freezeDur);
}
}
你试过的方法哪里出了问题?我会在那里放一个 isFrozen
位,然后在 Update
步骤上保释,例如:
public class EnemyControls : MonoBehaviour
{
private bool isFrozen = false;
// stuff
void Update()
{
if(isFrozen)
{
return;
}
// more Update stuff
}
// more stuff
public void StopEnemy()
{
// make enemy destination their position.
// agent.destination = transform.position;
Debug.Log("freeze enemy");
isFrozen = true;
animator.SetBool("isPatroling", false);
// Invoke("UpdateDestination", freezeDur);
}
float timer = 0;
bool isFrozen = false;
void Update()
{
if(isFrozen){
timer+= Time.deltaTime; //If isFrozen is true, ten add time to our timer
if(timer > freezeDur){ // If the timer reaches freezeDur then unfreeze and reset the timer.
isFrozen = false;
timer = 0;
}
return; //finally return statement so you will not execute code below this loop so the agent wont be able to move untill he is unfrozen.
}
// checking if ai has reached destination or last waypoint.
if (waypointIndex == waypoints.transform.childCount - 1 && agent.remainingDistance < 0.5f)
{
xWanderRange = Random.Range(-10.0f, 10.0f);
zWanderRange = Random.Range(-10.0f, 10.0f);
// checks that the distance is big enough to move enemy.
if ((xWanderRange < -5.0f || xWanderRange > 5.0f) && (zWanderRange < -5.0f || zWanderRange > 5.0f))
{
Vector3 targetPosition = new Vector3(xWanderRange, 0, zWanderRange) + transform.position;
NavMeshHit hit;
if (NavMesh.SamplePosition(targetPosition, out hit, 1.0f, NavMesh.AllAreas))
{
agent.destination = hit.position;
}
}
}
else if (agent.remainingDistance < 1.0f)
{
// Debug.Log("Reached destination");
IterateWaypointIndex();
UpdateDestination();
}
}
public void StopEnemy()
{
// make enemy destination their position.
// agent.destination = transform.position;
Debug.Log("freeze enemy");
//agent.ResetPath();
animator.SetBool("isPatroling", false);
agent.destination = transform.position; //Set the destination to its current position to stop the NPC
isFrozen = true; //Set this to true to check in update (Needs refactoring dont use Update too much. Try coroutines?
// Invoke("UpdateDestination", freezeDur);
}
请参阅上面的 //Comments
以了解我的更改说明。祝你好运!