using System; using System.Collections.Generic; using UnityEngine; using Drawing; using Sirenix.OdinInspector; using Sirenix.Serialization; using Unity.Mathematics; [Serializable] public class EnvironmentObserver{ // TODO: Clean this ugly shit up. Custom inspector with Odin plz. public string label; public bool drawLabel; enum LabelDrawingLocation{ PlayerOffset, HitLocation, IntersectingLength, } enum CastType{ Ray, Box, Sphere, BoxCast, SphereCast } [ShowInInspector, SerializeField] CastType castType; [SerializeReference] public List children; public Vector3 labelLocationOffset; public Vector3 labelRotationOffset; [ShowInInspector, SerializeField] LabelDrawingLocation labelLocation; public bool active; // Parameters public float length; public float width; public Vector3 size; public Vector3 rotation; public Vector3 start; public Vector3 direction; public bool useLayerMask; public LayerMask ignoreMask; public RaycastHit hit; private Collider[] overlapHits; public bool Evaluate(GameObject player){ if (active) { ignoreMask -= player.layer; Vector3 relativeStart = player.transform.position + start; Vector3 startOffsetFromRotation = player.transform.position + player.transform.rotation * (start) ; float halfExtents = width / 2f; // NOTE: I had a ref for a RaycastHit here that would correspond to hit but idk if it's needed. switch (castType) { case CastType.Ray: Physics.Raycast(relativeStart, player.transform.rotation * direction, out hit, length, ignoreMask); break; case CastType.Box: if (Physics.OverlapBox(startOffsetFromRotation, size / 2f, player.transform.rotation * Quaternion.Euler(rotation), ignoreMask).Length > 0) { return true; }; break; case CastType.Sphere: break; case CastType.BoxCast: break; case CastType.SphereCast: break; } if (hit.transform != null) { return true; } } hit = default; return false; } public void DrawObserverGizmo(GameObject player){ Vector3 relativeStart = player.transform.position + start; Vector3 startOffsetFromRotation = player.transform.position + player.transform.rotation * (start) ; Color gizmoColor = Evaluate(player) ? Color.green : Color.red; gizmoColor = active ? gizmoColor : Color.gray; using (Draw.ingame.WithColor(gizmoColor)){ Vector3 labelStartPos = Vector3.zero; switch (labelLocation) { case LabelDrawingLocation.PlayerOffset: labelStartPos = player.transform.position + labelLocationOffset; break; case LabelDrawingLocation.IntersectingLength: labelStartPos = (relativeStart + (player.transform.rotation * direction * length) / 2f ) + labelLocationOffset; break; case LabelDrawingLocation.HitLocation:{ if (hit.transform != null) { labelStartPos = hit.point + labelLocationOffset; } break; } } switch (castType) { case CastType.Ray: Draw.ingame.Line(relativeStart, relativeStart + (player.transform.rotation * direction.normalized) * length); break; case CastType.Box: Draw.ingame.WireBox(startOffsetFromRotation, player.transform.rotation * Quaternion.Euler(rotation), size); break; case CastType.Sphere: break; case CastType.BoxCast: break; default: throw new ArgumentOutOfRangeException(); } Draw.ingame.Label3D( labelStartPos, player.transform.rotation * Quaternion.Euler(labelRotationOffset), hit.collider == null ? "" : hit.collider.name, .5f, LabelAlignment.Center, Color.black ); } } } public class PlayerEnvironmentManager : MonoBehaviour{ [OdinSerialize] public List observers; void Start(){ CheckDuplicateLabels(observers); } // TODO: Not working. void CheckDuplicateLabels(List sourceList){ foreach (EnvironmentObserver sourceObserver in observers) { foreach (EnvironmentObserver observer in sourceList) { if (sourceObserver == observer) { continue; } if (sourceObserver.label == observer.label) { Debug.LogError($"Duplicate label found in observer: {observer.label} is in use multiple times"); } if (observer.children != null && observer.children.Count > 0) { CheckDuplicateLabels(observer.children); } } } } public bool EvaluateFromString(string searchLabel, List observerList = null){ List listToUse = observers; if (observerList != null) { listToUse = observerList; } foreach (EnvironmentObserver observer in listToUse) { if (observer.label == searchLabel) { return observer.Evaluate(gameObject); } if (observer.children != null && observer.children.Count > 0) { foreach (EnvironmentObserver childObserver in observer.children) { EvaluateFromString(searchLabel, childObserver.children); } } } return false; } public EnvironmentObserver FindObserverFromString(string searchLabel, List observerList = null){ List listToUse = observers; if (observerList != null) { listToUse = observerList; } foreach (EnvironmentObserver observer in listToUse) { if (observer.label == searchLabel) { return observer; } if (observer.children != null && observer.children.Count > 0) { foreach (EnvironmentObserver childObserver in observer.children) { FindObserverFromString(searchLabel, childObserver.children); } } } return null; } void Update(){ Debug.Log(EvaluateFromString("gamedev")); } void LateUpdate(){ foreach (EnvironmentObserver observer in observers) { observer.DrawObserverGizmo(gameObject); if (observer.children != null && observer.children.Count > 0) { foreach (EnvironmentObserver childObserver in observer.children) { childObserver.DrawObserverGizmo(gameObject); } } } } }