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 objectsInTrigger = new List(); void Start() { audioSource = GetComponent(); 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); } }