I am making a FPS game in Unity, one of my player's abilities is to 'freeze' any enemy. I've tried this in 3 ways at the moment:
- using Rigidbody.Constraints
- Setting Target waypoint to the enemies current position.
- Resetting the path.
I use waypoints to make my enemies patrol the map.
Enemy Movement Code:
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);
}
}
CodePudding user response:
What went wrong with the methods you tried? I would just put an isFrozen
bit in there and bail on the Update
step if it is, like:
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);
}
CodePudding user response:
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);
}
See the //Comments
above for explanation of my alterations. Good luck!