unity dark mode asset, changes to player locomotion, camera bobbing
This commit is contained in:
@@ -8,7 +8,6 @@ namespace RealityReboot.jelycho.Player {
|
||||
[SerializeField] float m_ForwardAngularDisplacement = 1.0f;
|
||||
[SerializeField] float m_SidewaysAngularDisplacement = 1.0f;
|
||||
[SerializeField] float m_HeightAngularDisplacement = 2.0f;
|
||||
[SerializeField] float m_LinearDisplacement = 0.05f;
|
||||
|
||||
Vector3 m_SpringPosition;
|
||||
Vector3 m_SpringVelocity;
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using RebootKit.Engine.Foundation;
|
||||
using System;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Services.Simulation.Sensors;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Assertions;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace RealityReboot.jelycho.Player {
|
||||
[AddComponentMenu(GameConsts.k_AddComponentMenu + "Player/First Person Camera")]
|
||||
@@ -9,34 +12,47 @@ namespace RealityReboot.jelycho.Player {
|
||||
[ConfigVar("fpp.camera.fov", 60.0f, "Field of view for the first person camera.")]
|
||||
static ConfigVar s_cameraFOV;
|
||||
|
||||
[SerializeField] float _pickDistance = 5.0f;
|
||||
|
||||
[SerializeField] LayerMask _pickLayer;
|
||||
|
||||
[Header("Base")]
|
||||
[field: SerializeField]
|
||||
public float Sensitivity { get; set; }
|
||||
|
||||
[SerializeField] float _pitchMin = -80f;
|
||||
|
||||
[SerializeField] float _pitchMax = 80f;
|
||||
|
||||
[SerializeField] float m_PitchMin = -80f;
|
||||
[SerializeField] float m_PitchMax = 80f;
|
||||
|
||||
[field: SerializeField]
|
||||
public CinemachineCamera Camera { get; private set; }
|
||||
|
||||
readonly RaycastSensor _raycastSensor = new();
|
||||
CinemachineBasicMultiChannelPerlin m_BobbingNoiseComponent;
|
||||
|
||||
[SerializeField] float m_BobbingFrequency = 0.5f;
|
||||
[SerializeField] float m_BobbingAmplitude = 0.75f;
|
||||
|
||||
[Header("Picking")]
|
||||
[SerializeField] float m_PickDistance = 5.0f;
|
||||
[SerializeField] LayerMask m_PickLayer;
|
||||
|
||||
readonly RaycastSensor m_RaycastSensor = new();
|
||||
|
||||
public float Pitch { get; private set; }
|
||||
public float Yaw { get; private set; }
|
||||
|
||||
public ISensor Sensor {
|
||||
get {
|
||||
_raycastSensor.ray = new Ray(Camera.transform.position, Camera.transform.forward);
|
||||
_raycastSensor.maxDistance = _pickDistance;
|
||||
_raycastSensor.layerMask = _pickLayer;
|
||||
return _raycastSensor;
|
||||
m_RaycastSensor.ray = new Ray(Camera.transform.position, Camera.transform.forward);
|
||||
m_RaycastSensor.maxDistance = m_PickDistance;
|
||||
m_RaycastSensor.layerMask = m_PickLayer;
|
||||
return m_RaycastSensor;
|
||||
}
|
||||
}
|
||||
|
||||
void Awake() {
|
||||
m_BobbingNoiseComponent =
|
||||
Camera.GetCinemachineComponent(CinemachineCore.Stage.Noise) as CinemachineBasicMultiChannelPerlin;
|
||||
Assert.IsNotNull(m_BobbingNoiseComponent);
|
||||
|
||||
SetBobbing(0.0f);
|
||||
}
|
||||
|
||||
public void Tick() {
|
||||
Camera.Lens.FieldOfView = s_cameraFOV.FloatValue;
|
||||
Camera.transform.localRotation = Quaternion.Euler(Pitch, 0f, 0f);
|
||||
@@ -46,7 +62,7 @@ namespace RealityReboot.jelycho.Player {
|
||||
float sens = Sensitivity;
|
||||
|
||||
Pitch -= y * sens;
|
||||
Pitch = Mathf.Clamp(Pitch, _pitchMin, _pitchMax);
|
||||
Pitch = Mathf.Clamp(Pitch, m_PitchMin, m_PitchMax);
|
||||
|
||||
Yaw += x * sens;
|
||||
}
|
||||
@@ -55,5 +71,10 @@ namespace RealityReboot.jelycho.Player {
|
||||
Pitch = Mathf.Asin(-forward.y) * Mathf.Rad2Deg;
|
||||
Yaw = Mathf.Atan2(forward.x, forward.z) * Mathf.Rad2Deg;
|
||||
}
|
||||
|
||||
public void SetBobbing(float t) {
|
||||
m_BobbingNoiseComponent.AmplitudeGain = m_BobbingAmplitude * t;
|
||||
m_BobbingNoiseComponent.FrequencyGain = m_BobbingFrequency * t;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,17 @@ namespace RealityReboot.jelycho.Player {
|
||||
[SerializeField] FPPCamera m_Camera;
|
||||
[SerializeField] CameraSpring m_CameraSpring;
|
||||
|
||||
[SerializeField, Range(0.0f, 1.0f), Tooltip("Percentage of run speed")]
|
||||
float m_EnableCameraBobbingPercentThreshold = 0.5f;
|
||||
|
||||
[SerializeField] float m_SprintCameraBobbing = 1.0f;
|
||||
[SerializeField] float m_RunCameraBobbing = 0.5f;
|
||||
[SerializeField] float m_IdleCameraBobbing = 0.0f;
|
||||
[SerializeField] float m_CameraBobbingTransitionSpeed = 5.0f;
|
||||
|
||||
float m_TargetCameraBobbing = 0.0f;
|
||||
float m_CurrentCameraBobbing = 0.0f;
|
||||
|
||||
[Header("Dragging")]
|
||||
[SerializeField] Transform m_DragGutStartPosition;
|
||||
[SerializeField] PhysicsObjectDragger m_PhysicsDragger;
|
||||
@@ -29,10 +40,29 @@ namespace RealityReboot.jelycho.Player {
|
||||
}
|
||||
|
||||
public override void OnTick() {
|
||||
m_Locomotion.YawRotation = m_Camera.Yaw;
|
||||
m_Camera.Tick();
|
||||
|
||||
m_PhysicsDragger.TargetWorldPosition = m_Camera.Camera.transform.position + m_Camera.Camera.transform.forward * 2.0f;
|
||||
m_Locomotion.YawRotation = m_Camera.Yaw;
|
||||
|
||||
// Camera bobbing
|
||||
if (m_Locomotion.IsGrounded &&
|
||||
m_Locomotion.SpeedXZ >= m_Locomotion.runSpeed * m_EnableCameraBobbingPercentThreshold) {
|
||||
if (m_Locomotion.IsSprinting) {
|
||||
m_TargetCameraBobbing = m_SprintCameraBobbing;
|
||||
} else {
|
||||
m_TargetCameraBobbing = m_RunCameraBobbing;
|
||||
}
|
||||
} else {
|
||||
m_TargetCameraBobbing = m_IdleCameraBobbing;
|
||||
}
|
||||
|
||||
m_CurrentCameraBobbing = Mathf.MoveTowards(m_CurrentCameraBobbing,
|
||||
m_TargetCameraBobbing,
|
||||
m_CameraBobbingTransitionSpeed * Time.deltaTime);
|
||||
m_Camera.SetBobbing(m_CurrentCameraBobbing);
|
||||
|
||||
m_PhysicsDragger.TargetWorldPosition = m_Camera.Camera.transform.position +
|
||||
m_Camera.Camera.transform.forward * 2.0f;
|
||||
|
||||
if (m_PhysicsDragger.Current.OrNull() is not null) {
|
||||
m_LineRenderer.enabled = true;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using KinematicCharacterController;
|
||||
using RebootKit.Engine.Extensions;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using Logger = RebootKit.Engine.Foundation.Logger;
|
||||
@@ -8,17 +10,18 @@ using Logger = RebootKit.Engine.Foundation.Logger;
|
||||
namespace RealityReboot.jelycho.Player {
|
||||
public class PlayerFPPLocomotion : MonoBehaviour, ICharacterController {
|
||||
static readonly Logger s_logger = new(nameof(PlayerFPPLocomotion));
|
||||
|
||||
[ConfigVar("fpp.show_debug", 1)]
|
||||
static ConfigVar s_showDebug;
|
||||
|
||||
[SerializeField] KinematicCharacterMotor m_Motor;
|
||||
|
||||
public float runSpeed = 10.0f;
|
||||
public float sprintSpeed = 20.0f;
|
||||
|
||||
public float groundAcceleration = 10.0f;
|
||||
public float acceleration = 8.0f;
|
||||
public float groundFriction = 10.0f;
|
||||
|
||||
public float airFriction = 1.0f;
|
||||
|
||||
public float jumpHeight = 2.0f;
|
||||
public float jumpInputDuration = 0.2f;
|
||||
public float coyoteDuration = 0.2f;
|
||||
@@ -29,14 +32,31 @@ namespace RealityReboot.jelycho.Player {
|
||||
public float YawRotation { get; set; }
|
||||
|
||||
Vector3 m_WishDir;
|
||||
bool m_IsSprinting;
|
||||
|
||||
public bool IsSprinting {
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] get;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] private set;
|
||||
}
|
||||
|
||||
bool m_IsJumpRequested;
|
||||
float m_JumpRequestedTime;
|
||||
float m_LastGroundedTime;
|
||||
|
||||
Vector3 m_LastVelocity;
|
||||
|
||||
public bool IsGrounded => m_Motor.GroundingStatus.IsStableOnGround;
|
||||
public bool IsGrounded {
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get {
|
||||
return m_Motor.GroundingStatus.IsStableOnGround;
|
||||
}
|
||||
}
|
||||
|
||||
public float SpeedXZ {
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get {
|
||||
return m_Motor.Velocity.With(y: 0.0f).magnitude;
|
||||
}
|
||||
}
|
||||
|
||||
void Awake() {
|
||||
m_Motor.CharacterController = this;
|
||||
@@ -47,20 +67,36 @@ namespace RealityReboot.jelycho.Player {
|
||||
Gizmos.DrawLine(transform.position,
|
||||
transform.position + m_WishDir * 2.0f);
|
||||
}
|
||||
|
||||
static GUIStyle s_debugLabelStyle;
|
||||
|
||||
void OnGUI() {
|
||||
if (s_showDebug.IndexValue == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (s_debugLabelStyle == null) {
|
||||
s_debugLabelStyle = new GUIStyle(GUI.skin.label) {
|
||||
fontSize = 20,
|
||||
normal = { textColor = Color.white },
|
||||
alignment = TextAnchor.LowerLeft
|
||||
};
|
||||
}
|
||||
|
||||
GUI.Label(new Rect(0, 0, Screen.width, Screen.height),
|
||||
$"Wish Direction: {m_WishDir}\n" +
|
||||
$"Is Grounded: {m_Motor.GroundingStatus.IsStableOnGround}\n" +
|
||||
$"Is Jump Requested: {m_IsJumpRequested}\n" +
|
||||
$"Motor Velocity: {m_Motor.Velocity}, magnitude: {m_Motor.Velocity.magnitude}\n" +
|
||||
$"Motor Base Velocity: {m_Motor.BaseVelocity}, magnitude: {m_Motor.BaseVelocity.magnitude}\n" +
|
||||
$"Last Velocity: {m_LastVelocity}, magnitude: {math.length(m_LastVelocity)}\n");
|
||||
$"Last Velocity: {m_LastVelocity}, magnitude: {math.length(m_LastVelocity)}\n" +
|
||||
$"XZ Last Velocity: {m_LastVelocity.With(y: 0.0f).magnitude}",
|
||||
s_debugLabelStyle);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetWishDirection(Vector3 dir) {
|
||||
m_WishDir = dir;
|
||||
m_WishDir = dir.normalized;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -71,7 +107,7 @@ namespace RealityReboot.jelycho.Player {
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetSprint(bool isSprinting) {
|
||||
m_IsSprinting = isSprinting;
|
||||
IsSprinting = isSprinting;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -88,38 +124,65 @@ namespace RealityReboot.jelycho.Player {
|
||||
float control,
|
||||
float deltaTime) {
|
||||
float currentSpeed = Vector3.Dot(currentVelocity, m_WishDir);
|
||||
|
||||
|
||||
float addSpeed = wishSpeed - currentSpeed;
|
||||
if (addSpeed <= 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
float accelSpeed = groundAcceleration * deltaTime * wishSpeed;
|
||||
float accelSpeed = acceleration * deltaTime * wishSpeed;
|
||||
if (accelSpeed > addSpeed) {
|
||||
accelSpeed = addSpeed;
|
||||
}
|
||||
|
||||
currentVelocity += accelSpeed * control * m_WishDir;
|
||||
}
|
||||
|
||||
void AirAccelerate(ref Vector3 currentVelocity,
|
||||
float deltaTime) {
|
||||
float wishSpeed = currentVelocity.magnitude;
|
||||
if (wishSpeed >= runSpeed) {
|
||||
wishSpeed = runSpeed;
|
||||
}
|
||||
|
||||
float currentSpeed = Vector3.Dot(currentVelocity, m_WishDir);
|
||||
float addSpeed = wishSpeed - currentSpeed;
|
||||
if (addSpeed <= 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
float accelSpeed = deltaTime * wishSpeed;
|
||||
if (accelSpeed > addSpeed) {
|
||||
accelSpeed = addSpeed;
|
||||
}
|
||||
|
||||
currentVelocity += accelSpeed * control * m_WishDir;
|
||||
currentVelocity += accelSpeed * m_WishDir;
|
||||
}
|
||||
|
||||
void ApplyFriction(ref Vector3 currentVelocity, float friction, float deltaTime) {
|
||||
float speed = currentVelocity.magnitude;
|
||||
float speed = currentVelocity.With(y: 0.0f).magnitude;
|
||||
if (speed <= 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
float drop = speed * friction * deltaTime;
|
||||
if (drop < speed) {
|
||||
currentVelocity *= (speed - drop) / speed;
|
||||
} else {
|
||||
currentVelocity = Vector3.zero;
|
||||
float stopSpeed = 12.0f;
|
||||
float control = speed < stopSpeed ? stopSpeed : speed;
|
||||
float newSpeed = speed - friction * control * deltaTime;
|
||||
|
||||
if (newSpeed <= 0.0f) {
|
||||
newSpeed = 0.0f;
|
||||
}
|
||||
newSpeed /= speed;
|
||||
|
||||
currentVelocity.x *= newSpeed;
|
||||
currentVelocity.z *= newSpeed;
|
||||
}
|
||||
|
||||
void GroundMovement(ref Vector3 currentVelocity, float deltaTime) {
|
||||
float wishSpeed = m_IsSprinting ? sprintSpeed : runSpeed;
|
||||
Accelerate(ref currentVelocity, wishSpeed, 1.0f, deltaTime);
|
||||
float wishSpeed = IsSprinting ? sprintSpeed : runSpeed;
|
||||
|
||||
ApplyFriction(ref currentVelocity, groundFriction, deltaTime);
|
||||
Accelerate(ref currentVelocity, wishSpeed, 1.0f, deltaTime);
|
||||
}
|
||||
|
||||
void ApplyGravity(ref Vector3 currentVelocity, float deltaTime) {
|
||||
@@ -149,9 +212,7 @@ namespace RealityReboot.jelycho.Player {
|
||||
if (m_Motor.GroundingStatus.IsStableOnGround) {
|
||||
GroundMovement(ref currentVelocity, deltaTime);
|
||||
} else {
|
||||
Accelerate(ref currentVelocity, runSpeed, airControl, deltaTime);
|
||||
ApplyFriction(ref currentVelocity, airFriction, deltaTime);
|
||||
|
||||
AirAccelerate(ref currentVelocity, deltaTime);
|
||||
ApplyGravity(ref currentVelocity, deltaTime);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace RealityReboot.jelycho {
|
||||
void Start() {
|
||||
Clear();
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
AddSegment();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user