173 lines
5.6 KiB
C#
173 lines
5.6 KiB
C#
|
using System;
|
|||
|
using System.Collections;
|
|||
|
using System.Collections.Generic;
|
|||
|
using UnityEngine;
|
|||
|
using UnityEngine.InputSystem;
|
|||
|
|
|||
|
namespace BNG {
|
|||
|
|
|||
|
public enum RotationMechanic {
|
|||
|
Snap,
|
|||
|
Smooth
|
|||
|
}
|
|||
|
public class PlayerRotation : MonoBehaviour {
|
|||
|
|
|||
|
[Header("Input")]
|
|||
|
[Tooltip("Set to false to skip Update")]
|
|||
|
public bool AllowInput = true;
|
|||
|
|
|||
|
[Tooltip("Used to determine whether to turn left / right. This can be an X Axis on the thumbstick, for example. -1 to snap left, 1 to snap right.")]
|
|||
|
public List<InputAxis> inputAxis = new List<InputAxis>() { InputAxis.RightThumbStickAxis };
|
|||
|
|
|||
|
[Tooltip("Unity Input Action used to rotate the player")]
|
|||
|
public InputActionReference RotateAction;
|
|||
|
|
|||
|
[Header("Smooth / Snap Turning")]
|
|||
|
[Tooltip("Snap rotation will rotate a fixed amount of degrees on turn. Smooth will linearly rotate the player.")]
|
|||
|
public RotationMechanic RotationType = RotationMechanic.Snap;
|
|||
|
|
|||
|
[Header("Snap Turn Settings")]
|
|||
|
[Tooltip("How many degrees to rotate if RotationType is set to 'Snap'")]
|
|||
|
public float SnapRotationAmount = 45f;
|
|||
|
|
|||
|
[Tooltip("Thumbstick X axis must be >= this amount to be considered an input event")]
|
|||
|
public float SnapInputAmount = 0.75f;
|
|||
|
|
|||
|
[Header("Smooth Turn Settings")]
|
|||
|
[Tooltip("How fast to rotate the player if RotationType is set to 'Smooth'")]
|
|||
|
public float SmoothTurnSpeed = 40f;
|
|||
|
|
|||
|
[Tooltip("Thumbstick X axis must be >= this amount to be considered an input event")]
|
|||
|
public float SmoothTurnMinInput = 0.1f;
|
|||
|
|
|||
|
float recentSnapTurnTime;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// How much to rotate this frame
|
|||
|
/// </summary>
|
|||
|
float rotationAmount = 0;
|
|||
|
|
|||
|
float xAxis;
|
|||
|
float previousXInput;
|
|||
|
|
|||
|
#region Events
|
|||
|
public delegate void OnBeforeRotateAction();
|
|||
|
public static event OnBeforeRotateAction OnBeforeRotate;
|
|||
|
|
|||
|
public delegate void OnAfterRotateAction();
|
|||
|
public static event OnAfterRotateAction OnAfterRotate;
|
|||
|
#endregion
|
|||
|
|
|||
|
void Update() {
|
|||
|
|
|||
|
if(!AllowInput) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
xAxis = GetAxisInput();
|
|||
|
|
|||
|
if (RotationType == RotationMechanic.Snap) {
|
|||
|
DoSnapRotation(xAxis);
|
|||
|
}
|
|||
|
|
|||
|
else if (RotationType == RotationMechanic.Smooth) {
|
|||
|
DoSmoothRotation(xAxis);
|
|||
|
}
|
|||
|
|
|||
|
// Store input for future checks
|
|||
|
previousXInput = xAxis;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Return a float between -1 and 1 to determine which direction to turn the character
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
public virtual float GetAxisInput() {
|
|||
|
|
|||
|
// Use the largest, non-zero value we find in our input list
|
|||
|
float lastVal = 0;
|
|||
|
|
|||
|
// Check Raw Input
|
|||
|
if(inputAxis != null) {
|
|||
|
for (int i = 0; i < inputAxis.Count; i++) {
|
|||
|
float axisVal = InputBridge.Instance.GetInputAxisValue(inputAxis[i]).x;
|
|||
|
|
|||
|
// Always take this value if our last entry was 0.
|
|||
|
if (lastVal == 0) {
|
|||
|
lastVal = axisVal;
|
|||
|
}
|
|||
|
else if (axisVal != 0 && axisVal > lastVal) {
|
|||
|
lastVal = axisVal;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Check Unity Input Action
|
|||
|
if(RotateAction != null) {
|
|||
|
float axisVal = RotateAction.action.ReadValue<Vector2>().x;
|
|||
|
// Always take this value if our last entry was 0.
|
|||
|
if (lastVal == 0) {
|
|||
|
lastVal = axisVal;
|
|||
|
}
|
|||
|
else if (axisVal != 0 && axisVal > lastVal) {
|
|||
|
lastVal = axisVal;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return lastVal;
|
|||
|
}
|
|||
|
|
|||
|
public virtual void DoSnapRotation(float xInput) {
|
|||
|
|
|||
|
// Reset rotation amount before retrieving inputs
|
|||
|
rotationAmount = 0;
|
|||
|
|
|||
|
// Snap Right
|
|||
|
if (xInput >= 0.1f && previousXInput < 0.1f) {
|
|||
|
rotationAmount += SnapRotationAmount;
|
|||
|
}
|
|||
|
// Snap Left
|
|||
|
else if (xInput <= -0.1f && previousXInput > -0.1f) {
|
|||
|
rotationAmount -= SnapRotationAmount;
|
|||
|
}
|
|||
|
|
|||
|
if(Math.Abs(rotationAmount) > 0) {
|
|||
|
|
|||
|
// Call any Before Rotation Events
|
|||
|
OnBeforeRotate?.Invoke();
|
|||
|
|
|||
|
// Apply rotation
|
|||
|
transform.rotation = Quaternion.Euler(new Vector3(transform.eulerAngles.x, transform.eulerAngles.y + rotationAmount, transform.eulerAngles.z));
|
|||
|
|
|||
|
recentSnapTurnTime = Time.time;
|
|||
|
|
|||
|
// Call any After Rotation Events
|
|||
|
OnAfterRotate?.Invoke();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public virtual bool RecentlySnapTurned() {
|
|||
|
return Time.time - recentSnapTurnTime <= 0.1f;
|
|||
|
}
|
|||
|
|
|||
|
public virtual void DoSmoothRotation(float xInput) {
|
|||
|
|
|||
|
// Reset rotation amount before retrieving inputs
|
|||
|
rotationAmount = 0;
|
|||
|
|
|||
|
// Smooth Rotate Right
|
|||
|
if (xInput >= SmoothTurnMinInput) {
|
|||
|
rotationAmount += xInput * SmoothTurnSpeed * Time.deltaTime;
|
|||
|
}
|
|||
|
// Smooth Rotate Left
|
|||
|
else if (xInput <= -SmoothTurnMinInput) {
|
|||
|
rotationAmount += xInput * SmoothTurnSpeed * Time.deltaTime;
|
|||
|
}
|
|||
|
|
|||
|
// Apply rotation
|
|||
|
transform.rotation = Quaternion.Euler(new Vector3(transform.eulerAngles.x, transform.eulerAngles.y + rotationAmount, transform.eulerAngles.z));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|