From e9ee111bce91cf5b8963554af7b589f9b89aa478 Mon Sep 17 00:00:00 2001 From: Thibault Pouch Date: Sun, 8 Mar 2026 20:20:24 +0100 Subject: [PATCH] feat(SlidingDoor): implement sliding door functionality with open/close events --- .../Code/Scripts/Interaction/SlidingDoor.cs | 114 ++++++++++++++++++ .../Scripts/Interaction/SlidingDoor.cs.meta | 2 + 2 files changed, 116 insertions(+) create mode 100644 Assets/Code/Scripts/Interaction/SlidingDoor.cs create mode 100644 Assets/Code/Scripts/Interaction/SlidingDoor.cs.meta diff --git a/Assets/Code/Scripts/Interaction/SlidingDoor.cs b/Assets/Code/Scripts/Interaction/SlidingDoor.cs new file mode 100644 index 0000000..d18d9b4 --- /dev/null +++ b/Assets/Code/Scripts/Interaction/SlidingDoor.cs @@ -0,0 +1,114 @@ +using UnityEngine; +using UnityEngine.Events; + +public class SlidingDoor : MonoBehaviour +{ + public enum SlideAxis { X, Y, Z } + public enum SlideDirection { Positive = 1, Negative = -1 } + + [Header("Slide Settings")] + [Tooltip("Local axis the door slides along.")] + [SerializeField] private SlideAxis axis = SlideAxis.X; + + [Tooltip("Which way along the axis the door opens.")] + [SerializeField] private SlideDirection direction = SlideDirection.Positive; + + [Tooltip("How far the door travels when fully open.")] + [SerializeField] private float slideDistance = 2f; + + [Tooltip("Movement speed (units per second).")] + [SerializeField] private float speed = 3f; + + [Header("Start State")] + [SerializeField] private bool startOpen = false; + + [Header("Events")] + public UnityEvent OnOpened; + public UnityEvent OnClosed; + + private Vector3 m_closedPos; + private Vector3 m_openPos; + private Vector3 m_targetPos; + private bool m_isOpen; + private bool m_eventFiredOpen; + private bool m_eventFiredClosed; + + private void Awake() + { + m_closedPos = transform.localPosition; + m_openPos = m_closedPos + GetSlideVector() * slideDistance; + + if (startOpen) + { + transform.localPosition = m_openPos; + m_isOpen = true; + } + + m_targetPos = m_isOpen ? m_openPos : m_closedPos; + } + + private void Update() + { + transform.localPosition = Vector3.MoveTowards( + transform.localPosition, m_targetPos, speed * Time.deltaTime); + + if (Vector3.Distance(transform.localPosition, m_openPos) < 0.01f && !m_eventFiredOpen) + { + m_eventFiredOpen = true; + m_eventFiredClosed = false; + OnOpened?.Invoke(); + } + else if (Vector3.Distance(transform.localPosition, m_closedPos) < 0.01f && !m_eventFiredClosed) + { + m_eventFiredClosed = true; + m_eventFiredOpen = false; + OnClosed?.Invoke(); + } + } + + public void Open() + { + m_isOpen = true; + m_targetPos = m_openPos; + } + + public void Close() + { + m_isOpen = false; + m_targetPos = m_closedPos; + } + + public void Toggle() + { + if (m_isOpen) + Close(); + else + Open(); + } + + private Vector3 GetSlideVector() + { + float sign = (float)direction; + return axis switch + { + SlideAxis.X => new Vector3(sign, 0f, 0f), + SlideAxis.Y => new Vector3(0f, sign, 0f), + SlideAxis.Z => new Vector3(0f, 0f, sign), + _ => Vector3.right, + }; + } + +#if UNITY_EDITOR + private void OnDrawGizmos() + { + Vector3 worldClosed = transform.parent != null + ? transform.parent.TransformPoint(transform.localPosition) + : transform.position; + + Vector3 slideVec = transform.TransformDirection(GetSlideVector()) * slideDistance; + Gizmos.color = Color.cyan; + Gizmos.DrawLine(worldClosed, worldClosed + slideVec); + Gizmos.DrawWireSphere(worldClosed + slideVec, 0.08f); + } +#endif +} diff --git a/Assets/Code/Scripts/Interaction/SlidingDoor.cs.meta b/Assets/Code/Scripts/Interaction/SlidingDoor.cs.meta new file mode 100644 index 0000000..a60983f --- /dev/null +++ b/Assets/Code/Scripts/Interaction/SlidingDoor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 0cc6c36a261296f4c82e315da147ba93 \ No newline at end of file