Hey, I’m looking for some insight on this script I made for wandering NPC’s.
If anyone has any critiques, suggestions, refactoring tips, or any comments I would love to hear them.
The specific script I am asking for a review on if called NCP_Patroll.cs
it can be found in my github project under nav-Experiments/Assets/This-Project/Scripts/NPC_Patrol.cs
The main ideas behind the script are for an NPC to cast rays out in a view range, collect a series of hit navigation points into an array, pick the farthest point and navigate to it.
once the NPC has a nav point it will stop casting rays for overhead reasons.
the project can be found here GitHub - JacobAButler/nav-Experiments
Here is the code for the script if that is better
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class NPC_Patrol : MonoBehaviour
{
// The number of rays
[SerializeField]
public int _rayNumber = 5;
// The view range in degrees.
[SerializeField]
public int _viewRange = 210;
// The distance between the rays.
[SerializeField]
public int _separation;
// The direction of the ray.
[SerializeField]
public Vector3 _rayVector;
// The length of the ray.
[SerializeField]
public float _rayLength = 10f;
// The distance between NPC and navPoint.
[SerializeField]
public float _dist;
// The height of the ray from the ground.
[SerializeField]
Vector3 _rayHeight = new Vector3(0.12f,.05f,0);
// May have to move this back into update
[SerializeField]
public RaycastHit _hit;
// Array of navPoints hit by the NPC
[SerializeField]
public Vector3[] _hitNavPoints;
// The destination chosen from _hitNavPoints
[SerializeField]
public Vector3 _destination;
// The
[SerializeField]
public float _maxDistance;
// Check to see in the NPC is moving
[SerializeField]
public bool _onRoute = false;
// NavMeshAgent component
NavMeshAgent _agent;
// Start is called before the first frame update
void Start()
{
_agent = this.GetComponent<NavMeshAgent>();
_destination = transform.position;
if (_agent == null)
{
Debug.LogError("The nav mesh agent component is not attached to " + gameObject.name);
}
_hitNavPoints = new Vector3[_rayNumber];
// When _hitNavPoints is initialized all the indicies are given a Vector3 and (0,0,0),
// if all the rays do not hit a navPoint on the first call,
for (int i = 0; i < _rayNumber; i++)
{
_hitNavPoints[i] = transform.position;
}
}
// Update is called once per frame
void Update()
{
if(_onRoute==false)
{
_hitNavPoints = drawRays();
_destination = findDestination(_hitNavPoints);
setDestination(_destination);
turnAround(_hitNavPoints);
}
//drawRays();
if(_onRoute && _agent.remainingDistance <= 1.0f)
{
_destination = transform.position;
_onRoute = false;
}
}
Vector3[] drawRays()
{
_rayVector = transform.TransformDirection(Vector3.right);
// the view range divided by the number of rays.
_separation = _viewRange/_rayNumber;
for(int i = 0; i < _rayNumber; i++)
{
//Need to figure out why there is not a ray for when i == 0
_rayVector = Quaternion.Euler(0, (_separation)%_viewRange, 0) * _rayVector;
Debug.DrawRay(transform.position + _rayHeight, -_rayVector*_rayLength, Color.green);
//**************************************
//******This is what works for now******
//**************************************
if (Physics.Raycast(transform.position+ _rayHeight, -_rayVector , out _hit, _rayLength))
{
_hit.collider.gameObject.tag = "NPC_Hit";
_hitNavPoints[i] = _hit.point;
}
else
{
_hitNavPoints[i] = transform.position;
}
}
return _hitNavPoints;
}
Vector3 findDestination(Vector3[] hitNavPoints)
{
Vector3 nextDestination = transform.position;
_maxDistance = 0;
for(int i = 0; i<hitNavPoints.Length;i++)
{
_dist = Vector3.Distance(hitNavPoints[i], transform.position);
if (_dist>_maxDistance)
{
_maxDistance = _dist;
nextDestination = hitNavPoints[i];
}
}
return nextDestination;
}
void setDestination(Vector3 destination)
{
if (destination!=transform.position)
{
_onRoute = true;
_agent.SetDestination(_destination);
}
}
void turnAround(Vector3[] _hitNavPoints)
{
}
}