Newer
Older
HierarchicalFSM-Unity3D / Assets / Scripts / NPC / NPCController.cs
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.AI;
  5. [RequireComponent(typeof(NavMeshAgent))]
  6. public class NPCController : MonoBehaviour
  7. {
  8. [SerializeField] private Waypoints waypoints;
  9. private Collider agentCollider;
  10. private NavMeshAgent agent;
  11. private Animator animator;
  12. private Vector2 Velocity;
  13. private Vector2 SmoothDeltaPosition;
  14. private FieldOfView agentFOV;
  15. private Awareness agentAwareness;
  16. private Dictionary<string, object> agentBeliefs;
  17. public Animator Animator => animator;
  18. public NavMeshAgent Agent => agent;
  19. public Collider AgentCollider => agentCollider;
  20. public Waypoints Waypoints => waypoints;
  21. public FieldOfView AgentFOV => agentFOV;
  22. public Awareness AgentAwareness => agentAwareness;
  23. public Dictionary<string, object> AgentBeliefs => agentBeliefs;
  24. void Awake()
  25. {
  26. agent = GetComponent<NavMeshAgent>();
  27. animator = GetComponent<Animator>();
  28. agentCollider = GetComponent<Collider>();
  29. agentFOV = GetComponentInChildren<FieldOfView>();
  30. agentAwareness = GetComponentInChildren<Awareness>();
  31. }
  32. // Start is called before the first frame update
  33. void Start()
  34. {
  35. agent.stoppingDistance = 0.1f;
  36. agent.updatePosition = false;
  37. animator.applyRootMotion = true;
  38. agent.updateRotation = true;
  39. }
  40. // Update is called once per frame
  41. void Update()
  42. {
  43. Debug.Log("IsMoving: " + animator.GetBool("IsMoving"));
  44. SynchronizeAnimatoraAndAgent();
  45. }
  46. private void OnAnimatorMove()
  47. {
  48. Vector3 rootPosition = animator.rootPosition;
  49. rootPosition.y = agent.nextPosition.y;
  50. transform.position = rootPosition;
  51. agent.nextPosition = rootPosition;
  52. }
  53. //Synchronize the animation and Agent
  54. private void SynchronizeAnimatoraAndAgent()
  55. {
  56. //Distance between the agent next position and the Game Object position
  57. Vector3 worldDeltaPosition = agent.nextPosition - transform.position;
  58. worldDeltaPosition.y = 0f;
  59. float dx = Vector3.Dot(transform.right, worldDeltaPosition);
  60. float dy = Vector3.Dot(transform.forward, worldDeltaPosition);
  61. Vector2 deltaPosition = new Vector2(dx, dy);
  62. float smooth = Mathf.Min(1, Time.deltaTime / 0.1f);
  63. SmoothDeltaPosition = Vector2.Lerp(SmoothDeltaPosition, deltaPosition, smooth);
  64. //Calculate the velocity
  65. Velocity = SmoothDeltaPosition / Time.deltaTime;
  66. if (agent.remainingDistance <= agent.stoppingDistance)
  67. {
  68. Velocity = Vector2.Lerp(Vector2.zero, Velocity, agent.remainingDistance / agent.stoppingDistance);
  69. }
  70. bool shouldMove = Velocity.magnitude > 0.5f && agent.remainingDistance > agent.stoppingDistance;
  71. animator.SetBool("IsMoving", shouldMove);
  72. animator.SetFloat("Velocity", Velocity.magnitude);
  73. animator.SetFloat("VelX", Velocity.x);
  74. animator.SetFloat("VelY", Velocity.y);
  75. float deltaMagnitude = worldDeltaPosition.magnitude;
  76. if (deltaMagnitude > agent.radius / 2f)
  77. {
  78. transform.position = Vector3.Lerp(animator.rootPosition, agent.nextPosition, smooth);
  79. }
  80. }
  81. public void AddAgentBelief(string key, object value)
  82. {
  83. //Checks for the key in dictionary
  84. if (!agentBeliefs.ContainsKey(key))
  85. {
  86. //Adds the key and value if it doesn't exists
  87. agentBeliefs.Add(key, value);
  88. }
  89. else
  90. {
  91. //Updates the value if key exists
  92. agentBeliefs[key] = value;
  93. }
  94. }
  95. public object GetAgentBelief(string key)
  96. {
  97. //Checks for the key in dictionary
  98. if (agentBeliefs.ContainsKey(key))
  99. {
  100. //Returns the value if the key exists
  101. return agentBeliefs[key];
  102. }
  103. else
  104. {
  105. //Returns null if the key doesn't exists
  106. Debug.LogWarning($"The {key} doesn't exist in {nameof(agentBeliefs)}");
  107. return null;
  108. }
  109. }
  110. }