Hi all.
I am using a extremly simple sort of weight system for my AI where I set a predifined int value to every object that should be of interest to the AI.
Flow of the AI is:
1: Search 360 degree for all objects. Set the int value “weight” to the found objects
2: Use Navmesh to travel to the location with the largest int value “weight”.
3: When reached, start a new scan again as in 1 and 2.
This works great until the AI has reached the players location. Then the scan goes on forever and the target path is placed at a position where a non walkable location is… “See video”
I have been sitting with this code for 3 days now and I would really need some help with it.
Am I doing this right or is this the wrong way to go?
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine.AI;
using UnityEngine;
using WatcherScanResults;
public class watcherScanBehavior : MonoBehaviour {
[SerializeField]
private Terrain terrain;
[SerializeField]
private GameObject eye;
[SerializeField]
private GameObject navMeshMain;
private List<cls_watcherScanResults> clsWSR_Locations = new List<cls_watcherScanResults>();
[SerializeField]
[Range(1.0f, 20000.0f)]
private float scanRange = 100.0f;
[SerializeField]
[Range(0.1f, 5.0f)]
private float scanSpeed = 1.0f;
[SerializeField]
[Range(1.0f, 50.0f)]
private float scanSphereSize = 3.0f;
[SerializeField]
[Range(0.0f, 10.0f)]
private float stopAtDistanceFromObject = 5.0f;
[SerializeField]
private float scanDegree = 0.0f;
private int scanLocationWeight;
private bool scanLocationAcquired = false;
private bool scanDone = false;
private bool scanning = true;
[SerializeField]
private GameObject target;
private Vector3 locationCoords;
private int highestWeight;
[SerializeField]
private bool agentReachedLocation = true;
[SerializeField]
private NavMeshAgent agent;
private NavMeshPath agentPath;
void Start() {
agentPath = new NavMeshPath();
agentReachedLocation = false;
}
private void LateUpdate() {
if (scanLocationAcquired == false) {
scanNewLocations();
} else {
if (scanLocationAcquired == true && agentReachedLocation == false) {
agent.CalculatePath(locationCoords, agentPath);
if (agentPath.status == NavMeshPathStatus.PathPartial) {
Debug.Log("Cant reach location");
scanLocationAcquired = false;
agentReachedLocation = false;
highestWeight = 0;
scanDegree = 0;
} else {
target.transform.position = locationCoords;
agent.SetDestination(locationCoords);
if (!agent.pathPending) {
if (agent.remainingDistance <= agent.stoppingDistance) {
if (!agent.hasPath || agent.velocity.sqrMagnitude == 0f) {
scanLocationAcquired = false;
agentReachedLocation = true;
highestWeight = 0;
scanDegree = 0;
Debug.Log("Standing still");
}
}
}
}
}
}
}
void scanNewLocations() {
RaycastHit hit;
if (scanDegree < 360) { // Tills 360 grader söks igenom
agentReachedLocation = false;
eye.transform.Rotate(new Vector3(0, 0, scanSpeed)); // Rotera ögat
Quaternion q = Quaternion.AngleAxis(scanSpeed * Time.deltaTime, Vector3.up);
Vector3 d = -eye.transform.right * scanRange;
Debug.DrawRay(eye.transform.position, q * d, Color.green, 2.0f); // Bara för att visualisera sökandet.
if (Physics.SphereCast(navMeshMain.transform.position, scanSphereSize, q * d, out hit, scanRange)) { // Spherecast
if (hit.transform.tag != "Untagged") {
switch (hit.transform.tag) {
case "Player":
scanLocationWeight = 1;
break;
case "TestBox":
scanLocationWeight = 2; // Temporary example
break;
default:
scanLocationWeight = 0;
break;
}
}
cls_watcherScanResults clsWSR_FoundLocation = new cls_watcherScanResults();
if (scanLocationWeight > 0){
clsWSR_FoundLocation.resultGameObject = hit.transform.gameObject;
clsWSR_FoundLocation.resultWeight = scanLocationWeight;
clsWSR_Locations.Add(clsWSR_FoundLocation);
}
}
scanDegree++;
} else {
for (int i = 0; i < clsWSR_Locations.Count; i++) {
if (clsWSR_Locations[i].resultWeight > highestWeight) {
highestWeight = clsWSR_Locations[i].resultWeight;
locationCoords = clsWSR_Locations[i].resultGameObject.transform.position;
}
}
clsWSR_Locations.Clear();
if (highestWeight == 0) {
Vector2 coords;
coords = Random.insideUnitCircle * scanRange;
locationCoords = new Vector3(coords.x, terrain.SampleHeight(new Vector3(coords.x, 0, coords.y)), coords.y);
}
scanLocationAcquired = true;
}
}
}
Video: