Files
beyond/Assets/Scripts/Door/DoorSystem.cs
2026-02-04 04:35:23 +01:00

156 lines
4.7 KiB
C#

using UnityEngine;
using System.Collections.Generic;
[RequireComponent(typeof(AudioSource))]
public class DoorSystem : MonoBehaviour
{
public enum MotionType { Rotate, Slide }
[Header("G³ówne Ustawienia")]
public MotionType motionType = MotionType.Rotate;
public bool isAutomatic = true; // Czy maj¹ siê same otwieraæ?
public string playerTag = "Player";
[Header("Skrzyd³a Drzwi")]
public Transform doorWing1;
public Transform doorWing2;
public bool invertWing2 = true;
[Header("Parametry Ruchu")]
public Vector3 actionAxis = Vector3.up;
public float amount = 90f; // K¹t/Dystans bazowy
public float springStrength = 10f;
public float springDamper = 4f;
[Header("Audio")]
public AudioClip openSound;
public AudioClip closeSound;
public AudioClip slamSound;
private float currentValue = 0f;
private float targetValue = 0f;
private float velocity = 0f;
private float currentDirectionMult = 1f; // 1 lub -1 w zale¿noœci od strony
private Vector3 wing1StartPos, wing2StartPos;
private Quaternion wing1StartRot, wing2StartRot;
private AudioSource audioSource;
private bool playedSlam = true;
private bool isOpen = false;
// Lista obiektów wewn¹trz triggera (Safety System)
private List<Collider> objectsInTrigger = new List<Collider>();
void Start()
{
audioSource = GetComponent<AudioSource>();
if (doorWing1) { wing1StartPos = doorWing1.localPosition; wing1StartRot = doorWing1.localRotation; }
if (doorWing2) { wing2StartPos = doorWing2.localPosition; wing2StartRot = doorWing2.localRotation; }
}
// Wywo³ywane przez Raycast lub przycisk interakcji
public void Interact(Vector3 interactorPosition)
{
if (isOpen)
{
TryClose();
}
else
{
SetDirection(interactorPosition);
Open();
}
}
private void Open()
{
isOpen = true;
targetValue = amount * currentDirectionMult;
playedSlam = false;
if (openSound) audioSource.PlayOneShot(openSound);
}
private void TryClose()
{
// Safety check: nie zamykaj, jeœli ktoœ stoi w przejœciu
if (objectsInTrigger.Count > 0) return;
isOpen = false;
targetValue = 0f;
if (closeSound) audioSource.PlayOneShot(closeSound);
}
// Sprawdza, z której strony jest gracz wzglêdem osi Z (Forward) drzwi
private void SetDirection(Vector3 position)
{
Vector3 directionToPlayer = position - transform.position;
float dot = Vector3.Dot(transform.forward, directionToPlayer);
// Jeœli gracz jest z przodu (dot > 0), drzwi otwieraj¹ siê do ty³u (-1)
// Jeœli gracz jest z ty³u (dot < 0), drzwi otwieraj¹ siê do przodu (1)
currentDirectionMult = (dot > 0) ? -1f : 1f;
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag(playerTag))
{
if (!objectsInTrigger.Contains(other)) objectsInTrigger.Add(other);
if (isAutomatic && !isOpen)
{
SetDirection(other.transform.position);
Open();
}
}
}
private void OnTriggerExit(Collider other)
{
if (other.CompareTag(playerTag))
{
if (objectsInTrigger.Contains(other)) objectsInTrigger.Remove(other);
if (isAutomatic && isOpen)
{
TryClose();
}
}
}
void Update()
{
float dt = Time.deltaTime;
float force = (targetValue - currentValue) * springStrength;
float damping = velocity * springDamper;
float acceleration = force - damping;
velocity += acceleration * dt;
currentValue += velocity * dt;
if (!isOpen && !playedSlam && Mathf.Abs(currentValue) < 0.05f)
{
if (slamSound) audioSource.PlayOneShot(slamSound);
playedSlam = true;
currentValue = 0; // Hard stop
velocity = 0;
}
UpdateDoorVisuals(currentValue);
}
void UpdateDoorVisuals(float val)
{
if (doorWing1) ApplyTransform(doorWing1, val, wing1StartPos, wing1StartRot, false);
if (doorWing2) ApplyTransform(doorWing2, val, wing2StartPos, wing2StartRot, invertWing2);
}
void ApplyTransform(Transform target, float val, Vector3 startPos, Quaternion startRot, bool invert)
{
float finalVal = invert ? -val : val;
if (motionType == MotionType.Rotate)
target.localRotation = startRot * Quaternion.AngleAxis(finalVal, actionAxis);
else
target.localPosition = startPos + (actionAxis.normalized * finalVal);
}
}