123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- using UnityEngine;
- namespace HQFPSWeapons
- {
- /// <summary>
- /// Sends a ray from the center of the camera, in the game world.
- /// Gathers data about what is in front of the player, and stores it in a variable.
- /// </summary>
- public class PlayerInteraction : PlayerComponent
- {
- [SerializeField]
- private Camera m_WorldCamera = null;
- [SerializeField]
- [Tooltip("The maximum distance at which you can interact with objects.")]
- private float m_InteractionDistance = 2f;
- [SerializeField]
- [Range(0f, 60f)]
- private float m_MaxInteractionAngle = 30f;
- [SerializeField]
- private LayerMask m_LayerMask = new LayerMask();
- private InteractiveObject m_InteractedObject;
- private void Awake()
- {
- Player.WantsToInteract.AddChangeListener(OnChanged_WantsToInteract);
- }
- private void OnChanged_WantsToInteract(bool wantsToInteract)
- {
- var raycastData = Player.RaycastData.Get();
- var wantedToInteractPreviously = Player.WantsToInteract.GetPreviousValue();
- var wantsToInteractNow = wantsToInteract;
- if(raycastData != null && raycastData.IsInteractive)
- {
- if(!wantedToInteractPreviously && wantsToInteractNow)
- {
- raycastData.InteractiveObject.OnInteractionStart(Player);
- m_InteractedObject = raycastData.InteractiveObject;
- }
- }
- if(m_InteractedObject != null && wantedToInteractPreviously && !wantsToInteractNow)
- {
- m_InteractedObject.OnInteractionEnd(Player);
- m_InteractedObject = null;
- }
- }
- private void Update()
- {
- var ray = m_WorldCamera.ViewportPointToRay(Vector2.one * 0.5f);
- var lastRaycastData = Player.RaycastData.Get();
- var collidersInRange = Physics.OverlapSphere(m_WorldCamera.transform.position, m_InteractionDistance, m_LayerMask, QueryTriggerInteraction.Collide);
- float smallestAngle = 1000f;
- InteractiveObject closestObject = null;
- int closestObjectIndex = -1;
- Vector3 cameraPosition = m_WorldCamera.transform.position;
- Vector3 cameraDirection = m_WorldCamera.transform.forward;
- for(int i = 0;i < collidersInRange.Length; i ++)
- {
- InteractiveObject interactiveObject = collidersInRange[i].GetComponent<InteractiveObject>();
- RaycastHit hitInfo;
- if(interactiveObject != null && Physics.Linecast(cameraPosition, interactiveObject.transform.position + (interactiveObject.transform.position - cameraPosition).normalized * 0.05f, out hitInfo, m_LayerMask))
- {
- if(hitInfo.collider == null || hitInfo.collider == collidersInRange[i])
- {
- float angle = Vector3.Angle(cameraDirection, interactiveObject.transform.position - cameraPosition);
- if(angle < smallestAngle)
- {
- smallestAngle = angle;
- closestObject = interactiveObject;
- closestObjectIndex = i;
- }
- }
- }
- }
- if(smallestAngle < m_MaxInteractionAngle && ((lastRaycastData != null && lastRaycastData.Collider != collidersInRange[closestObjectIndex]) || lastRaycastData == null))
- {
- var raycastData = new RaycastData(collidersInRange[closestObjectIndex], closestObject);
- Player.RaycastData.Set(raycastData);
- bool startedRaycastingOnObject =
- lastRaycastData != null &&
- raycastData.IsInteractive &&
- raycastData.InteractiveObject != lastRaycastData.InteractiveObject;
- if(startedRaycastingOnObject)
- raycastData.InteractiveObject.OnRaycastStart(Player);
- else if(raycastData.IsInteractive)
- raycastData.InteractiveObject.OnRaycastUpdate(Player);
- else if(lastRaycastData != null && lastRaycastData.InteractiveObject != null)
- lastRaycastData.InteractiveObject.OnRaycastEnd(Player);
- }
- else if(smallestAngle > m_MaxInteractionAngle)
- {
- Player.RaycastData.Set(null);
- // Let the object know the ray it's not on it anymore.
- if(lastRaycastData != null && lastRaycastData.IsInteractive)
- {
- if(lastRaycastData.IsInteractive)
- lastRaycastData.InteractiveObject.OnRaycastEnd(Player);
- }
- }
- // if(Physics.Raycast(ray, out hitInfo, m_InteractionDistance, m_LayerMask, QueryTriggerInteraction.Collide) && ((lastRaycastData != null && lastRaycastData.HitInfo.collider != hitInfo.collider) || lastRaycastData == null))
- // {
- // var raycastData = new RaycastData(hitInfo);
- // Player.RaycastData.Set(raycastData);
- //
- // bool startedRaycastingOnObject =
- // lastRaycastData != null &&
- // raycastData.IsInteractive &&
- // raycastData.InteractiveObject != lastRaycastData.InteractiveObject;
- //
- // if(startedRaycastingOnObject)
- // raycastData.InteractiveObject.OnRaycastStart(Player);
- // else if(raycastData.IsInteractive)
- // raycastData.InteractiveObject.OnRaycastUpdate(Player);
- // else if(lastRaycastData != null && lastRaycastData.InteractiveObject != null)
- // lastRaycastData.InteractiveObject.OnRaycastEnd(Player);
- // }
- // else if(hitInfo.collider == null)
- // {
- // Player.RaycastData.Set(null);
- //
- // // Let the object know the ray it's not on it anymore.
- // if(lastRaycastData != null && lastRaycastData.IsInteractive)
- // {
- // if(lastRaycastData.IsInteractive)
- // lastRaycastData.InteractiveObject.OnRaycastEnd(Player);
- // }
- // }
- // bool objectInProximity = Physics.CheckSphere(transform.position + transform.TransformVector(m_ProximityDetection.Offset), m_ProximityDetection.Radius, m_ProximityDetection.Mask);
- //
- // Player.ObjectInProximity.Set(objectInProximity);
- if(m_InteractedObject != null)
- m_InteractedObject.OnInteractionUpdate(Player);
- }
- // private void OnDrawGizmosSelected()
- // {
- // Gizmos.color = Color.red;
- // Gizmos.DrawWireSphere(transform.position + transform.TransformVector(m_ProximityDetection.Offset), m_ProximityDetection.Radius);
- // }
- // // -------------------- Internal --------------------
- // [Serializable]
- // public struct ProximityDetection
- // {
- // public Vector3 Offset;
- //
- // [Range(0f, 2f)]
- // public float Radius;
- //
- // public LayerMask Mask;
- // }
- }
- }
|