feat: Event & Teleporter

This commit is contained in:
2026-11-03 22:58:10 +01:00
parent a7e8ef1a1f
commit 9fd4e13d34
34 changed files with 5877 additions and 25 deletions

View File

@@ -1,4 +1,5 @@
using Arena.Combat;
using System;
using UnityEngine;
using UnityEngine.InputSystem;
@@ -18,6 +19,7 @@ namespace Arena.Characters
{
public CharacterController Controller;
public InputActionReference MoveAction;
public InputActionReference InteractAction;
}
[System.Serializable]
@@ -37,8 +39,12 @@ namespace Arena.Characters
[SerializeField] private StateContainer _state;
[SerializeField] private Health _health;
public StateContainer State => _state;
public Action OnInteract;
public StateContainer State => _state;
public Health Health => _health;
private bool _isInteracting;
private Vector2 _moveInput;
private Camera _camera;
@@ -65,12 +71,16 @@ namespace Arena.Characters
void OnEnable()
{
_references.MoveAction.action.Enable();
_references.InteractAction.action.Enable();
}
void OnDisable()
{
if (Instance == this)
{
_references.MoveAction.action.Disable();
_references.InteractAction.action.Disable();
}
}
void OnDestroy()
@@ -88,20 +98,47 @@ namespace Arena.Characters
GetInputs();
Move(t);
Interact();
}
#endregion
#region Public Methods
#region PUBLIC METHODS
public void TakeDamage(int amount)
{
_health.TakeDamage(amount);
}
// <summary>
/// Teleports the player.
/// </summary>
/// <param name="pose">x, y, z: position. w: angle around the vertical axis, in degrees.</param>
public void Teleport(Vector4 pose)
{
// An enabled CharacterController would overwrite the new position
_references.Controller.enabled = false;
Vector3 position = new Vector3(pose.x, pose.y, pose.z);
Quaternion rotation = Quaternion.Euler(0f, pose.w, 0f);
transform.SetPositionAndRotation(position, rotation);
_references.Controller.enabled = true;
}
/// <summary>
/// Teleports the player to the position and heading of a target, such as a spawn point.
/// </summary>
public void Teleport(Transform target)
{
Vector3 position = target.position;
Vector4 pose = new Vector4(position.x, position.y, position.z, target.eulerAngles.y);
Teleport(pose);
}
#endregion
#region Private Methods
#region PRIVATE METHODS
#if UNITY_EDITOR
[ContextMenu("Debug/Take 25 Damage")]
@@ -114,6 +151,7 @@ namespace Arena.Characters
private void GetInputs()
{
_moveInput = _references.MoveAction.action.ReadValue<Vector2>();
_isInteracting = _references.InteractAction.action.WasPressedThisFrame();
}
private void Move(float t)
@@ -126,6 +164,14 @@ namespace Arena.Characters
_references.Controller.Move(velocity * t);
}
private void Interact()
{
if (_isInteracting)
{
OnInteract?.Invoke();
}
}
private Vector3 ToWorldDirection(Vector2 input)
{
// Only the camera rotation around the vertical axis is kept

View File

@@ -1,16 +1,89 @@
using UnityEngine;
using UnityEngine.Events;
public class PlayerEvent : MonoBehaviour
namespace Arena.Characters
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
public class PlayerEvent : MonoBehaviour
{
public enum Trigger
{
OnPlayerEnter,
OnPlayerInteract
}
}
[System.Serializable]
public class Settings
{
[Tooltip("OnPlayerEnter: as soon as the player enters. OnPlayerInteract: when the player interacts inside the zone.")]
public Trigger Trigger;
}
// Update is called once per frame
void Update()
{
[SerializeField] private Settings _settings;
[SerializeField] private UnityEvent _onPlayer;
private bool _isListening;
#region UNITY LIFECYCLES
private void OnDisable()
{
// The object can be hidden while the player is inside
StopListening();
}
void OnTriggerEnter(Collider other)
{
if (!IsPlayer(other))
return;
if (_settings.Trigger == Trigger.OnPlayerEnter)
_onPlayer.Invoke();
else
StartListening();
}
void OnTriggerExit(Collider other)
{
if (IsPlayer(other))
StopListening();
}
#endregion
private bool IsPlayer(Collider other)
{
return Player.Instance != null && other.gameObject == Player.Instance.gameObject;
}
private void StartListening()
{
Player.Instance.OnInteract += HandleInteract;
_isListening = true;
}
private void StopListening()
{
if (!_isListening)
return;
if (Player.Instance != null)
Player.Instance.OnInteract -= HandleInteract;
_isListening = false;
}
private void HandleInteract()
{
_onPlayer.Invoke();
}
public void Teleport(Transform target)
{
if (!Player.Instance)
return;
StopListening();
Player.Instance.Teleport(target);
}
}
}