using System.Collections; using System.Collections.Generic; using UnityEngine; namespace BNG { public class DoorHelper : MonoBehaviour { public AudioClip DoorOpenSound; public AudioClip DoorCloseSound; /// /// Does the handle need to be turned in order to open the door from the closed position? /// [Tooltip("Does the handle need to be turned in order to open the door from the closed position?")] public bool RequireHandleTurnToOpen = false; /// /// If RequireHandleTurnToOpen and the handle has not fully opened then the door will be kinematic / immovable /// bool handleLocked = false; /// /// This transform is used to determine how many degrees have been turned. Required if RequireHandleTurnToOpen is true /// public Transform HandleFollower; public float DegreesTurned; /// /// How many degrees the handle must turn in order for the latch to be open /// public float DegreesTurnToOpen = 10f; /// /// Rotate this transform with Handle Rotation /// public Transform DoorLockTransform; float initialLockPosition; HingeJoint hinge; Rigidbody rigid; bool playedOpenSound = false; // Need to open door up a certain amount before considering playing a close sound afterwards bool readyToPlayCloseSound = false; public float AngularVelocitySnapDoor = 0.2f; public float angle; public float AngularVelocity = 0.2f; [Tooltip("If true the door will not respond to user input")] public bool DoorIsLocked = false; public float lockPos; // public string DebugText; // Cache for GC Vector3 currentRotation; float moveLockAmount, rotateAngles, ratio; void Start() { hinge = GetComponent(); rigid = GetComponent(); if (DoorLockTransform) { initialLockPosition = DoorLockTransform.transform.localPosition.x; } } void Update() { // Read Angular Velocity used for snapping door shut AngularVelocity = rigid.angularVelocity.magnitude; // DebugText = rigid.angularVelocity.x + ", " + rigid.angularVelocity.y + ", " + rigid.angularVelocity.z; // Get the modified angle of of the lever. Use this to get percentage based on Min and Max angles. currentRotation = transform.localEulerAngles; angle = Mathf.Floor(currentRotation.y); if(angle >= 180) { angle -= 180; } else { angle = 180 - angle; } // Play Open Sound if (angle > 10) { if(!playedOpenSound) { VRUtils.Instance.PlaySpatialClipAt(DoorOpenSound, transform.position, 1f, 1f); playedOpenSound = true; } } if(angle > 30) { readyToPlayCloseSound = true; } // Reset Open Sound if(angle < 2 && playedOpenSound) { playedOpenSound = false; } // Should we snap the door closed? if (angle < 1 && AngularVelocity <= AngularVelocitySnapDoor) { rigid.angularVelocity = Vector3.zero; } // Play Close Sound if (readyToPlayCloseSound && angle < 2) { VRUtils.Instance.PlaySpatialClipAt(DoorCloseSound, transform.position, 1f, 1f); readyToPlayCloseSound = false; } // Calculate Handle if available if (HandleFollower) { DegreesTurned = Mathf.Abs(HandleFollower.localEulerAngles.y - 270); } if(DoorLockTransform) { // 45 Degrees = Fully Open moveLockAmount = 0.025f; rotateAngles = 55; ratio = rotateAngles / (rotateAngles - Mathf.Clamp(DegreesTurned, 0, rotateAngles)); lockPos = initialLockPosition - (ratio * moveLockAmount) + moveLockAmount; lockPos = Mathf.Clamp(lockPos, initialLockPosition - moveLockAmount, initialLockPosition); DoorLockTransform.transform.localPosition = new Vector3(lockPos, DoorLockTransform.transform.localPosition.y, DoorLockTransform.transform.localPosition.z); } // Set Lock Status if(RequireHandleTurnToOpen) { handleLocked = DegreesTurned < DegreesTurnToOpen; } // Lock Door in place if closed and requires handle to be turned if(angle < 0.02f && (handleLocked || DoorIsLocked)) { // Check on detection mode if (rigid.collisionDetectionMode == CollisionDetectionMode.Continuous || rigid.collisionDetectionMode == CollisionDetectionMode.ContinuousDynamic) { rigid.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative; } rigid.isKinematic = true; } else { // Check on detection mode if (rigid.collisionDetectionMode == CollisionDetectionMode.ContinuousSpeculative) { rigid.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; } rigid.isKinematic = false; } } } }