using System; using System.Collections; using System.Collections.Generic; using System.IO; //using Mono.Cecil; using PixelCrushers.DialogueSystem; using UnityEngine; using UnityEngine.AI; using UnityEngine.UI; namespace Beyond { public class DirectioIndicator : MonoBehaviour { // Start is called before the first frame update private Renderer m_renderer; private Material m_material; public Color m_baseColor; public float m_minDistance = 5f; public float m_FadeDistance = 10f; public float m_refreshDistance = 2f; public float m_fadeTime = 1f; public float m_timeOut = 5f; // public bool m_showNewTarget = false; private NavMeshPath m_lastPath; private Vector3 m_lastPlayerPos; private Quaternion m_lastDirection; private Transform m_lastTarget; private float m_lastDistance; private float lerpRate = 1f; private float m_timer; private float m_refreshTimer = 0f; [SerializeField] private float m_distanceTh = 1f; [SerializeField] private float m_distanceUpdateTime = 2; public State m_state = State.IDLE; public bool m_showAllTheTime = false; public enum State { IDLE, FADE_IN, TARGET, TARGET_TIMEOUT, FADE_OUT, } void SetState(State s) { Debug.Log("State: " + s); switch (s) { case State.IDLE: m_lastDistance = Single.MaxValue; if (!m_showAllTheTime) m_renderer.enabled = false; break; case State.FADE_IN: m_renderer.enabled = true; m_material.color = Color.black; break; case State.FADE_OUT: break; case State.TARGET: //m_lastDistance = Single.MaxValue; if (m_showAllTheTime) { m_renderer.enabled = true; } break; case State.TARGET_TIMEOUT: break; } m_timer = 0f; m_state = s; } void Start() { m_renderer = GetComponentInChildren(); m_material = m_renderer.material; m_lastPath = new NavMeshPath(); SetState(State.IDLE); } void GetTargetPoint(Vector3 target) { var playerTrans = Player.Instance.transform; NavMesh.CalculatePath(playerTrans.position, target, NavMesh.AllAreas, m_lastPath); } bool ShouldRefreshPath(Transform target) { if (m_lastTarget != target) return true; Vector3 diff = m_lastPlayerPos - target.position; diff.y = 0f; m_refreshTimer += Time.deltaTime; bool result = diff.magnitude > m_refreshDistance || m_refreshTimer > 1f; if (result) { m_refreshTimer = 0f; } return result; } Vector3 GetDirection(Transform target, Vector3 playerPos, out float distance) { distance = Single.MaxValue; Vector3 targetPos = target.position; Vector3 diff = targetPos - playerPos; diff.y = 0f; distance = diff.magnitude; diff /= distance; if (distance < m_FadeDistance) { return diff; } if (ShouldRefreshPath(target)) { if (NavMesh.CalculatePath(playerPos, targetPos, NavMesh.AllAreas, m_lastPath)) { m_lastPlayerPos = playerPos; } else { return diff; } } if (m_lastPath == null || m_lastPath.corners.Length == 0) { return diff; } float pointDist = 0f; for (int id=0; id m_minDistance) { break; } } return diff; } // Update is called once per frame void Update() { if (Compass.Instance == null) { return; } var playerTrans = Player.Instance.transform; var target = Compass.Instance.FindClosestIndicator(playerTrans); float distance = Single.MaxValue; if (target != null) { var direction = GetDirection(target, playerTrans.position, out distance); if (distance > m_minDistance) { var dir = Quaternion.LookRotation(direction.normalized); transform.rotation = Quaternion.Slerp(m_lastDirection, dir, 1f - MathF.Pow(2, -Time.deltaTime * lerpRate)); m_lastDirection = transform.rotation; } if (target != m_lastTarget) m_lastDistance = distance; } float a = 0f; switch (m_state) { case State.IDLE: if (target != null) { if (m_lastDistance == Single.MaxValue) m_lastDistance = distance; if (GameStateManager.Instance.CurrentState == GameStateManager.State.COMBAT) return; if (m_showAllTheTime) { SetState(State.TARGET); break; } if (distance > m_FadeDistance && distance > m_lastDistance + m_distanceTh) { SetState(State.FADE_IN); } else if (m_timer > m_distanceUpdateTime) { m_timer = 0f; m_lastDistance = distance; } } break; case State.FADE_IN: a = (m_timer / m_fadeTime); if (a < 1) { m_material.color = m_baseColor * a; } else { m_material.color = m_baseColor; SetState(State.TARGET); } break; case State.TARGET: if (m_showAllTheTime) break; if (target != null) { if (distance < m_FadeDistance || (m_timer > m_timeOut && distance + m_distanceTh < m_lastDistance)) { SetState(State.FADE_OUT); m_lastDistance = distance; } } else { SetState(State.FADE_OUT); } break; case State.FADE_OUT: a = (m_timer / m_fadeTime); if (a < 1) { m_material.color = m_baseColor * (1-a); } else { m_material.color = Color.black; SetState(State.TARGET_TIMEOUT); /* if (!m_showNewTarget) { m_lastDistance = distance; } */ } break; case State.TARGET_TIMEOUT: if (m_timer > m_timeOut) { /* if (distance > m_lastDistance + m_distanceTh) { SetState(State.FADE_IN); } else { m_timer = 0f; m_lastDistance = distance; } */ SetState(State.IDLE); } break; } m_timer += Time.deltaTime; m_lastTarget = target; } private void OnDrawGizmos() { if (Player.Instance == null) return; var playerTrans = Player.Instance.transform; var target = Compass.Instance.FindClosestIndicator(playerTrans); float distance = 0f; if (target != null) { var direction = GetDirection(target, playerTrans.position, out distance); Gizmos.color = Color.red; Gizmos.DrawRay(playerTrans.position, direction*distance); Gizmos.color = Color.blue; if (m_lastPath != null && m_lastPath.corners.Length > 1) { for (int id = 0; id < m_lastPath.corners.Length-1; id++) { Gizmos.DrawLine(m_lastPath.corners[id], m_lastPath.corners[id+1]); } } } } } }