chore: Project Restructuring & Theatre

This commit is contained in:
Alexandre Coirier
2026-05-13 12:24:48 +02:00
parent 4070916c1f
commit e96d0bf6e6
2145 changed files with 20957 additions and 44792 deletions
@@ -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