How do I get my AI to chase the player?,How do I go from patrolling to chasing the player?
I am new to Unity and Scripting. So far I have a code to where my AI makes a patrol around my Nav Mesh. I want to have it chase the player and attack the player when the player comes into a certain range, but return to patrolling once the player gets out of that range. This is for an Oculus project. Any help is greatly appreciated. Here is the code I have so far:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class NPCSimplePatrol : MonoBehaviour
{
//Dictates whether the agent waits on each node
[SerializeField]
bool _patrolWaiting;
//The total time we wait at each node
[SerializeField]
float _totalWaitTime = 3f;
//The probability of switching direction
[SerializeField]
float _switchProbability = 0.2f;
//The list of all patrol nodes to visit
[SerializeField]
List<Waypoint> _patrolPoints;
//Private variables for base behaviour
NavMeshAgent _navMeshAgent;
int _currentPatrolIndex;
bool _travelling;
bool _waiting;
bool _patrolForward;
float _waitTimer;
public Transform player;
static Animator anim;
//Use this for initialization
public void Start()
{
anim = GetComponent<Animator>();
_navMeshAgent = this.GetComponent<NavMeshAgent>();
if(_navMeshAgent == null)
{
Debug.LogError("The nav mesh agent component is not attached to " + gameObject.name);
}
else
{
if(_patrolPoints != null && _patrolPoints.Count >= 2)
{
_currentPatrolIndex = 0;
SetDestination();
}
else
{
Debug.Log("Insufficient patrol points for basic patrolling behaviour.");
}
}
}
public void Update()
{
//Check if we're close to destination
if (_travelling && _navMeshAgent.remainingDistance <= 1.0f)
{
_travelling = false;
//If we're going to wait, then wait
if (_patrolWaiting)
{
_waiting = true;
_waitTimer = 0f;
}
else
{
ChangePatrolPoint();
SetDestination();
}
}
//Instead if we're waiting
if (_waiting)
{
anim.SetBool("IsIdle", true);
anim.SetBool("IsWalking", false);
anim.SetBool("IsAttacking", false);
_waitTimer += Time.deltaTime;
if (_waitTimer >= _totalWaitTime)
{
_waiting = false;
ChangePatrolPoint();
SetDestination();
anim.SetBool("IsIdle", false);
anim.SetBool("IsWalking", true);
anim.SetBool("IsAttacking", false);
}
}
}
private void SetDestination()
{
if (_patrolPoints != null)
{
Vector3 targetVector = _patrolPoints[_currentPatrolIndex].transform.position;
_navMeshAgent.SetDestination(targetVector);
_travelling = true;
}
}
/// <summary>
/// Selects a new patrol point in the available list but
/// also with a small probability allows for us to move forward or backwards
/// </summary>
private void ChangePatrolPoint()
{
if(UnityEngine.Random.Range(0f, 1f) <= _switchProbability)
{
_patrolForward = !_patrolForward;
}
if (_patrolForward)
{
_currentPatrolIndex = (_currentPatrolIndex + 1) % _patrolPoints.Count;
}
else
{
if(--_currentPatrolIndex < 0)
{
_currentPatrolIndex = _patrolPoints.Count - 1;
}
}
}
}
Answer by Eyes-Wide-Shut · Apr 24, 2019 at 02:30 AM
I can't write out code to help you, because I'm on my phone but you'll want to setup a trigger, when a player enters it, in the update function or late update function start setting the nav mesh agent destination to the player's position.
Okay so that link didn't work, and I can't upload the code because it exceeds 3000 characters.
Answer by ADay0Remember · Apr 26, 2019 at 06:41 AM
So I created a script to chase, and the AI does. The only problem is that it won't patrol, but just sit there idle here is my code that I have. Thanks for the quick reply by the way.
using System.Collections;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Chase : MonoBehaviour
{
//Dictates whether the agent waits on each node
[SerializeField]
bool _patrolWaiting;
//The total time we wait at each node
[SerializeField]
float _totalWaitTime = 3f;
//The probability of switching direction
[SerializeField]
float _switchProbability = 0.2f;
//The list of all patrol nodes to visit
[SerializeField]
List<Waypoint> _patrolPoints;
//Private variables for base behaviour
public Transform player;
static Animator anim;
NavMeshAgent _navMeshAgent;
int _currentPatrolIndex;
bool _travelling;
bool _waiting;
bool _patrolForward;
bool player_detected;
float _waitTimer;
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animator>();
_navMeshAgent = this.GetComponent<NavMeshAgent>();
if (_navMeshAgent == null)
{
Debug.LogError("The nav mesh agent component is not attached to " + gameObject.name);
}
else
{
if (_patrolPoints != null && _patrolPoints.Count >= 2)
{
_currentPatrolIndex = 0;
//SetDestination();
}
else
{
Debug.Log("Insufficient patrol points for basic patrolling behaviour.");
}
}
}
// Update is called once per frame
void Update()
{
Vector3 direction = player.position - this.transform.position;
float angle = Vector3.Angle(direction, this.transform.forward);
// this affects radius
if(Vector3.Distance(player.position, this.transform.position) < 20 && angle < 30)
{
direction.y = 0;
this.transform.rotation = Quaternion.Slerp(this.transform.rotation, Quaternion.LookRotation(direction), 0.1f);
anim.SetBool("IsIdle", false);
if(direction.magnitude > 2)
{
this.transform.Translate(0, 0, 0.05f);
anim.SetBool("IsWalking", true);
anim.SetBool("IsAttacking", false);
}
else
{
anim.SetBool("IsAttacking", true);
anim.SetBool("IsWalking", false);
}
}
else
{
anim.SetBool("IsIdle", true);
anim.SetBool("IsWalking", false);
anim.SetBool("IsAttacking", false);
}
//Check if we're close to destination
if (_travelling && _navMeshAgent.remainingDistance <= 1.0f)
{
_travelling = false;
//If we're going to wait, then wait
if (_patrolWaiting)
{
_waiting = true;
_waitTimer = 0f;
}
else
{
ChangePatrolPoint();
SetDestination();
}
}
//Instead if we're waiting
if (_waiting)
{
anim.SetBool("IsIdle", true);
anim.SetBool("IsWalking", false);
anim.SetBool("IsAttacking", false);
_waitTimer += Time.deltaTime;
if (_waitTimer >= _totalWaitTime)
{
_waiting = false;
ChangePatrolPoint();
SetDestination();
anim.SetBool("IsIdle", false);
anim.SetBool("IsWalking", true);
anim.SetBool("IsAttacking", false);
}
}
void SetDestination()
{
if (_patrolPoints != null)
{
Vector3 targetVector = _patrolPoints[_currentPatrolIndex].transform.position;
_navMeshAgent.SetDestination(targetVector);
_travelling = true;
}
}
/// <summary>
/// Selects a new patrol point in the available list but
/// also with a small probability allows for us to move forward or backwards
/// </summary>
void ChangePatrolPoint()
{
if (UnityEngine.Random.Range(0f, 1f) <= _switchProbability)
{
_patrolForward = !_patrolForward;
}
if (_patrolForward)
{
_currentPatrolIndex = (_currentPatrolIndex + 1) % _patrolPoints.Count;
}
else
{
if (--_currentPatrolIndex < 0)
{
_currentPatrolIndex = _patrolPoints.Count - 1;
}
}
}
}
}
Answer by boyblakk · Apr 26, 2019 at 03:40 PM
make a public float example public float lookRadius = 10f;
then create a method now you can see the lookRadius private void OnDrawGizmosSelected() { Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, lookRadius); } then simply write it in your code for the SetDestination
float distance = Vector3.Distance(target.position, transform.position); if (distance <= lookRadius) { pathfinder.SetDestination(targetPosition); }
so if you are in the look radius the enemy will come after you and if not he wont i hope this helps