382 lines
11 KiB
C#

using _PROJECT.NewHandPresence;
using System.Collections;
using System.Collections.Generic;
using Unity.XR.CoreUtils;
using UnityEditor;
using UnityEngine;
public enum ElevatorState
{
Stationary,
OpeningDoors,
AwaitingPassengers,
ClosingDoors,
Moving
}
public class ElevatorBox : MonoBehaviour
{
public List<ElevatorOuter> callers = new List<ElevatorOuter>();
public GameObject leftDoor;
public Transform leftDoorOpenPos;
public Transform leftDoorClosedPos;
public GameObject rightDoor;
public Transform rightDoorOpenPos;
public Transform rightDoorClosedPos;
public float doorOpenTime = 4f;
public float doorCloseTime = 5.6f;
public float floorMoveTime = 5f;
public float doorStayOpenTime = 2f;
[System.Serializable]
public struct FloorData
{
public int floorNumber; // can be -1, 0, 1, 2 ...
public Transform floorPoint; // reference to the transform in scene
}
// Unity can display arrays/lists of this struct in Inspector
public FloorData[] floors;
// Runtime dictionary for quick lookup
private Dictionary<int, Transform> floorDict = new Dictionary<int, Transform>();
[System.Serializable]
public struct FloorNumbers
{
public int floorNumber;
public GameObject floorNumberSprite;
}
public List<FloorNumbers> floorDisplayNumbers;
public AudioSource audioSource;
public AudioClip[] openDoorsClips;
public AudioClip[] closeDoorsClips;
public AudioClip[] moveElevatorClips;
private int currentFloor = 2;
private int targetFloor = 2;
private ElevatorState state = ElevatorState.Stationary;
void Awake()
{
foreach (var f in floors)
{
if (!floorDict.ContainsKey(f.floorNumber))
floorDict.Add(f.floorNumber, f.floorPoint);
}
}
private void Start()
{
updateDisplayFloorNumber(currentFloor);
foreach (ElevatorOuter caller in callers)
caller.statusPlate.UpdateDisplayFloorNumber(currentFloor);
}
public IEnumerator callElevator(int floor)
{
//Debug.Log("Calling Elevator");
Debug.Log(state);
if (state == ElevatorState.Stationary || state == ElevatorState.ClosingDoors)
{
Debug.Log(floor);
if (floor != currentFloor)
{
//Debug.Log("Started moving lift");
yield return StartCoroutine(CloseDoors());
targetFloor = floor;
yield return StartCoroutine(MoveToFloor(targetFloor));
}
else
StartCoroutine(OpenDoors());
SetState(ElevatorState.AwaitingPassengers);
}
}
public void interestExpired()
{
if (state == ElevatorState.AwaitingPassengers)
{
if (IsElevatorEmpty())
{
StartCoroutine(CloseAndStationary());
}
}
}
private bool IsElevatorEmpty()
{
return this.GetComponentInChildren<XROrigin>() == null;
}
private void SetState(ElevatorState newstate)
{
Debug.Log("Setting new state of " + newstate);
this.state = newstate;
}
private void OnTriggerEnter(Collider other)
{
XROrigin enteredPlayerVR = other.GetComponent<XROrigin>();
KbmController enteredPlayerKbm = other.GetComponent<KbmController>();
Debug.Log("Player Entered box");
if (enteredPlayerVR != null)
{
addChild(enteredPlayerVR);
}
else if (enteredPlayerKbm != null)
{
enteredPlayerKbm.transform.SetParent(this.transform);
}
else
return;
switch (targetFloor)
{
case int f when f == floors[0].floorNumber:
targetFloor = floors[1].floorNumber;
break;
case int f when f == floors[1].floorNumber:
targetFloor = floors[0].floorNumber;
break;
default:
break;
}
StartCoroutine(LiftTransferSequence());
}
private void OnTriggerExit(Collider other)
{
// Was it a player, that exited?
XROrigin exitedPlayerVR = other.GetComponent<XROrigin>();
KbmController exitedPlayerKbm = other.GetComponent<KbmController>();
if (exitedPlayerVR != null)
{
removeChild(exitedPlayerVR);
}
else if (exitedPlayerKbm != null)
{
exitedPlayerKbm.transform.SetParent(null);
}
else
return;
Debug.Log("Player exited box, state is: " + this.state);
if (this.state == ElevatorState.AwaitingPassengers)
{
if (IsElevatorEmpty())
{
//Debug.Log("Elevator is empty");
StartCoroutine(CloseAndStationary());
}
}
}
private ElevatorOuter findTargetCaller()
{
//Debug.Log("finding target caller");
foreach (ElevatorOuter caller in this.callers)
{
//Debug.Log(caller.floor);
//Debug.Log(targetFloor);
if (caller.floor == targetFloor)
{
//Debug.Log("found caller");
return caller;
}
}
return null;
}
private ElevatorOuter findCurrentCaller()
{
//Debug.Log("finding target caller");
foreach (ElevatorOuter caller in this.callers)
{
//Debug.Log(caller.floor);
//Debug.Log(targetFloor);
if (caller.floor == this.currentFloor)
{
//Debug.Log("found caller");
return caller;
}
}
return null;
}
private void SetCurrentFloor(int floor) {
this.currentFloor = floor;
updateDisplayFloorNumber(floor);
foreach (ElevatorOuter caller in callers)
caller.statusPlate.UpdateDisplayFloorNumber(floor);
}
private void updateDisplayFloorNumber(int newValue)
{
foreach (var f in floorDisplayNumbers)
{
if (f.floorNumber != newValue)
f.floorNumberSprite.SetActive(false);
else
f.floorNumberSprite.SetActive(true);
}
}
public void addChild(XROrigin player)
{
player.transform.SetParent(this.transform);
}
public void removeChild(XROrigin player)
{
player.transform.SetParent(null);
}
private void playRandomAudioClipFrom(AudioClip[] list)
{
if (list.Length == 0) return;
int index = Random.Range(0, list.Length);
audioSource.clip = list[index];
audioSource.Play();
}
private IEnumerator LiftTransferSequence()
{
yield return StartCoroutine(CloseDoors());
yield return StartCoroutine(MoveToFloor(targetFloor));
}
public IEnumerator MoveToFloor(int floorNumber)
{
Debug.Log("Moving to floor " + floorNumber);
if (floorDict.TryGetValue(floorNumber, out Transform target))
{
yield return StartCoroutine(MoveElevator(target.position));
SetCurrentFloor(targetFloor);
}
else
{
Debug.LogWarning($"No floor defined for number {floorNumber}");
}
yield return StartCoroutine(OpenDoors());
}
private IEnumerator CloseAndStationary()
{
Debug.Log("Close and set stationary");
// Wait for CloseDoors() to finish
yield return StartCoroutine(CloseDoors());
// After doors have closed, set state
SetState(ElevatorState.Stationary);
}
private IEnumerator CloseDoors()
{
//if (state == ElevatorState.AwaitingPassengers) {
//Debug.Log("Closing doors");
if (Vector3.Distance(leftDoor.transform.position, leftDoorClosedPos.position) < 0.01f)
yield break;
SetState(ElevatorState.ClosingDoors);
playRandomAudioClipFrom(closeDoorsClips);
ElevatorOuter currentCaller = findCurrentCaller();
if (currentCaller != null) currentCaller.CloseDoors();
yield return StartCoroutine(MoveDoors(leftDoor, leftDoorClosedPos, rightDoor, rightDoorClosedPos, doorCloseTime));
//}
}
private IEnumerator OpenDoors()
{
if (state != ElevatorState.AwaitingPassengers) {
//Debug.Log("Opening doors");
SetState(ElevatorState.OpeningDoors);
playRandomAudioClipFrom(openDoorsClips);
ElevatorOuter targetCaller = findTargetCaller();
//Debug.Log("Target caller is: " + targetCaller);
if (targetCaller != null)
targetCaller.OpenDoors();
yield return StartCoroutine(MoveDoors(leftDoor, leftDoorOpenPos, rightDoor, rightDoorOpenPos, doorOpenTime));
SetState(ElevatorState.AwaitingPassengers);
yield return new WaitForSeconds(doorStayOpenTime); // wait for passengers
}
}
private IEnumerator MoveDoors(GameObject left, Transform targetLeft, GameObject right, Transform targetRight, float moveTime)
{
Debug.Log("Moving doors");
Vector3 startL = left.transform.position;
Vector3 startR = right.transform.position;
float t = 0;
while (t < 1f)
{
t += Time.deltaTime / moveTime;
float easedT = Mathf.SmoothStep(0f, 1f, t); // ease in/out
left.transform.position = Vector3.Lerp(startL, targetLeft.position, easedT);
right.transform.position = Vector3.Lerp(startR, targetRight.position, easedT);
yield return null;
}
//Debug.Log("Inner Doors moved");
}
private IEnumerator MoveElevator(Vector3 targetPos)
{
if (targetFloor > currentFloor)
foreach (ElevatorOuter caller in callers)
caller.statusPlate.SetMoveState(ElevatorMoveState.Ascending);
else
foreach (ElevatorOuter caller in callers)
caller.statusPlate.SetMoveState(ElevatorMoveState.Decending);
Vector3 startPos = transform.position;
float t = 0;
SetState(ElevatorState.Moving);
playRandomAudioClipFrom(moveElevatorClips);
while (t < 1f)
{
t += Time.deltaTime / floorMoveTime;
float easedT = Mathf.SmoothStep(0f, 1f, t); // ease in/out
transform.position = Vector3.Lerp(startPos, targetPos, easedT);
yield return null;
}
foreach (ElevatorOuter caller in callers)
caller.statusPlate.SetMoveState(ElevatorMoveState.NotMoving);
}
}