diff --git a/Assets/Editor.meta b/Assets/Editor.meta new file mode 100644 index 0000000..6374377 --- /dev/null +++ b/Assets/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3b6078cdd5879a94f9505a4f7c7517c5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/FieldOfViewEditor.cs b/Assets/Editor/FieldOfViewEditor.cs new file mode 100644 index 0000000..77a860e --- /dev/null +++ b/Assets/Editor/FieldOfViewEditor.cs @@ -0,0 +1,32 @@ +using UnityEngine; +using UnityEditor; + +[CustomEditor(typeof(FieldOfView))] +public class FieldOfViewEditor : Editor +{ + private void OnSceneGUI() + { + FieldOfView fov = (FieldOfView)target; + Handles.color = Color.white; + Handles.DrawWireArc(fov.transform.position, Vector3.up, Vector3.forward, 360, fov.Radius); + + Vector3 viewAngle01 = DirectionFromAngle(fov.transform.eulerAngles.y, -fov.Angle / 2); + Vector3 viewAngle02 = DirectionFromAngle(fov.transform.eulerAngles.y, fov.Angle / 2); + + Handles.color = Color.yellow; + Handles.DrawLine(fov.transform.position, fov.transform.position + viewAngle01 * fov.Radius); + Handles.DrawLine(fov.transform.position, fov.transform.position + viewAngle02 * fov.Radius); + + if (fov.GetTarget() != null) + { + Handles.color = Color.green; + Handles.DrawLine(fov.transform.position, fov.GetTarget().transform.position); + } + } + + private Vector3 DirectionFromAngle(float eulerY, float angleInDegrees) + { + angleInDegrees += eulerY; + return new Vector3(Mathf.Sin(angleInDegrees * Mathf.Deg2Rad), 0, Mathf.Cos(angleInDegrees * Mathf.Deg2Rad)); + } +} diff --git a/Assets/Editor/FieldOfViewEditor.cs.meta b/Assets/Editor/FieldOfViewEditor.cs.meta new file mode 100644 index 0000000..3041f75 --- /dev/null +++ b/Assets/Editor/FieldOfViewEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1bfd2211149522449963d3af42e480d2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/OutdoorsScene.unity b/Assets/OutdoorsScene.unity index 2884985..d1f8bbd 100644 --- a/Assets/OutdoorsScene.unity +++ b/Assets/OutdoorsScene.unity @@ -2369,12 +2369,12 @@ m_Acceleration: 8 avoidancePriority: 50 m_AngularSpeed: 120 - m_StoppingDistance: 0 + m_StoppingDistance: 0.2 m_AutoTraverseOffMeshLink: 1 m_AutoBraking: 1 m_AutoRepath: 1 m_Height: 2 - m_BaseOffset: 0 + m_BaseOffset: -0.08 m_WalkableMask: 4294967295 m_ObstacleAvoidanceType: 4 --- !u!1660057539 &9223372036854775807 diff --git a/Assets/OutdoorsScene/NavMesh-Ground.asset b/Assets/OutdoorsScene/NavMesh-Ground.asset index adfbf90..2a2b504 100644 --- a/Assets/OutdoorsScene/NavMesh-Ground.asset +++ b/Assets/OutdoorsScene/NavMesh-Ground.asset Binary files differ diff --git a/Assets/Scripts/NPC/FSM/Actions/Patrol/PatrolEntryAction.cs b/Assets/Scripts/NPC/FSM/Actions/Patrol/PatrolEntryAction.cs deleted file mode 100644 index acfdaad..0000000 --- a/Assets/Scripts/NPC/FSM/Actions/Patrol/PatrolEntryAction.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.AI; - -[CreateAssetMenu(menuName = "Finite State Machine/Action/Patrol/EntryAction")] -public class PatrolEntryAction : Action -{ - //This action will set a initial destination to the agent - //This action only runs once, since is an entry action on the Patrol State - private Vector3 startPosition; - - //Execute Action - public override void Execute(FSM fsm) - { - NavMeshAgent agent = fsm.Controller.Agent; - Waypoints waypoints = fsm.Controller.Waypoints; - Animator animator = fsm.Controller.Animator; - - //Generates a random index - int randomIndex = Random.Range(0, waypoints.WaypointsList.Length); - - //Sets agent destination to the random position - startPosition = waypoints.WaypointsList[randomIndex].transform.position; - agent.destination = startPosition; - animator.SetBool("IsMoving", true); - fsm.Controller.Agent.isStopped = false; - } -} diff --git a/Assets/Scripts/NPC/FSM/Actions/Patrol/PatrolEntryAction.cs.meta b/Assets/Scripts/NPC/FSM/Actions/Patrol/PatrolEntryAction.cs.meta deleted file mode 100644 index eda0162..0000000 --- a/Assets/Scripts/NPC/FSM/Actions/Patrol/PatrolEntryAction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f18c99b4f69fb7a4bae88912a2d9a497 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scripts/NPC/FSM/Actions/Patrol/PatrolWalkAction.asset b/Assets/Scripts/NPC/FSM/Actions/Patrol/PatrolWalkAction.asset index 6980994..fc01e1f 100644 --- a/Assets/Scripts/NPC/FSM/Actions/Patrol/PatrolWalkAction.asset +++ b/Assets/Scripts/NPC/FSM/Actions/Patrol/PatrolWalkAction.asset @@ -13,5 +13,5 @@ m_Name: PatrolWalkAction m_EditorClassIdentifier: waitTime: 3 - distOffSet: 0.1 - isWaiting: 1 + distOffSet: 1 + isWaiting: 0 diff --git a/Assets/Scripts/NPC/FSM/Actions/Patrol/PatrolWalkAction.cs b/Assets/Scripts/NPC/FSM/Actions/Patrol/PatrolWalkAction.cs index 550f167..9855be4 100644 --- a/Assets/Scripts/NPC/FSM/Actions/Patrol/PatrolWalkAction.cs +++ b/Assets/Scripts/NPC/FSM/Actions/Patrol/PatrolWalkAction.cs @@ -30,7 +30,7 @@ fsm.Controller.Agent.isStopped = false; // Agent starts moving // Check the remaining distance to the destination - if (!agent.pathPending && agent.remainingDistance <= distOffSet) + if (AsReachedWaypoint(agent)) { // Generates a random index int randomIndex = Random.Range(0, waypoints.WaypointsList.Length); @@ -62,5 +62,8 @@ // After waiting, set the agent to move again isWaiting = false; } + + private bool AsReachedWaypoint(NavMeshAgent agent) => + agent.remainingDistance <= agent.stoppingDistance ? true : false; } diff --git a/Assets/Scripts/NPC/FSM/Actions/Patrol/SetRandomLocation.cs b/Assets/Scripts/NPC/FSM/Actions/Patrol/SetRandomLocation.cs new file mode 100644 index 0000000..495a42f --- /dev/null +++ b/Assets/Scripts/NPC/FSM/Actions/Patrol/SetRandomLocation.cs @@ -0,0 +1,26 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.AI; + +[CreateAssetMenu(menuName = "Finite State Machine/Action/Patrol/GetRandomLocation")] +public class SetRandomLocation : Action +{ + //This action will set a initial destination to the agent + //This action only runs once, since is an entry action on the Patrol State + private Vector3 destination; + + //Execute Action + public override void Execute(FSM fsm) + { + NavMeshAgent agent = fsm.Controller.Agent; + Waypoints waypoints = fsm.Controller.Waypoints; + + //Generates a random index + int randomIndex = Random.Range(0, waypoints.WaypointsList.Length); + + //Sets agent destination to a random waypoint + destination = waypoints.WaypointsList[randomIndex].transform.position; + agent.destination = destination; + } +} diff --git a/Assets/Scripts/NPC/FSM/Actions/Patrol/SetRandomLocation.cs.meta b/Assets/Scripts/NPC/FSM/Actions/Patrol/SetRandomLocation.cs.meta new file mode 100644 index 0000000..eda0162 --- /dev/null +++ b/Assets/Scripts/NPC/FSM/Actions/Patrol/SetRandomLocation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f18c99b4f69fb7a4bae88912a2d9a497 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/NPC/FieldOfView.cs b/Assets/Scripts/NPC/FieldOfView.cs new file mode 100644 index 0000000..22922a2 --- /dev/null +++ b/Assets/Scripts/NPC/FieldOfView.cs @@ -0,0 +1,67 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class FieldOfView : MonoBehaviour +{ + [SerializeField] private float radius; + [Range(0, 360)] + [SerializeField] private float angle; + [SerializeField] private float delay; + [SerializeField] private Vector3 lastPosition; + + [SerializeField] private GameObject targetRef; + + [SerializeField] private LayerMask targetMask; + [SerializeField] private LayerMask obstructionMask; + + public float Radius => radius; + public float Angle => angle; + + // Start is called before the first frame update + void Start() + { + StartCoroutine(FOVRoutine()); + } + + private IEnumerator FOVRoutine() + { + WaitForSeconds wait = new WaitForSeconds(delay); + + while (true) + { + yield return wait; + FieldOfViewCheck(); + } + } + + private void FieldOfViewCheck() + { + Collider[] rangeCheck = Physics.OverlapSphere(transform.position, radius, targetMask); + + if (rangeCheck.Length != 0) + { + Transform target = rangeCheck[0].transform; + Vector3 directionToTarget = (target.position - transform.position).normalized; + + if (Vector3.Angle(transform.forward, directionToTarget) < angle / 2) + { + float distanceToTarget = Vector3.Distance(transform.position, directionToTarget); + + if (!Physics.Raycast(transform.position, directionToTarget, distanceToTarget, obstructionMask)) + { + targetRef = target.gameObject; + lastPosition = target.position; + } + } + } + + else targetRef = null; + } + + //Returns the Last Position the target was seen + public Vector3 LastPosition() => lastPosition; + + //Returns the current target + public GameObject GetTarget() => targetRef; +} diff --git a/Assets/Scripts/NPC/FieldOfView.cs.meta b/Assets/Scripts/NPC/FieldOfView.cs.meta new file mode 100644 index 0000000..c77a187 --- /dev/null +++ b/Assets/Scripts/NPC/FieldOfView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fc6ae1c3ef2650447a489e6e7ff66a68 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/ProjectSettings/Packages/com.unity.probuilder/Settings.json b/ProjectSettings/Packages/com.unity.probuilder/Settings.json index ba1f0ab..80df71c 100644 --- a/ProjectSettings/Packages/com.unity.probuilder/Settings.json +++ b/ProjectSettings/Packages/com.unity.probuilder/Settings.json @@ -159,7 +159,7 @@ { "type": "UnityEngine.Vector3, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "key": "ShapeBuilder.LastSize", - "value": "{\"m_Value\":{\"x\":-0.25,\"y\":1.1891614198684693,\"z\":3.0}}" + "value": "{\"m_Value\":{\"x\":5.5,\"y\":3.215651750564575,\"z\":0.25}}" }, { "type": "UnityEngine.Quaternion, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",