chore: Project Restructuring & Theatre
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using System;
|
||||
|
||||
namespace Unheimlich.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic reusable trigger component. Handles the once-flag, optional delay,
|
||||
/// OnStart/OnEnable auto-fire, and exposes a UnityEvent + C# event for downstream systems.
|
||||
/// Compose this on any GameObject that needs to fire a game event from multiple sources.
|
||||
/// </summary>
|
||||
public class GameEventTrigger : MonoBehaviour
|
||||
{
|
||||
[Header("Auto-fire")]
|
||||
[Tooltip("Fire automatically on Start()")]
|
||||
[SerializeField] private bool _fireOnStart;
|
||||
|
||||
[Tooltip("Fire automatically when this GameObject is enabled")]
|
||||
[SerializeField] private bool _fireOnEnable;
|
||||
|
||||
[Header("Behaviour")]
|
||||
[Tooltip("Delay in seconds before the event fires")]
|
||||
[SerializeField] private float _delay;
|
||||
|
||||
[Tooltip("Prevent this trigger from firing more than once per Play Mode session")]
|
||||
[SerializeField] private bool _fireOnlyOnce = true;
|
||||
|
||||
[Header("Callbacks")]
|
||||
[Tooltip("Called when the trigger fires (after the optional delay)")]
|
||||
[SerializeField] private UnityEvent _onTriggered;
|
||||
|
||||
/// <summary>C# event raised when the trigger fires. Useful for code-only listeners.</summary>
|
||||
public event Action OnTriggered;
|
||||
|
||||
private bool _hasFired;
|
||||
|
||||
private bool _startFired;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
// Reset per-session so the trigger can fire again when entering Play Mode
|
||||
// without Domain Reload.
|
||||
_hasFired = false;
|
||||
_startFired = false;
|
||||
|
||||
// NOTE: _fireOnEnable is intentionally deferred to Start() so all Singleton
|
||||
// Awake() calls across the scene complete before listeners access managers.
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (_startFired)
|
||||
return;
|
||||
|
||||
_startFired = true;
|
||||
|
||||
// Fire once even if both flags are ticked
|
||||
if (_fireOnStart || _fireOnEnable)
|
||||
Fire();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires the trigger. Respects the once-flag and optional delay.
|
||||
/// Call this from any external script, UnityEvent, or animation event.
|
||||
/// </summary>
|
||||
public void Fire()
|
||||
{
|
||||
if (_fireOnlyOnce && _hasFired)
|
||||
return;
|
||||
|
||||
if (_delay > 0f)
|
||||
Invoke(nameof(ExecuteTrigger), _delay);
|
||||
else
|
||||
ExecuteTrigger();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the fired state so the trigger can fire again.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
_hasFired = false;
|
||||
CancelInvoke(nameof(ExecuteTrigger));
|
||||
}
|
||||
|
||||
private void ExecuteTrigger()
|
||||
{
|
||||
if (_fireOnlyOnce && _hasFired)
|
||||
return;
|
||||
|
||||
_hasFired = true;
|
||||
_onTriggered?.Invoke();
|
||||
OnTriggered?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 358c75d041ea30a4ab85380893077e70
|
||||
@@ -0,0 +1,56 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unheimlich.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Central event system for player actions.
|
||||
/// Decouples player components from each other.
|
||||
/// </summary>
|
||||
public static class PlayerEvents
|
||||
{
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
private static void ResetAll()
|
||||
{
|
||||
OnJump = null;
|
||||
OnTeleport = null;
|
||||
OnCameraShake = null;
|
||||
OnDiapasonEquip = null;
|
||||
OnDiapasonUnequip = null;
|
||||
OnDiapasonTap = null;
|
||||
OnEnterDialogue = null;
|
||||
OnExitDialogue = null;
|
||||
OnEnterListening = null;
|
||||
OnExitListening = null;
|
||||
}
|
||||
|
||||
// Movement events
|
||||
public static event System.Action OnJump;
|
||||
public static event System.Action<Vector3, Quaternion> OnTeleport;
|
||||
|
||||
// Camera events
|
||||
public static event System.Action<float> OnCameraShake;
|
||||
|
||||
// Diapason events
|
||||
public static event System.Action OnDiapasonEquip;
|
||||
public static event System.Action OnDiapasonUnequip;
|
||||
public static event System.Action OnDiapasonTap;
|
||||
|
||||
// Context events
|
||||
public static event System.Action OnEnterDialogue;
|
||||
public static event System.Action OnExitDialogue;
|
||||
public static event System.Action OnEnterListening;
|
||||
public static event System.Action OnExitListening;
|
||||
|
||||
// Trigger methods
|
||||
public static void TriggerJump() => OnJump?.Invoke();
|
||||
public static void TriggerTeleport(Vector3 position, Quaternion rotation) => OnTeleport?.Invoke(position, rotation);
|
||||
public static void TriggerCameraShake(float intensity) => OnCameraShake?.Invoke(intensity);
|
||||
public static void TriggerDiapasonEquip() => OnDiapasonEquip?.Invoke();
|
||||
public static void TriggerDiapasonUnequip() => OnDiapasonUnequip?.Invoke();
|
||||
public static void TriggerDiapasonTap() => OnDiapasonTap?.Invoke();
|
||||
public static void TriggerEnterDialogue() => OnEnterDialogue?.Invoke();
|
||||
public static void TriggerExitDialogue() => OnExitDialogue?.Invoke();
|
||||
public static void TriggerEnterListening() => OnEnterListening?.Invoke();
|
||||
public static void TriggerExitListening() => OnExitListening?.Invoke();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 82279ebe597d0b84eb1f7ab31139587d
|
||||
@@ -0,0 +1,87 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace Unheimlich.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract base for any physics-trigger zone that fires when the player enters.
|
||||
/// Handles collider validation, player tag check, once-flag, retrigger, and Gizmos.
|
||||
/// Subclasses implement OnPlayerEntered() and optionally OnPlayerExited().
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Collider))]
|
||||
public abstract class TriggerZoneBase : MonoBehaviour
|
||||
{
|
||||
[Header("Zone Settings")]
|
||||
[SerializeField] private string _playerTag = "Player";
|
||||
|
||||
[Header("Gizmo")]
|
||||
[SerializeField] private Color _gizmoColor = new Color(0.8f, 0.5f, 0.0f, 0.35f);
|
||||
|
||||
protected bool HasFired { get; private set; }
|
||||
|
||||
private Collider _collider;
|
||||
|
||||
/// <summary>
|
||||
/// Override to control whether the zone can fire again after the first trigger.
|
||||
/// Default is false (fires once). Subclasses expose their own retrigger field and return it here.
|
||||
/// </summary>
|
||||
protected virtual bool IsRetriggerable => false;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
_collider = GetComponent<Collider>();
|
||||
|
||||
if (!_collider.isTrigger)
|
||||
{
|
||||
Debug.LogWarning($"[{GetType().Name}] Collider on '{gameObject.name}' is not a trigger. Forcing it.", this);
|
||||
_collider.isTrigger = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (!other.CompareTag(_playerTag))
|
||||
return;
|
||||
|
||||
if (HasFired && !IsRetriggerable)
|
||||
return;
|
||||
|
||||
HasFired = true;
|
||||
OnPlayerEntered(other);
|
||||
}
|
||||
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (!other.CompareTag(_playerTag))
|
||||
return;
|
||||
|
||||
OnPlayerExited(other);
|
||||
}
|
||||
|
||||
/// <summary>Called when the player enters the trigger zone.</summary>
|
||||
protected abstract void OnPlayerEntered(Collider playerCollider);
|
||||
|
||||
/// <summary>Called when the player exits the trigger zone. Override if needed.</summary>
|
||||
protected virtual void OnPlayerExited(Collider playerCollider) { }
|
||||
|
||||
/// <summary>Resets the fired state so the zone can fire again.</summary>
|
||||
public void ResetZone()
|
||||
{
|
||||
HasFired = false;
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
Gizmos.color = _gizmoColor;
|
||||
Gizmos.matrix = transform.localToWorldMatrix;
|
||||
|
||||
Collider col = GetComponent<Collider>();
|
||||
if (col is BoxCollider box)
|
||||
Gizmos.DrawCube(box.center, box.size);
|
||||
else if (col is SphereCollider sphere)
|
||||
Gizmos.DrawSphere(sphere.center, sphere.radius);
|
||||
else if (col is CapsuleCollider capsule)
|
||||
Gizmos.DrawWireSphere(capsule.center, capsule.radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9fae9f4c26344344e93baeaee0281284
|
||||
Reference in New Issue
Block a user