Last active
October 7, 2020 09:06
-
-
Save HolyFot/467623b4a55b2c4e82b1457052067107 to your computer and use it in GitHub Desktop.
Unity Door Script with Pivot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Perfect Door/Chest/DrawBridge Animation Script | |
//Author: HolyFot | |
//License: CC0 | |
using UnityEngine; | |
using System.Collections; | |
public class Door : MonoBehaviour | |
{ | |
[SerializeField] public GameObject doorObj; | |
[SerializeField] public GameObject pivot; | |
[SerializeField] public bool isBackwards = false; | |
[SerializeField] private float startY = 0f; | |
[SerializeField] public float openSpeed = 100f; | |
[SerializeField] public float targetAngle = 90f; | |
[SerializeField] public AnimationCurve speedCurve = new AnimationCurve(new Keyframe(0, 0.3f), new Keyframe(0.1f, 0.3f), new Keyframe(0.5f, 1f), new Keyframe(0.9f, 0.3f), new Keyframe(1f, 0.3f)); | |
[SerializeField] public DoorOpenMethod doorOpenType; | |
[SerializeField] AudioClip openSound; | |
[SerializeField] AudioClip closeSound; | |
[SerializeField] AudioSource audioSource; | |
[SerializeField] float playCloseSoundAtPercent = 0.9f; | |
public bool isOpen = false; | |
public bool isTesting = false; | |
private bool isOpening = false; | |
private bool isClosing = false; | |
private bool playedCloseSound = false; | |
private Vector3 startPos; | |
void Awake() | |
{ | |
if (doorObj == null) | |
{ | |
Debug.LogWarning("Door Object not set!"); | |
return; | |
} | |
if (pivot == null) | |
{ | |
Debug.LogWarning("Pivot Object not set!"); | |
return; | |
} | |
if (audioSource == null) | |
{ | |
audioSource = gameObject.AddComponent<AudioSource>(); | |
} | |
if (doorOpenType == DoorOpenMethod.X_Mode) | |
{ | |
startY = doorObj.transform.localRotation.eulerAngles.x; | |
if (isTesting) | |
Debug.Log("start X: " + startY.ToString()); | |
} | |
else if (doorOpenType == DoorOpenMethod.Z_Mode) | |
{ | |
startY = doorObj.transform.localRotation.eulerAngles.z; | |
if (isTesting) | |
Debug.Log("start Z: " + startY.ToString()); | |
} | |
else if (doorOpenType == DoorOpenMethod.Y_Mode) | |
{ | |
startY = doorObj.transform.localRotation.eulerAngles.y; | |
if (isTesting) | |
Debug.Log("start Y: " + startY.ToString()); | |
} | |
startPos = doorObj.transform.localPosition; | |
} | |
void Update() | |
{ | |
if (isTesting) | |
{ | |
if (Input.GetKeyDown(KeyCode.F)) | |
{ | |
ToggleDoor(); | |
} | |
} | |
} | |
public void ToggleDoor() | |
{ | |
if (isOpen) | |
CloseDoor(); | |
else | |
OpenDoor(); | |
} | |
public void OpenDoor() | |
{ | |
StopDoorAnims(); | |
isOpening = true; | |
if (!isBackwards) | |
StartCoroutine("ForwardDoor2"); | |
else | |
StartCoroutine("ReverseDoor2"); | |
if (openSound != null) | |
audioSource.PlayOneShot(openSound); | |
isOpen = true; | |
} | |
public void CloseDoor() | |
{ | |
StopDoorAnims(); | |
playedCloseSound = false; | |
isClosing = true; | |
if (!isBackwards) | |
StartCoroutine("ReverseDoor2"); | |
else | |
StartCoroutine("ForwardDoor2"); | |
isOpen = false; | |
} | |
public void StopDoorAnims() | |
{ | |
StopCoroutine("ForwardDoor2"); | |
StopCoroutine("ReverseDoor2"); | |
} | |
private IEnumerator ForwardDoor2() | |
{ | |
if (doorOpenType == DoorOpenMethod.X_Mode) | |
{ | |
while (doorObj.transform.localRotation.eulerAngles.x < startY + targetAngle - 1f) | |
{ | |
float calcSpeed = CalcSpeedRamp2(doorObj.transform.localRotation.eulerAngles.x, startY, startY + targetAngle); | |
doorObj.transform.RotateAround(pivot.transform.position, Vector3.right, calcSpeed * Time.deltaTime); | |
//if (isTesting) | |
//Debug.Log("Opening.. X: " + doorObj.transform.localRotation.eulerAngles.x.ToString("0.000")); | |
isOpening = true; | |
yield return null; | |
} | |
doorObj.transform.localEulerAngles = new Vector3(targetAngle, doorObj.transform.localEulerAngles.y, doorObj.transform.localEulerAngles.z); | |
} | |
else if (doorOpenType == DoorOpenMethod.Z_Mode) | |
{ | |
while (doorObj.transform.localRotation.eulerAngles.z < startY + targetAngle - 1f) | |
{ | |
float calcSpeed = CalcSpeedRamp2(doorObj.transform.localRotation.eulerAngles.z, startY, startY + targetAngle); | |
doorObj.transform.RotateAround(pivot.transform.position, Vector3.up, calcSpeed * Time.deltaTime); | |
//if (isTesting) | |
//Debug.Log("Opening.. Z: " + doorObj.transform.localRotation.eulerAngles.z.ToString("0.000")); | |
isOpening = true; | |
yield return null; | |
} | |
doorObj.transform.localRotation = Quaternion.Euler(doorObj.transform.localRotation.eulerAngles.x, doorObj.transform.localRotation.eulerAngles.y, targetAngle); | |
} | |
else if (doorOpenType == DoorOpenMethod.Y_Mode) //Rotate around Y | |
{ | |
while (doorObj.transform.localRotation.eulerAngles.y < startY + targetAngle - 1f) | |
{ | |
float calcSpeed = CalcSpeedRamp2(doorObj.transform.localRotation.eulerAngles.y, startY, startY + targetAngle); | |
doorObj.transform.RotateAround(pivot.transform.position, Vector3.left, calcSpeed * Time.deltaTime); | |
//if (isTesting) | |
//Debug.Log("Opening.. Y: " + doorObj.transform.localRotation.eulerAngles.y.ToString("0.000")); | |
isOpening = true; | |
yield return null; | |
} | |
doorObj.transform.localEulerAngles = new Vector3(doorObj.transform.localEulerAngles.x, targetAngle, doorObj.transform.localEulerAngles.z); | |
} | |
isOpening = false; | |
} | |
private IEnumerator ReverseDoor2() | |
{ | |
if (doorOpenType == DoorOpenMethod.X_Mode) | |
{ | |
while (doorObj.transform.localRotation.eulerAngles.x > startY && doorObj.transform.localRotation.eulerAngles.x < targetAngle + 1f) | |
{ | |
float calcSpeed = CalcSpeedRamp2(doorObj.transform.localRotation.eulerAngles.x, startY, startY + targetAngle); | |
doorObj.transform.RotateAround(pivot.transform.position, Vector3.right, -1 * calcSpeed * Time.deltaTime); | |
//if (isTesting) | |
//Debug.Log("Close door X: " + doorObj.transform.localRotation.eulerAngles.x.ToString("0.000")); | |
isClosing = true; | |
yield return null; | |
} | |
doorObj.transform.localEulerAngles = new Vector3(startY, doorObj.transform.localEulerAngles.y, doorObj.transform.localEulerAngles.z); | |
doorObj.transform.localPosition = startPos; | |
} | |
else if (doorOpenType == DoorOpenMethod.Z_Mode) | |
{ | |
while (doorObj.transform.localRotation.eulerAngles.z > startY && doorObj.transform.localRotation.eulerAngles.z < targetAngle + 1f) | |
{ | |
float calcSpeed = CalcSpeedRamp2(doorObj.transform.localRotation.eulerAngles.z, startY, startY + targetAngle); | |
doorObj.transform.RotateAround(pivot.transform.position, Vector3.up, -1 * calcSpeed * Time.deltaTime); | |
//if (isTesting) | |
//Debug.Log("Close door Z: " + doorObj.transform.localRotation.eulerAngles.z.ToString("0.000")); | |
isClosing = true; | |
yield return null; | |
} | |
doorObj.transform.localEulerAngles = new Vector3(doorObj.transform.localEulerAngles.x, doorObj.transform.localEulerAngles.y, startY); | |
doorObj.transform.localPosition = startPos; | |
} | |
else if (doorOpenType == DoorOpenMethod.Y_Mode) | |
{ | |
while (doorObj.transform.localRotation.eulerAngles.y > startY && doorObj.transform.localRotation.eulerAngles.y < targetAngle + 1f) | |
{ | |
float calcSpeed = CalcSpeedRamp2(doorObj.transform.localRotation.eulerAngles.y, startY, startY + targetAngle); | |
doorObj.transform.RotateAround(pivot.transform.position, Vector3.left, -1 * calcSpeed * Time.deltaTime); | |
//if (isTesting) | |
//Debug.Log("Close door Y: " + doorObj.transform.localRotation.eulerAngles.y.ToString("0.000")); | |
isClosing = true; | |
yield return null; | |
} | |
doorObj.transform.eulerAngles = new Vector3(doorObj.transform.rotation.x, startY, doorObj.transform.rotation.z); | |
doorObj.transform.localPosition = startPos; | |
} | |
isClosing = false; | |
} | |
private float CalcSpeedRamp(float value, float min, float max) | |
{ | |
float curr = 1f; | |
float percent = Mathf.Abs(value) / Mathf.Abs(max - min); | |
if (percent < 0.3f) //30% speed up | |
curr = percent * 10f * openSpeed; | |
else if (percent > 0.7f) //70% slow down | |
curr = (1f - percent) * 10f * openSpeed; //0.3, 0.2, 0.15, 0.1, 0 | |
else | |
curr = openSpeed; //Regular Speed | |
if (curr <= 5f) //1% speed safety | |
curr = openSpeed * 0.01f; | |
return curr; | |
} | |
private float CalcSpeedRamp2(float value, float min, float max) | |
{ | |
float curr = 1f; | |
float percent = Mathf.Abs(value) / Mathf.Abs(max - min); | |
curr = openSpeed * speedCurve.Evaluate(percent); | |
if (isClosing) | |
{ | |
if (!playedCloseSound && 1f-percent >= playCloseSoundAtPercent) | |
{ | |
if (closeSound != null) | |
audioSource.PlayOneShot(closeSound); | |
if (isTesting) | |
Debug.Log("Play Close: Curr Precent: " + percent.ToString("0.000")); | |
playedCloseSound = true; | |
} | |
} | |
return curr; | |
} | |
} | |
public enum DoorOpenMethod | |
{ | |
Z_Mode, | |
Y_Mode, | |
X_Mode | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment