Files
2025-05-29 22:31:40 +03:00

478 lines
14 KiB
C#

/*
* Original Code by: NOT_lonely (http://not-lonely.com/)
* Code Revision by: sluice (www.sluicegaming.com)
*
*/
using System;
using UnityEngine;
using UnityEngine.UI;
namespace NOTLonely_Door
{
public class DoorScript : MonoBehaviour
{
private Transform[] Childs;
private Transform Joint01;
private Transform Joint02;
public enum OpenStyle
{
BUTTON,
AUTOMATIC
}
[Serializable]
public class DoorControls
{
public float openingSpeed = 1;
public float closingSpeed = 1.3f;
[Range(0, 1)]
public float closeStartFrom = 0.6f;
public OpenStyle openMethod; //Open by button or automatically?
public KeyCode openButton = KeyCode.E; //Button on the keyboard to open the door
public bool autoClose = false; //Automatically close the door. Forced to true when in AUTOMATIC mode.
[Tooltip("0 - the door is closed, 1 - the door is opened. You can set it to something like 0.15 to get semi-opened door at start.")]
[Range(0, 1)]
public float OpenedAtStart = 0; //if grather than 0, the door will be in open state at start.
}
[Serializable]
public class AnimNames //names of the animations, which you use for every action
{
public string OpeningAnim = "Door_open";
public string LockedAnim = "Door_locked";
}
[Serializable]
public class DoorSounds
{
public bool enabled = true;
public AudioClip open;
public AudioClip close;
public AudioClip closed;
[Range(0, 1.0f)]
public float volume = 1.0f;
[Range(0, 0.4f)]
public float pitchRandom = 0.2f;
}
[Serializable]
public class DoorTexts
{
public bool enabled = false;
public string openingText = "Press [BUTTON] to open";
public string closingText = "Press [BUTTON] to close";
public string lockText = "You need a key!";
public GameObject TextPrefab;
}
[Serializable]
public class KeySystem
{
public bool enabled = false;
[HideInInspector]
public bool isUnlock = false;
[Tooltip("If you have a padlock model, you can put the prefab here.")]
public GameObject LockPrefab;
}
[Tooltip("player's head with collider in trigger mode. Type your tag here (usually it is MainCamera)")]
public string PlayerHeadTag = "MainCamera";
[Tooltip("Empty gameObject in the door knobs area. It needed to open the door if " + "'" + "Open by button" + "'" + " type is selected. If you don't want to put this object in this slot manually, you can simply create the object with the name " + "'" + "doorKnob" + "'" + " and put it in the door prefab.")]
public Transform knob; //Empty GO in the door knobs area.
public DoorControls controls = new DoorControls();
public AnimNames AnimationNames = new AnimNames();
public DoorSounds doorSounds = new DoorSounds();
public DoorTexts doorTexts = new DoorTexts();
public KeySystem keySystem = new KeySystem();
Transform player;
bool Opened = false;
bool inZone = false;
Canvas TextObj;
Text theText;
AudioSource SoundFX;
Animation doorAnimation;
Animation LockAnim;
void Start()
{
//Border reparenting
Childs = GetComponentsInChildren<Transform>();
foreach (Transform Child in Childs)
{
if (Child.name == "Joint01")
{
Joint01 = Child.transform;
}
else if (Child.name == "Joint02")
{
Joint02 = Child.transform;
}
}
foreach (Transform Child in Childs)
{
if (Child.name == "Door_bottom01")
{
//print(gameObject.name + " bottom has been found");
Child.parent = Joint01;
}
else if (Child.name == "Door_bottom02")
{
Child.parent = Joint02;
}
}
//--------------------------------
if (controls.openMethod == OpenStyle.AUTOMATIC)
controls.autoClose = true;
if (PlayerHeadTag == "")
Debug.LogError("You need to set a tag!");
if (GameObject.FindWithTag(PlayerHeadTag) != null)
{
player = GameObject.FindWithTag(PlayerHeadTag).transform;
}
else
{
Debug.LogWarning(gameObject.name + ": You need to set your player's camera tag to " + "'" + PlayerHeadTag + "'." + " The " + "'" + gameObject.name + "'" + " can't open/close if you don't set this tag");
}
AddText();
AddLock();
AddAudioSource();
DetectDoorKnob();
doorAnimation = GetComponent<Animation>();
if (controls.OpenedAtStart > 0)
{
doorAnimation[AnimationNames.OpeningAnim].normalizedTime = controls.OpenedAtStart;
doorAnimation[AnimationNames.OpeningAnim].speed = 0;
doorAnimation.Play(AnimationNames.OpeningAnim);
}
}
void AddText()
{
if (doorTexts.enabled)
{
if (doorTexts.TextPrefab == null)
{
Debug.LogWarning(gameObject.name + ": Text prefab missing, if you want see the text, please, put the text prefab in Text Prefab slot");
return;
}
GameObject go = Instantiate(doorTexts.TextPrefab, Vector3.zero, new Quaternion(0, 0, 0, 0)) as GameObject;
TextObj = go.GetComponent<Canvas>();
theText = TextObj.GetComponentInChildren<Text>();
}
}
void AddLock()
{
if (!keySystem.enabled)
return;
if (keySystem.LockPrefab == null)
{
//Debug.Log(gameObject.name + ": you can set a padlock prefab if you want.");
}
else
{
LockAnim = keySystem.LockPrefab.GetComponent<Animation>();
keySystem.enabled = true;
}
}
void AddAudioSource()
{
GameObject go = new GameObject("SoundFX");
go.transform.position = transform.position;
go.transform.rotation = transform.rotation;
go.transform.parent = transform;
SoundFX = go.AddComponent<AudioSource>();
SoundFX.volume = doorSounds.volume;
SoundFX.spatialBlend = 1;
SoundFX.playOnAwake = false;
SoundFX.clip = doorSounds.open;
}
void DetectDoorKnob()
{
if (knob == null)
{
Transform[] children = GetComponentsInChildren<Transform>(true);
foreach (Transform child in children)
{
if (child.name == "doorKnob")
{
knob = child;
}
}
}
}
void Update()
{
if (!doorAnimation.isPlaying && SoundFX.isPlaying)
{
SoundFX.Stop();
}
if (!inZone)
{
HideHint();
return;
}
if (controls.openMethod == OpenStyle.AUTOMATIC && !Opened)
OpenDoor();
if (PLayerIsLookingAtDoorKnob())
{
if (controls.openMethod == OpenStyle.BUTTON)
ShowHint();
}
else
{
HideHint();
return;
}
if (!Input.GetKeyDown(controls.openButton) || controls.openMethod != OpenStyle.BUTTON)
return;
if (Opened)
{
if (!controls.autoClose)
CloseDoor();
}
else
{
if (keySystem.enabled)
{
if (keySystem.isUnlock)
OpenLockDoor();
else
PlayClosedFXs();
}
else
{
OpenDoor();
}
}
}
bool PLayerIsLookingAtDoorKnob()
{
Vector3 forward = player.TransformDirection(Vector3.back);
Vector3 thisTransform = knob.position - player.transform.position;
float dotProd = Vector3.Dot(forward.normalized, thisTransform.normalized);
return (dotProd < 0 && dotProd < -0.9f);
}
void OpenLockDoor()
{
if (keySystem.LockPrefab != null)
{
LockAnim.Play("Lock_open");
Invoke("OpenDoor", 1);
}
else
{
OpenDoor();
}
}
public void Unlock()
{
keySystem.isUnlock = true;
}
void OnTriggerEnter(Collider other)
{
if (other.tag != PlayerHeadTag)
return;
inZone = true;
}
void OnTriggerExit(Collider other)
{
if (other.tag != PlayerHeadTag)
return;
if (Opened && controls.autoClose)
CloseDoor();
inZone = false;
}
void ShowHint()
{
if (Opened)
{
if (!controls.autoClose)
CloseText();
}
else
{
if (keySystem.enabled && !keySystem.isUnlock)
LockText();
else
OpenText();
}
}
void HideHint()
{
if (controls.openMethod == OpenStyle.BUTTON)
HideText();
}
#region AUDIO
/*
* AUDIO
*/
void PlaySFX(AudioClip clip)
{
if (!doorSounds.enabled)
return;
SoundFX.pitch = UnityEngine.Random.Range(1 - doorSounds.pitchRandom, 1 + doorSounds.pitchRandom);
SoundFX.clip = clip;
SoundFX.Play();
}
void PlayClosedFXs()
{
if (doorSounds.closed != null)
{
SoundFX.clip = doorSounds.closed;
SoundFX.Play();
if (doorAnimation[AnimationNames.LockedAnim] != null)
{
doorAnimation.Play(AnimationNames.LockedAnim);
doorAnimation[AnimationNames.LockedAnim].speed = 1;
doorAnimation[AnimationNames.LockedAnim].normalizedTime = 0;
}
}
}
void CloseSound()
{
if (doorAnimation[AnimationNames.OpeningAnim].speed < 0 && doorSounds.close != null)
PlaySFX(doorSounds.close);
}
#endregion
#region TEXT
/*
* TEXT
*/
public void OpenText()
{
ShowText(doorTexts.openingText);
}
void LockText()
{
ShowText(doorTexts.lockText);
}
void CloseText()
{
ShowText(doorTexts.closingText);
}
void ShowText(string txt)
{
if (!doorTexts.enabled)
return;
string tempTxt = txt;
if (controls.openMethod == OpenStyle.BUTTON)
tempTxt = txt.Replace("[BUTTON]", "'" + controls.openButton.ToString() + "'");
TextObj.enabled = false;
theText.text = tempTxt;
TextObj.enabled = true;
}
void HideText()
{
if (!doorTexts.enabled)
return;
if (doorTexts.TextPrefab != null)
{
TextObj.enabled = false;
}
else
{
doorTexts.enabled = false;
}
}
#endregion
void OpenDoor()
{
doorAnimation[AnimationNames.OpeningAnim].speed = controls.openingSpeed;
doorAnimation[AnimationNames.OpeningAnim].normalizedTime = doorAnimation[AnimationNames.OpeningAnim].normalizedTime;
doorAnimation.Play(AnimationNames.OpeningAnim);
if (doorSounds.open != null)
PlaySFX(doorSounds.open);
Opened = true;
if (controls.openMethod == OpenStyle.BUTTON)
HideText();
keySystem.enabled = false;
}
void CloseDoor()
{
if (doorAnimation[AnimationNames.OpeningAnim].normalizedTime < 0.98f && doorAnimation[AnimationNames.OpeningAnim].normalizedTime > 0)
{
doorAnimation[AnimationNames.OpeningAnim].speed = -controls.closingSpeed;
doorAnimation[AnimationNames.OpeningAnim].normalizedTime = doorAnimation[AnimationNames.OpeningAnim].normalizedTime;
doorAnimation.Play(AnimationNames.OpeningAnim);
}
else
{
doorAnimation[AnimationNames.OpeningAnim].speed = -controls.closingSpeed;
doorAnimation[AnimationNames.OpeningAnim].normalizedTime = controls.closeStartFrom;
doorAnimation.Play(AnimationNames.OpeningAnim);
}
if (doorAnimation[AnimationNames.OpeningAnim].normalizedTime > controls.closeStartFrom)
{
doorAnimation[AnimationNames.OpeningAnim].speed = -controls.closingSpeed;
doorAnimation[AnimationNames.OpeningAnim].normalizedTime = controls.closeStartFrom;
doorAnimation.Play(AnimationNames.OpeningAnim);
}
Opened = false;
if (controls.openMethod == OpenStyle.BUTTON && !controls.autoClose)
HideText();
}
}
}