feat(SlidingDoor): implement sliding door functionality with open/close events
This commit is contained in:
114
Assets/Code/Scripts/Interaction/SlidingDoor.cs
Normal file
114
Assets/Code/Scripts/Interaction/SlidingDoor.cs
Normal file
@@ -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
|
||||
}
|
||||
2
Assets/Code/Scripts/Interaction/SlidingDoor.cs.meta
Normal file
2
Assets/Code/Scripts/Interaction/SlidingDoor.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0cc6c36a261296f4c82e315da147ba93
|
||||
Reference in New Issue
Block a user