using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; [RequireComponent(typeof(EyeSimulation))] public class EyePOIManager : MonoBehaviour, IListener { private EyeSimulation eyeSim; private List<EyePOI> POIs; private EyePOI currentPOI = null; private Camera headCam; private float poiCheckTime = 2f; private float t = 0f; private void Awake() { eyeSim = GetComponent<EyeSimulation>(); POIs = FindObjectsOfType<EyePOI>().ToList(); headCam = Camera.main; } private void Start() { TestCurrentPOI(); EventManager.Instance.AddListener(EVENT_TYPE.ON_EYE_POI_APPEARED, this); EventManager.Instance.AddListener(EVENT_TYPE.ON_EYE_POI_DISAPPEARED, this); } private void Update() { TestCurrentPOI(); } public void OnEvent<T>(EVENT_TYPE eventType, Component Sender, T param = default) { switch(eventType) { case EVENT_TYPE.ON_EYE_POI_APPEARED: break; case EVENT_TYPE.ON_EYE_POI_DISAPPEARED: break; } } /// <summary> /// Searches for active POI in camera frustrum and chooses the one with highest weight and closest to eyes. /// </summary> private void GetNewPOI() { Plane[] camPlanes = GeometryUtility.CalculateFrustumPlanes(headCam); List<EyePOI> activePOIsInCamera = new List<EyePOI>(); foreach(EyePOI poi in POIs) { if (poi.IsActive && GeometryUtility.TestPlanesAABB(camPlanes, poi.GetComponent<Collider>().bounds)) { activePOIsInCamera.Add(poi); } } if (activePOIsInCamera.Count == 0) { currentPOI = null; return; } int maxWeightId = activePOIsInCamera.Count - 1; float maxWeight = activePOIsInCamera[maxWeightId].Weight; for (int i = activePOIsInCamera.Count - 2; i >= 0; i--) { if (activePOIsInCamera[i].Weight < maxWeight) { activePOIsInCamera.RemoveAt(i); maxWeightId--; } else if (activePOIsInCamera[i].Weight > maxWeight) { activePOIsInCamera.RemoveAt(maxWeightId); maxWeightId = i; maxWeight = activePOIsInCamera[i].Weight; } } if (activePOIsInCamera.Count == 1) { currentPOI = activePOIsInCamera[0]; return; } EyePOI closest = activePOIsInCamera[0]; float minDistance = Vector3.Distance(transform.position, closest.transform.position); for (int i = 1; i < activePOIsInCamera.Count; i++) { float distance = Vector3.Distance(transform.position, activePOIsInCamera[i].transform.position); if (distance < minDistance) { closest = activePOIsInCamera[i]; minDistance = distance; } } currentPOI = closest; } private void TestCurrentPOI() { t += Time.deltaTime; Plane[] camPlanes = GeometryUtility.CalculateFrustumPlanes(headCam); if (t >= poiCheckTime || (currentPOI != null && !(currentPOI.IsActive && GeometryUtility.TestPlanesAABB(camPlanes, currentPOI.GetComponent<Collider>().bounds)))) { t = 0f; GetNewPOI(); if (currentPOI != null) eyeSim.target = currentPOI.transform; else eyeSim.target = null; } } }