feat: add throwable boxs and set it as prefab
This commit is contained in:
189
Assets/Code/Scripts/Interaction/ButtonSequenceDoorPuzzle.cs
Normal file
189
Assets/Code/Scripts/Interaction/ButtonSequenceDoorPuzzle.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
public class ButtonSequenceDoorPuzzle : MonoBehaviour
|
||||
{
|
||||
[Header("References")]
|
||||
[Tooltip("All available buttons for this puzzle.")]
|
||||
[SerializeField] private WallInteractButton[] buttons;
|
||||
|
||||
[Tooltip("Door to open when the sequence is correct.")]
|
||||
[SerializeField] private SlidingDoor targetDoor;
|
||||
|
||||
[Tooltip("Optional blocks controlled by this puzzle (reset with SetOff on start/wrong input).")]
|
||||
[SerializeField] private TestBlock[] puzzleBlocks;
|
||||
|
||||
[Header("Sequence")]
|
||||
[Tooltip("Button indices (from the buttons array) that must be pressed in order. Example: 2,0,3")]
|
||||
[SerializeField] private int[] requiredSequence = { 0, 1, 2 };
|
||||
|
||||
[Tooltip("If true, wrong input resets progress back to 0.")]
|
||||
[SerializeField] private bool resetOnWrongPress = true;
|
||||
|
||||
[Tooltip("If true, puzzle can only be solved once.")]
|
||||
[SerializeField] private bool lockAfterSolved = true;
|
||||
|
||||
[Header("Debug")]
|
||||
[SerializeField] private bool enableDebugLogs = true;
|
||||
|
||||
private int m_progress;
|
||||
private bool m_isSolved;
|
||||
private UnityAction[] m_cachedListeners;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
SetAllBlocksOff();
|
||||
RegisterAllButtons();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
UnregisterAllButtons();
|
||||
}
|
||||
|
||||
private void RegisterAllButtons()
|
||||
{
|
||||
if (buttons == null)
|
||||
return;
|
||||
|
||||
m_cachedListeners = new UnityAction[buttons.Length];
|
||||
|
||||
for (int i = 0; i < buttons.Length; i++)
|
||||
{
|
||||
WallInteractButton button = buttons[i];
|
||||
if (button == null)
|
||||
continue;
|
||||
|
||||
int buttonIndex = i;
|
||||
UnityAction action = () => OnButtonPressed(buttonIndex);
|
||||
m_cachedListeners[i] = action;
|
||||
button.OnInteract.AddListener(action);
|
||||
}
|
||||
}
|
||||
|
||||
private void UnregisterAllButtons()
|
||||
{
|
||||
if (buttons == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < buttons.Length; i++)
|
||||
{
|
||||
WallInteractButton button = buttons[i];
|
||||
if (button == null)
|
||||
continue;
|
||||
|
||||
if (m_cachedListeners != null && i < m_cachedListeners.Length && m_cachedListeners[i] != null)
|
||||
button.OnInteract.RemoveListener(m_cachedListeners[i]);
|
||||
}
|
||||
|
||||
m_cachedListeners = null;
|
||||
m_progress = 0;
|
||||
}
|
||||
|
||||
private void OnButtonPressed(int buttonIndex)
|
||||
{
|
||||
Log($"Button pressed: index {buttonIndex}");
|
||||
|
||||
if (m_isSolved && lockAfterSolved)
|
||||
{
|
||||
Log("Puzzle already solved and locked.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsSequenceValid())
|
||||
{
|
||||
Log("Invalid sequence configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
int expectedIndex = requiredSequence[m_progress];
|
||||
Log($"Expected button index: {expectedIndex} (step {m_progress + 1}/{requiredSequence.Length})");
|
||||
|
||||
if (buttonIndex == expectedIndex)
|
||||
{
|
||||
m_progress++;
|
||||
Log($"Correct input. Progress: {m_progress}/{requiredSequence.Length}");
|
||||
|
||||
if (m_progress >= requiredSequence.Length)
|
||||
{
|
||||
SolvePuzzle();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (resetOnWrongPress)
|
||||
{
|
||||
Log("Wrong input. Resetting sequence and turning puzzle blocks OFF.");
|
||||
m_progress = 0;
|
||||
SetAllBlocksOff();
|
||||
return;
|
||||
}
|
||||
|
||||
Log("Wrong input, but resetOnWrongPress is disabled.");
|
||||
}
|
||||
|
||||
private bool IsSequenceValid()
|
||||
{
|
||||
if (requiredSequence == null || requiredSequence.Length == 0)
|
||||
return false;
|
||||
|
||||
if (buttons == null || buttons.Length == 0)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < requiredSequence.Length; i++)
|
||||
{
|
||||
int index = requiredSequence[i];
|
||||
if (index < 0 || index >= buttons.Length)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SolvePuzzle()
|
||||
{
|
||||
m_isSolved = true;
|
||||
m_progress = 0;
|
||||
Log("Sequence completed. Opening door.");
|
||||
|
||||
if (targetDoor != null)
|
||||
targetDoor.Open();
|
||||
}
|
||||
|
||||
private void SetAllBlocksOff()
|
||||
{
|
||||
if (puzzleBlocks == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < puzzleBlocks.Length; i++)
|
||||
{
|
||||
if (puzzleBlocks[i] == null)
|
||||
continue;
|
||||
|
||||
puzzleBlocks[i].SetOff();
|
||||
}
|
||||
}
|
||||
|
||||
private void Log(string message)
|
||||
{
|
||||
if (!enableDebugLogs)
|
||||
return;
|
||||
|
||||
Debug.Log($"[{nameof(ButtonSequenceDoorPuzzle)}] {message}", this);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (requiredSequence == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < requiredSequence.Length; i++)
|
||||
{
|
||||
requiredSequence[i] = Math.Max(0, requiredSequence[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 920802292ba9a49d2bee3519a905717d
|
||||
72
Assets/Code/Scripts/Interaction/PlayerBoxController.cs
Normal file
72
Assets/Code/Scripts/Interaction/PlayerBoxController.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class BoxPickup : MonoBehaviour
|
||||
{
|
||||
public Transform PlayerTransform;
|
||||
public Transform CameraTransform;
|
||||
public Transform HandTransform;
|
||||
public float ThrowForce = 10f;
|
||||
public float PickupDistance = 5f;
|
||||
|
||||
private bool isHeld;
|
||||
private Rigidbody m_rigidbody;
|
||||
private PlayerInputController input;
|
||||
|
||||
void Start()
|
||||
{
|
||||
m_rigidbody = GetComponent<Rigidbody>();
|
||||
input = PlayerTransform.GetComponent<PlayerInputController>();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (input.InteractPressed)
|
||||
{
|
||||
if (!isHeld)
|
||||
TryPickup();
|
||||
else
|
||||
Drop();
|
||||
}
|
||||
|
||||
if (input.ThrowPressed)
|
||||
Throw();
|
||||
}
|
||||
|
||||
private void TryPickup()
|
||||
{
|
||||
Collider[] hits = Physics.OverlapSphere(PlayerTransform.position, PickupDistance);
|
||||
|
||||
foreach (Collider hit in hits)
|
||||
{
|
||||
if (hit.transform == transform) {
|
||||
Pickup();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Pickup()
|
||||
{
|
||||
isHeld = true;
|
||||
m_rigidbody.isKinematic = true;
|
||||
transform.SetParent(HandTransform);
|
||||
transform.localPosition = Vector3.zero;
|
||||
transform.localRotation = Quaternion.identity;
|
||||
}
|
||||
|
||||
private void Drop()
|
||||
{
|
||||
isHeld = false;
|
||||
transform.SetParent(null);
|
||||
m_rigidbody.isKinematic = false;
|
||||
}
|
||||
|
||||
private void Throw()
|
||||
{
|
||||
if (!isHeld)
|
||||
return;
|
||||
|
||||
Drop();
|
||||
m_rigidbody.AddForce(PlayerTransform.forward * ThrowForce, ForceMode.Impulse);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a36af2e55a3732eb2abc110ae2365702
|
||||
76
Assets/Code/Scripts/Interaction/PressurePlateButton.cs
Normal file
76
Assets/Code/Scripts/Interaction/PressurePlateButton.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
[RequireComponent(typeof(Collider))]
|
||||
public class PressurePlateButton : MonoBehaviour
|
||||
{
|
||||
[Header("Detection")]
|
||||
[Tooltip("Layers that can activate the plate. Keep default to allow everything.")]
|
||||
[SerializeField] private LayerMask detectionMask = ~0;
|
||||
|
||||
[Tooltip("If true, rigidbody objects can activate the plate.")]
|
||||
[SerializeField] private bool allowRigidbodies = true;
|
||||
|
||||
[Tooltip("If true, the Player can activate the plate (tag Player or PlayerMovement component).")]
|
||||
[SerializeField] private bool allowPlayer = true;
|
||||
|
||||
[Header("Events")]
|
||||
public UnityEvent OnPressed;
|
||||
public UnityEvent OnReleased;
|
||||
|
||||
private readonly HashSet<Collider> m_validCollidersOnPlate = new HashSet<Collider>();
|
||||
private bool m_isPressed;
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
Collider col = GetComponent<Collider>();
|
||||
col.isTrigger = true;
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (!IsValidActivator(other))
|
||||
return;
|
||||
|
||||
m_validCollidersOnPlate.Add(other);
|
||||
|
||||
if (!m_isPressed)
|
||||
{
|
||||
m_isPressed = true;
|
||||
OnPressed?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (!m_validCollidersOnPlate.Remove(other))
|
||||
return;
|
||||
|
||||
if (m_validCollidersOnPlate.Count == 0 && m_isPressed)
|
||||
{
|
||||
m_isPressed = false;
|
||||
OnReleased?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsValidActivator(Collider other)
|
||||
{
|
||||
if (((1 << other.gameObject.layer) & detectionMask) == 0)
|
||||
return false;
|
||||
|
||||
if (allowPlayer)
|
||||
{
|
||||
if (other.CompareTag("Player"))
|
||||
return true;
|
||||
|
||||
if (other.GetComponentInParent<PlayerMovement>() != null)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (allowRigidbodies && other.attachedRigidbody != null)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69374de63bb12844d97acb7a794b7b40
|
||||
114
Assets/Code/Scripts/Interaction/SlidingDoor.cs
Normal file
114
Assets/Code/Scripts/Interaction/SlidingDoor.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
public class SlidingDoor : MonoBehaviour
|
||||
{
|
||||
public enum SlideAxis { X, Y, Z }
|
||||
public enum SlideDirection { Positive = 1, Negative = -1 }
|
||||
|
||||
[Header("Slide Settings")]
|
||||
[Tooltip("Local axis the door slides along.")]
|
||||
[SerializeField] private SlideAxis axis = SlideAxis.X;
|
||||
|
||||
[Tooltip("Which way along the axis the door opens.")]
|
||||
[SerializeField] private SlideDirection direction = SlideDirection.Positive;
|
||||
|
||||
[Tooltip("How far the door travels when fully open.")]
|
||||
[SerializeField] private float slideDistance = 2f;
|
||||
|
||||
[Tooltip("Movement speed (units per second).")]
|
||||
[SerializeField] private float speed = 3f;
|
||||
|
||||
[Header("Start State")]
|
||||
[SerializeField] private bool startOpen = false;
|
||||
|
||||
[Header("Events")]
|
||||
public UnityEvent OnOpened;
|
||||
public UnityEvent OnClosed;
|
||||
|
||||
private Vector3 m_closedPos;
|
||||
private Vector3 m_openPos;
|
||||
private Vector3 m_targetPos;
|
||||
private bool m_isOpen;
|
||||
private bool m_eventFiredOpen;
|
||||
private bool m_eventFiredClosed;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
m_closedPos = transform.localPosition;
|
||||
m_openPos = m_closedPos + GetSlideVector() * slideDistance;
|
||||
|
||||
if (startOpen)
|
||||
{
|
||||
transform.localPosition = m_openPos;
|
||||
m_isOpen = true;
|
||||
}
|
||||
|
||||
m_targetPos = m_isOpen ? m_openPos : m_closedPos;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
transform.localPosition = Vector3.MoveTowards(
|
||||
transform.localPosition, m_targetPos, speed * Time.deltaTime);
|
||||
|
||||
if (Vector3.Distance(transform.localPosition, m_openPos) < 0.01f && !m_eventFiredOpen)
|
||||
{
|
||||
m_eventFiredOpen = true;
|
||||
m_eventFiredClosed = false;
|
||||
OnOpened?.Invoke();
|
||||
}
|
||||
else if (Vector3.Distance(transform.localPosition, m_closedPos) < 0.01f && !m_eventFiredClosed)
|
||||
{
|
||||
m_eventFiredClosed = true;
|
||||
m_eventFiredOpen = false;
|
||||
OnClosed?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public void Open()
|
||||
{
|
||||
m_isOpen = true;
|
||||
m_targetPos = m_openPos;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
m_isOpen = false;
|
||||
m_targetPos = m_closedPos;
|
||||
}
|
||||
|
||||
public void Toggle()
|
||||
{
|
||||
if (m_isOpen)
|
||||
Close();
|
||||
else
|
||||
Open();
|
||||
}
|
||||
|
||||
private Vector3 GetSlideVector()
|
||||
{
|
||||
float sign = (float)direction;
|
||||
return axis switch
|
||||
{
|
||||
SlideAxis.X => new Vector3(sign, 0f, 0f),
|
||||
SlideAxis.Y => new Vector3(0f, sign, 0f),
|
||||
SlideAxis.Z => new Vector3(0f, 0f, sign),
|
||||
_ => Vector3.right,
|
||||
};
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
Vector3 worldClosed = transform.parent != null
|
||||
? transform.parent.TransformPoint(transform.localPosition)
|
||||
: transform.position;
|
||||
|
||||
Vector3 slideVec = transform.TransformDirection(GetSlideVector()) * slideDistance;
|
||||
Gizmos.color = Color.cyan;
|
||||
Gizmos.DrawLine(worldClosed, worldClosed + slideVec);
|
||||
Gizmos.DrawWireSphere(worldClosed + slideVec, 0.08f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
2
Assets/Code/Scripts/Interaction/SlidingDoor.cs.meta
Normal file
2
Assets/Code/Scripts/Interaction/SlidingDoor.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0cc6c36a261296f4c82e315da147ba93
|
||||
148
Assets/Code/Scripts/Interaction/TestBlock.cs
Normal file
148
Assets/Code/Scripts/Interaction/TestBlock.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
public class TestBlock : MonoBehaviour
|
||||
{
|
||||
[Header("Visual")]
|
||||
[SerializeField] private Renderer targetRenderer;
|
||||
[SerializeField] private Color offColor = Color.red;
|
||||
[SerializeField] private Color onColor = Color.green;
|
||||
|
||||
[Header("Material")]
|
||||
[SerializeField] private string colorPropertyName = "_BaseColor";
|
||||
|
||||
[Header("Optional Auto Wiring")]
|
||||
[Tooltip("If assigned, block turns ON while plate is pressed and OFF when released.")]
|
||||
[SerializeField] private PressurePlateButton[] pressurePlates;
|
||||
|
||||
[Tooltip("If assigned, block toggles every time the wall button is interacted with.")]
|
||||
[SerializeField] private WallInteractButton[] wallButtons;
|
||||
|
||||
private MaterialPropertyBlock m_propertyBlock;
|
||||
private bool m_isOn;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (targetRenderer == null)
|
||||
{
|
||||
targetRenderer = GetComponentInChildren<Renderer>();
|
||||
}
|
||||
|
||||
m_propertyBlock = new MaterialPropertyBlock();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
SetOff();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
RegisterEvents();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
UnregisterEvents();
|
||||
}
|
||||
|
||||
public void SetOn()
|
||||
{
|
||||
m_isOn = true;
|
||||
Debug.Log($"{gameObject.name} turned ON");
|
||||
ApplyColor(onColor);
|
||||
}
|
||||
|
||||
public void SetOff()
|
||||
{
|
||||
m_isOn = false;
|
||||
Debug.Log($"{gameObject.name} turned OFF");
|
||||
ApplyColor(offColor);
|
||||
}
|
||||
|
||||
public void Toggle()
|
||||
{
|
||||
if (m_isOn)
|
||||
SetOff();
|
||||
else
|
||||
SetOn();
|
||||
}
|
||||
|
||||
// Generic interaction entry point for UnityEvents from any interactable.
|
||||
public void TriggerInteraction()
|
||||
{
|
||||
Toggle();
|
||||
}
|
||||
|
||||
public void Activate()
|
||||
{
|
||||
SetOn();
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
SetOff();
|
||||
}
|
||||
|
||||
private void ApplyColor(Color color)
|
||||
{
|
||||
if (targetRenderer == null)
|
||||
return;
|
||||
|
||||
targetRenderer.GetPropertyBlock(m_propertyBlock);
|
||||
m_propertyBlock.SetColor(colorPropertyName, color);
|
||||
targetRenderer.SetPropertyBlock(m_propertyBlock);
|
||||
}
|
||||
|
||||
private void RegisterEvents()
|
||||
{
|
||||
if (pressurePlates != null)
|
||||
{
|
||||
for (int i = 0; i < pressurePlates.Length; i++)
|
||||
{
|
||||
if (pressurePlates[i] == null)
|
||||
continue;
|
||||
|
||||
pressurePlates[i].OnPressed.AddListener(SetOn);
|
||||
pressurePlates[i].OnReleased.AddListener(SetOff);
|
||||
}
|
||||
}
|
||||
|
||||
if (wallButtons != null)
|
||||
{
|
||||
for (int i = 0; i < wallButtons.Length; i++)
|
||||
{
|
||||
if (wallButtons[i] == null)
|
||||
continue;
|
||||
|
||||
wallButtons[i].OnInteract.AddListener(Toggle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UnregisterEvents()
|
||||
{
|
||||
if (pressurePlates != null)
|
||||
{
|
||||
for (int i = 0; i < pressurePlates.Length; i++)
|
||||
{
|
||||
if (pressurePlates[i] == null)
|
||||
continue;
|
||||
|
||||
pressurePlates[i].OnPressed.RemoveListener(SetOn);
|
||||
pressurePlates[i].OnReleased.RemoveListener(SetOff);
|
||||
}
|
||||
}
|
||||
|
||||
if (wallButtons != null)
|
||||
{
|
||||
for (int i = 0; i < wallButtons.Length; i++)
|
||||
{
|
||||
if (wallButtons[i] == null)
|
||||
continue;
|
||||
|
||||
wallButtons[i].OnInteract.RemoveListener(Toggle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Code/Scripts/Interaction/TestBlock.cs.meta
Normal file
2
Assets/Code/Scripts/Interaction/TestBlock.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b93699191d7b58146b2c38540cbed40f
|
||||
138
Assets/Code/Scripts/Interaction/WallInteractButton.cs
Normal file
138
Assets/Code/Scripts/Interaction/WallInteractButton.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
[RequireComponent(typeof(Collider))]
|
||||
public class WallInteractButton : MonoBehaviour
|
||||
{
|
||||
[Header("Interaction")]
|
||||
[Tooltip("Key the player must press to interact (keyboard fallback).")]
|
||||
[SerializeField] private Key interactKey = Key.E;
|
||||
|
||||
[Tooltip("If true, the button can only be triggered once.")]
|
||||
[SerializeField] private bool oneShot = false;
|
||||
|
||||
[Header("Physical Press")]
|
||||
[Tooltip("Transform that moves to simulate a physical press (optional).")]
|
||||
[SerializeField] private Transform buttonMesh;
|
||||
|
||||
[Tooltip("How far the button moves when pressed.")]
|
||||
[SerializeField] private float pressDepth = 0.05f;
|
||||
|
||||
[Tooltip("Speed of the press/release animation.")]
|
||||
[SerializeField] private float pressSpeed = 10f;
|
||||
|
||||
[Header("Events")]
|
||||
public UnityEvent OnInteract;
|
||||
|
||||
private bool m_playerInRange;
|
||||
private bool m_used;
|
||||
|
||||
private Vector3 m_buttonRestPos;
|
||||
private Vector3 m_buttonPressedPos;
|
||||
private bool m_isVisuallyPressed;
|
||||
|
||||
public PlayerHeadController headController;
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
Collider col = GetComponent<Collider>();
|
||||
col.isTrigger = true;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (buttonMesh != null)
|
||||
{
|
||||
m_buttonRestPos = buttonMesh.localPosition;
|
||||
m_buttonPressedPos = m_buttonRestPos - buttonMesh.localRotation * Vector3.forward * pressDepth;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!headController.isHoldingHead && m_playerInRange && Keyboard.current != null && Keyboard.current[interactKey].wasPressedThisFrame)
|
||||
{
|
||||
TryInteract();
|
||||
}
|
||||
|
||||
AnimateButton();
|
||||
}
|
||||
|
||||
private void TryInteract()
|
||||
{
|
||||
if (oneShot && m_used)
|
||||
return;
|
||||
|
||||
m_used = true;
|
||||
m_isVisuallyPressed = true;
|
||||
OnInteract?.Invoke();
|
||||
|
||||
if (!oneShot)
|
||||
Invoke(nameof(ReleaseVisual), 0.15f);
|
||||
}
|
||||
|
||||
private void ReleaseVisual()
|
||||
{
|
||||
m_isVisuallyPressed = false;
|
||||
}
|
||||
|
||||
private void AnimateButton()
|
||||
{
|
||||
if (buttonMesh == null)
|
||||
return;
|
||||
|
||||
Vector3 target = m_isVisuallyPressed ? m_buttonPressedPos : m_buttonRestPos;
|
||||
buttonMesh.localPosition = Vector3.Lerp(buttonMesh.localPosition, target, Time.deltaTime * pressSpeed);
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (IsPlayer(other))
|
||||
m_playerInRange = true;
|
||||
}
|
||||
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (IsPlayer(other))
|
||||
m_playerInRange = false;
|
||||
}
|
||||
|
||||
private bool IsPlayer(Collider other)
|
||||
{
|
||||
if (other.CompareTag("Player"))
|
||||
return true;
|
||||
|
||||
if (other.GetComponentInParent<PlayerMovement>() != null)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
Collider col = GetComponent<Collider>();
|
||||
if (col == null)
|
||||
return;
|
||||
|
||||
Gizmos.matrix = transform.localToWorldMatrix;
|
||||
Gizmos.color = m_playerInRange
|
||||
? new Color(0f, 1f, 0f, 0.25f)
|
||||
: new Color(1f, 0.9f, 0f, 0.15f);
|
||||
|
||||
if (col is SphereCollider sphere)
|
||||
{
|
||||
Gizmos.DrawSphere(sphere.center, sphere.radius);
|
||||
Gizmos.color = m_playerInRange ? Color.green : Color.yellow;
|
||||
Gizmos.DrawWireSphere(sphere.center, sphere.radius);
|
||||
}
|
||||
else if (col is BoxCollider box)
|
||||
{
|
||||
Gizmos.DrawCube(box.center, box.size);
|
||||
Gizmos.color = m_playerInRange ? Color.green : Color.yellow;
|
||||
Gizmos.DrawWireCube(box.center, box.size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96a3f628ff18ea34788167cc398180ca
|
||||
Reference in New Issue
Block a user