feat: Player & Camera
This commit is contained in:
140
Assets/_Content/Scripts/Characters/Player.cs
Normal file
140
Assets/_Content/Scripts/Characters/Player.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using Arena.Combat;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace Arena.Characters
|
||||
{
|
||||
public class Player : MonoBehaviour, IDamageable
|
||||
{
|
||||
[System.Serializable]
|
||||
private class Settings
|
||||
{
|
||||
[Tooltip("Movement speed, in km/h.")]
|
||||
public float Speed = 10;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
private struct References
|
||||
{
|
||||
public CharacterController Controller;
|
||||
public InputActionReference MoveAction;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class StateContainer
|
||||
{
|
||||
public bool IsMoving = false;
|
||||
}
|
||||
|
||||
#region FIELDS
|
||||
|
||||
public static Player Instance { get; private set; }
|
||||
|
||||
const float KMH_TO_MS = 1 / 3.6f;
|
||||
|
||||
[SerializeField] private Settings _settings;
|
||||
[SerializeField] private References _references;
|
||||
[SerializeField] private StateContainer _state;
|
||||
[SerializeField] private Health _health;
|
||||
|
||||
public StateContainer State => _state;
|
||||
|
||||
private Vector2 _moveInput;
|
||||
private Camera _camera;
|
||||
|
||||
#endregion
|
||||
|
||||
#region UNITY LIFECYCLES
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (Instance && Instance != this)
|
||||
{
|
||||
Debug.LogWarning($"A second Player was found on {name}, it is destroyed.");
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = this;
|
||||
|
||||
_health.Initialize();
|
||||
|
||||
_camera = Camera.main;
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
_references.MoveAction.action.Enable();
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
if (Instance == this)
|
||||
_references.MoveAction.action.Disable();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if (Instance == this)
|
||||
Instance = null;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (_health.IsDead)
|
||||
return;
|
||||
|
||||
float t = Time.deltaTime;
|
||||
|
||||
GetInputs();
|
||||
Move(t);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void TakeDamage(int amount)
|
||||
{
|
||||
_health.TakeDamage(amount);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[ContextMenu("Debug/Take 25 Damage")]
|
||||
private void DebugTakeDamage()
|
||||
{
|
||||
TakeDamage(25);
|
||||
}
|
||||
#endif
|
||||
|
||||
private void GetInputs()
|
||||
{
|
||||
_moveInput = _references.MoveAction.action.ReadValue<Vector2>();
|
||||
}
|
||||
|
||||
private void Move(float t)
|
||||
{
|
||||
Vector3 direction = ToWorldDirection(_moveInput);
|
||||
Vector3 velocity = direction * KMH_TO_MS * _settings.Speed;
|
||||
|
||||
_state.IsMoving = velocity.sqrMagnitude > .01f;
|
||||
|
||||
_references.Controller.Move(velocity * t);
|
||||
}
|
||||
|
||||
private Vector3 ToWorldDirection(Vector2 input)
|
||||
{
|
||||
// Only the camera rotation around the vertical axis is kept
|
||||
Quaternion cameraHeading = Quaternion.Euler(0f, _camera.transform.eulerAngles.y, 0f);
|
||||
return cameraHeading * new Vector3(input.x, 0f, input.y);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/Characters/Player.cs.meta
Normal file
2
Assets/_Content/Scripts/Characters/Player.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 502392351c6ed7e4c9a3a895792f5b68
|
||||
75
Assets/_Content/Scripts/Characters/PlayerCamera.cs
Normal file
75
Assets/_Content/Scripts/Characters/PlayerCamera.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace Arena.Characters
|
||||
{
|
||||
[ExecuteAlways]
|
||||
public class PlayerCamera : MonoBehaviour
|
||||
{
|
||||
[System.Serializable]
|
||||
public class Settings
|
||||
{
|
||||
[Tooltip("x: horizontal distance from the player, y: height above the player, in meters.")]
|
||||
public Vector2 Offset = new Vector2(7f, 8f);
|
||||
|
||||
[Tooltip("Rotation of the offset around the player, in degrees.")]
|
||||
public float Angle = 0f;
|
||||
|
||||
[Tooltip("Time to catch up with the player, in seconds. 0: no smoothing.")]
|
||||
[Range(0f, 1f)] public float Smooth = 0.2f;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
private struct References
|
||||
{
|
||||
public Player Player;
|
||||
}
|
||||
|
||||
#region FIELDS
|
||||
|
||||
[SerializeField] private Settings _settings;
|
||||
[SerializeField] private References _references;
|
||||
|
||||
private Vector3 _velocity;
|
||||
|
||||
#endregion
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (!GetPlayer())
|
||||
return;
|
||||
|
||||
Vector3 targetPos = GetTargetPosition();
|
||||
|
||||
if (!Application.isPlaying || _settings.Smooth == 0)
|
||||
{
|
||||
transform.position = targetPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.position = Vector3.SmoothDamp(transform.position, targetPos, ref _velocity, _settings.Smooth);
|
||||
}
|
||||
}
|
||||
|
||||
private bool GetPlayer()
|
||||
{
|
||||
if (_references.Player)
|
||||
return true;
|
||||
|
||||
// In edit mode, Player.Awake has not run, so the singleton is empty
|
||||
else if (Player.Instance)
|
||||
_references.Player = Player.Instance;
|
||||
else
|
||||
_references.Player = FindFirstObjectByType<Player>();
|
||||
|
||||
return _references.Player != null;
|
||||
}
|
||||
|
||||
private Vector3 GetTargetPosition()
|
||||
{
|
||||
Quaternion rotation = Quaternion.Euler(0, _settings.Angle, 0);
|
||||
Vector3 offset = rotation * new Vector3(0, _settings.Offset.y, -_settings.Offset.x);
|
||||
return _references.Player.transform.position + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/Characters/PlayerCamera.cs.meta
Normal file
2
Assets/_Content/Scripts/Characters/PlayerCamera.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd78e931d0126914e8206e9f6bb2b9de
|
||||
16
Assets/_Content/Scripts/Characters/PlayerEvent.cs
Normal file
16
Assets/_Content/Scripts/Characters/PlayerEvent.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class PlayerEvent : MonoBehaviour
|
||||
{
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
2
Assets/_Content/Scripts/Characters/PlayerEvent.cs.meta
Normal file
2
Assets/_Content/Scripts/Characters/PlayerEvent.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3c874cb9bc4c364d87e100aada2b434
|
||||
Reference in New Issue
Block a user