GameLogic/ArenaDoor.cs
using System;
using System.Threading.Tasks;
using Sandbox;

public sealed class ArenaDoor : Component
{
	[Property, Group( "Références Prefab" ), Title( "Porte / Herse mobile" )] 
	public GameObject MovingHatch { get; set; }

	[Property, Group( "Références Prefab" ), Title( "Point de spawn (Empty)" )] 
	public GameObject SpawnPoint { get; set; }

	[Property, Group( "Mouvement" ), Title( "Décalage position basse" )] 
	public Vector3 LoweredOffset { get; set; } = new Vector3( 0, 0, -180f );

	[Property, Group( "Mouvement" ), Title( "Vitesse d'abaissement" )] 
	public float MoveSpeed { get; set; } = 4.0f;

	[Property, Group( "Audio" )] 
	public SoundEvent DoorMoveSound { get; set; }

	// Raccourcis pour que le spawner n'ait pas à vérifier si SpawnPoint est null
	public Vector3 SpawnPosition => SpawnPoint?.WorldPosition ?? WorldPosition;
	public Rotation SpawnRotation => SpawnPoint?.WorldRotation ?? WorldRotation;

	public bool IsOpen => _isOpen;

	private Vector3 _initialLocalPos;
	private Vector3 _targetLocalPos;
	private bool _isOpen = false;

	protected override void OnStart()
	{
		// Sécurité si non assigné dans l'inspecteur
		if ( MovingHatch == null ) 
			MovingHatch = GameObject;

		_initialLocalPos = MovingHatch.LocalPosition;
		_targetLocalPos = _initialLocalPos;
	}

	protected override void OnUpdate()
	{
		if ( MovingHatch == null ) return;

		if ( MovingHatch.LocalPosition.Distance( _targetLocalPos ) > 0.5f )
		{
			MovingHatch.LocalPosition = Vector3.Lerp( MovingHatch.LocalPosition, _targetLocalPos, Time.Delta * MoveSpeed );
		}
	}

	public async Task OpenDoorAsync( float autoCloseAfterSeconds = 0f )
	{
		_isOpen = true;
		_targetLocalPos = _initialLocalPos + LoweredOffset;

		if ( DoorMoveSound != null ) 
			Sound.Play( DoorMoveSound, WorldPosition );

		if ( autoCloseAfterSeconds > 0f )
		{
			await Task.Delay( (int)(autoCloseAfterSeconds * 1000f) );
			CloseDoor();
		}
	}

	public void CloseDoor()
	{
		_isOpen = false;
		_targetLocalPos = _initialLocalPos;

		if ( DoorMoveSound != null ) 
			Sound.Play( DoorMoveSound, WorldPosition );
	}
}