diff --git a/Assets/_Content/Scenes/Theatre.unity b/Assets/_Content/Scenes/Theatre.unity index 21178a74..b3da71e3 100644 --- a/Assets/_Content/Scenes/Theatre.unity +++ b/Assets/_Content/Scenes/Theatre.unity @@ -448,6 +448,17 @@ Transform: m_CorrespondingSourceObject: {fileID: 8725966219179855439, guid: 6493d77978c5c1246a0410d1f9204524, type: 3} m_PrefabInstance: {fileID: 1549040694} m_PrefabAsset: {fileID: 0} +--- !u!114 &57213877 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 5295567073180248356, guid: 6493d77978c5c1246a0410d1f9204524, type: 3} + m_PrefabInstance: {fileID: 1549040694} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c85c0434d95406f4da8daa149ba90838, type: 3} + m_Name: + m_EditorClassIdentifier: OctoCore.Runtime::OctoCore.Components.OctoPlayer --- !u!4 &58792973 stripped Transform: m_CorrespondingSourceObject: {fileID: 992638687589661580, guid: 8a998c00fc583a54082d05343d747b99, type: 3} @@ -2923,6 +2934,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: OctoCore.Runtime::OctoCore.OctoPlayerDrive _state: + ForcePlayerToFollowTarget: 0 MoveInfluence: 0 LookInfluence: 0 YawRange: 0 @@ -3002,6 +3014,18 @@ MonoBehaviour: m_StringArgument: m_BoolArgument: 0 m_CallState: 2 + - m_Target: {fileID: 654342081} + m_TargetAssemblyTypeName: OctoCore.Components.OctoPlayerDriver, OctoCore.Runtime + m_MethodName: ForcePlayerToFollowTarget + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 OnRelease: m_PersistentCalls: m_Calls: @@ -10902,7 +10926,7 @@ MonoBehaviour: _onTrigger: m_PersistentCalls: m_Calls: - - m_Target: {fileID: 0} + - m_Target: {fileID: 57213877} m_TargetAssemblyTypeName: OctoCore.Components.OctoPlayer, OctoCore.Runtime m_MethodName: Teleport m_Mode: 5 diff --git a/Assets/_Content/Scripts/Features/Player/Runtime/Camera/CameraEffects.cs b/Assets/_Content/Scripts/Features/Player/Runtime/Camera/CameraEffects.cs index a7308521..3ec8a84a 100644 --- a/Assets/_Content/Scripts/Features/Player/Runtime/Camera/CameraEffects.cs +++ b/Assets/_Content/Scripts/Features/Player/Runtime/Camera/CameraEffects.cs @@ -175,14 +175,14 @@ namespace Unheimlich.Features.Player float targetYaw = Mathf.Atan2(targetDirection.x, targetDirection.z) * Mathf.Rad2Deg; float targetPitch = -Mathf.Asin(targetDirection.y) * Mathf.Rad2Deg; - float currentYaw = PlayerController.Instance.Movement.Yaw; - float currentPitch = PlayerController.Instance.Movement.Pitch; + float currentYaw = PlayerController.Instance.Movement.State.Yaw; + float currentPitch = PlayerController.Instance.Movement.State.Pitch; float newYaw = Mathf.LerpAngle(currentYaw, targetYaw, Settings.aimAssistStrength * Time.deltaTime); float newPitch = Mathf.Lerp(currentPitch, targetPitch, Settings.aimAssistStrength * Time.deltaTime); - PlayerController.Instance.Movement.Yaw = newYaw; - PlayerController.Instance.Movement.Pitch = newPitch; + PlayerController.Instance.Movement.State.Yaw = newYaw; + PlayerController.Instance.Movement.State.Pitch = newPitch; } _hasAimAssistTarget = false; diff --git a/Packages/OctoCore/Runtime/Scripts/Components/OctoPlayer.cs b/Packages/OctoCore/Runtime/Scripts/Components/OctoPlayer.cs index 8026c694..37a4b578 100644 --- a/Packages/OctoCore/Runtime/Scripts/Components/OctoPlayer.cs +++ b/Packages/OctoCore/Runtime/Scripts/Components/OctoPlayer.cs @@ -35,6 +35,12 @@ namespace OctoCore.Components public PlayerModes Mode = PlayerModes.FirstPerson; public Orientations Orientation = Orientations.Camera; + [Tooltip("Allow position movement.")] + public bool AllowMove = true; + + [Tooltip("Allow looking around.")] + public bool AllowLook = true; + [Tooltip("Walk speed (km/h).")] public float WalkSpeed = 10; @@ -47,17 +53,8 @@ namespace OctoCore.Components [Tooltip("Maximum jump height reached at the apex (meters).")] public float JumpHeight = .4f; - [Tooltip("Maximum step height (meters).")] - public float StepHeight = 0.3f; - [Tooltip("Downward acceleration applied to the player (m/s²).")] public float Gravity = 9.8f; - - [Tooltip("Enable jump.")] - public bool CanJump = true; - - [Tooltip("Enable sprint.")] - public bool CanRun = true; } [System.Serializable] @@ -111,37 +108,9 @@ namespace OctoCore.Components private Vector3 _moveDirection; public bool IsPaused => State.IsPaused; - public float Radius => _references.Controller ? _references.Controller.radius : 0; + public float Radius => _references.Controller ? _references.Controller.radius : 0; public FirstPerson _FirstPerson => _firstPerson; - /// True when the player is actively sprinting (inertia > 0.1 and CanRun enabled). - public bool IsRunning => _settings.CanRun && _runInertia > 0.1f; - - // Public access to yaw and pitch for external aim assist systems - public float Yaw - { - get => State.Yaw; - set => State.Yaw = value; - } - - public float Pitch - { - get => State.Pitch; - set => State.Pitch = Mathf.Clamp(value, _firstPerson.MinPitch, _firstPerson.MaxPitch); - } - - public bool CanJump - { - get => _settings.CanJump; - set => _settings.CanJump = value; - } - - public bool CanRun - { - get => _settings.CanRun; - set => _settings.CanRun = value; - } - void OnEnable() { if (!Instance) Instance = this; @@ -212,44 +181,43 @@ namespace OctoCore.Components OctoCore.Instance.UI.SetCursor(); } + public void AllowMove(bool allow) { _settings.AllowMove = allow; } + public void Drive(OctoPlayerDriver driver) { State.Driver = driver; } public void ReleaseDrive() { State.Driver = null; } - public void SetYaw(float yaw) { State.Yaw = yaw; } - public void SetPitch(float pitch) { State.Pitch = pitch; } - - // Convenience methods for external scripts - public void SetCanJump(bool value) => _settings.CanJump = value; - public void SetCanRun(bool value) => _settings.CanRun = value; + public void SetYaw(float yaw) { State.Yaw = yaw; } + public void SetPitch(float pitch) { State.Yaw = pitch; } private void Move(Vector2 value) { _moveInput = value; } private void Look(Vector2 value) { _lookInput = value; } - private void Run() { _runInput = true; } + private void Run() { _runInput = true; } private void Jump() { _jumpInput = true; } private void HandleFocus() { bool escapePressed = false; - bool mouseClicked = false; + bool mouseClicked = false; #if ENABLE_INPUT_SYSTEM escapePressed = Keyboard.current != null && Keyboard.current.escapeKey.wasPressedThisFrame; - mouseClicked = + mouseClicked = Mouse.current != null && ( - Mouse.current.leftButton.wasPressedThisFrame || - Mouse.current.rightButton.wasPressedThisFrame || - Mouse.current.middleButton.wasPressedThisFrame || + Mouse.current.leftButton.wasPressedThisFrame || + Mouse.current.rightButton.wasPressedThisFrame || + Mouse.current.middleButton.wasPressedThisFrame || Mouse.current.forwardButton.wasPressedThisFrame || Mouse.current.backButton.wasPressedThisFrame ); #else escapePressed = Input.GetKeyDown(KeyCode.Escape); - mouseClicked = + mouseClicked = Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1) || Input.GetMouseButtonDown(2); #endif + if (!Application.isFocused || escapePressed) { if (State.IsFocussed) @@ -269,130 +237,93 @@ namespace OctoCore.Components private void HandleMovement() { - _moveInput = (State.IsPaused || !State.IsFocussed) ? Vector2.zero : Vector2.ClampMagnitude(_moveInput, 1); - Camera cam = (_firstPerson.Camera && _firstPerson.Camera.enabled && _firstPerson.Camera.gameObject.activeInHierarchy) - ? _firstPerson.Camera - : Camera.main; + _moveInput = (State.IsPaused || !State.IsFocussed || !_settings.AllowMove) ? Vector2.zero : Vector2.ClampMagnitude(_moveInput, 1); + Camera cam = (_firstPerson.Camera && _firstPerson.Camera.enabled && _firstPerson.Camera.gameObject.activeInHierarchy) ? _firstPerson.Camera : Camera.main; bool accelerating = _moveInput.magnitude > .1f; - bool isGrounded = _references.Controller ? _references.Controller.isGrounded : true; - float t = Time.deltaTime / 3.6f; + bool isGrounded = _references.Controller ? _references.Controller.isGrounded : true; + float t = Time.deltaTime / 3.6f; - // ── Move ──────────────────────────────────────────────────────────── + // Move Vector3 move = new Vector3(_moveInput.x, 0, _moveInput.y); if (_settings.Orientation == Orientations.Camera && cam) { - Vector3 camForward = cam.transform.forward; camForward.y = 0; camForward.Normalize(); - Vector3 camRight = cam.transform.right; camRight.y = 0; camRight.Normalize(); + Vector3 camForward = cam.transform.forward; + camForward.y = 0; + camForward.Normalize(); + + Vector3 camRight = cam.transform.right; + camRight.y = 0; + camRight.Normalize(); + move = camRight * move.x + camForward * move.z; } if (State.Driver) - State.Driver.ApplyMoveInfluence(move, move.magnitude * t, out move); + State.Driver.ApplyMoveInfluence(move, t, out move); float deltaSmooth = t * (accelerating ? 30 : 15); _moveDirection = Vector3.Lerp(_moveDirection, move, deltaSmooth * 1.5f); deltaSmooth *= 1 - Vector3.Cross(_moveInertia, _moveDirection).magnitude; - _moveInertia = Vector3.Lerp(_moveInertia, move, deltaSmooth); + _moveInertia = Vector3.Lerp(_moveInertia, move, deltaSmooth); if (!accelerating && _moveInertia.magnitude < .01f) _moveInertia = Vector3.zero; - // Sprint inertia — clamped to 0 if CanRun is off - _runInertia = Mathf.Lerp( - _runInertia, - (_runInput && _settings.CanRun) ? 1f : 0f, - t * (accelerating ? 5 : 3) - ); - State.IsRunning = IsRunning; + _runInertia = Mathf.Lerp(_runInertia, _runInput ? 1 : 0, t * (accelerating ? 5 : 3)); + State.IsRunning = _runInertia > .1f; Vector3 moveDelta = _moveInertia * t * Mathf.Lerp(_settings.WalkSpeed, _settings.RunSpeed, _runInertia); - // ── Jump ──────────────────────────────────────────────────────────── - - if (isGrounded && _jumpInput && !_jumpping && _settings.CanJump) + if (isGrounded && _jumpInput && !_jumpping) { - _jumpInput = false; - _jumpping = true; - _jumpLerp = 0; - _jumpTime = Time.timeSinceLevelLoad; + _jumpInput = false; + _jumpping = true; + _jumpLerp = 0; + _jumpTime = Time.timeSinceLevelLoad; _jumpAltitude = transform.position.y; } - // Consume the input even if CanJump is off, so it doesn't queue up - if (_jumpInput && !_settings.CanJump) _jumpInput = false; - float jumpOffset = 0; if (_jumpping) { _jumpInput = false; - _jumpLerp = (Time.timeSinceLevelLoad - _jumpTime) / _settings.JumpDuration; + _jumpLerp = (Time.timeSinceLevelLoad - _jumpTime) / _settings.JumpDuration; - // FIX: added 0.15s grace period before checking isGrounded to avoid immediate re-trigger - bool landingAllowed = (Time.timeSinceLevelLoad - _jumpTime) > 0.15f; - - if (_jumpLerp >= 1 || (_jumpLerp > .5f && isGrounded && landingAllowed)) + if (_jumpLerp >= 1 || (_jumpLerp > .3f && isGrounded)) { _jumpping = false; _jumpLerp = 0; } else { - float x = _jumpLerp * 2 - 1f; - float y = x < 0 - ? Mathf.Sqrt(1f - x * x) - : Mathf.Cos(x * .5f * Mathf.PI); + float x = _jumpLerp; + x = x * 2 - 1; + + float y; + if (x < 0) y = Mathf.Sqrt(1f - x * x); + else y = Mathf.Cos(x * .5f * Mathf.PI); + + y = _jumpAltitude + y * _settings.JumpHeight; - y = _jumpAltitude + y * _settings.JumpHeight; jumpOffset = y - transform.position.y; } } - // ── Step-up ───────────────────────────────────────────────────────── - - if (_references.Controller && isGrounded && !_jumpping) - { - float feetY = transform.position.y - (_references.Controller.height * 0.5f); - float castFromY = feetY + _settings.StepHeight; - - Vector3 stepOrigin = new Vector3(transform.position.x, castFromY, transform.position.z); - Vector3 stepDir = new Vector3(moveDelta.x, 0, moveDelta.z).normalized; - - if (stepDir.magnitude > 0.1f) - { - float stepDist = _references.Controller.radius + 0.05f; - - if (!Physics.Raycast(stepOrigin, stepDir, stepDist)) - { - Vector3 probeOrigin = stepOrigin + stepDir * stepDist; - if (Physics.Raycast(probeOrigin, Vector3.down, out RaycastHit hit, _settings.StepHeight)) - { - float stepUp = hit.point.y - feetY; - if (stepUp > 0.05f) - moveDelta.y = Mathf.Max(moveDelta.y, stepUp); - } - } - } - } - - // ── Apply ─────────────────────────────────────────────────────────── - if (_jumpping) moveDelta.y = jumpOffset; - else if (!isGrounded) - moveDelta.y -= _settings.Gravity * Time.deltaTime; else - moveDelta.y = -0.1f; + moveDelta.y -= _settings.Gravity * Time.deltaTime; if (_references.Controller && _references.Controller.enabled) _references.Controller.Move(moveDelta); else transform.position += moveDelta; - // ── Rotate ────────────────────────────────────────────────────────── + // Rotate switch (_settings.Mode) { @@ -401,17 +332,23 @@ namespace OctoCore.Components { Vector2 delta = (State.IsPaused || !State.IsFocussed) ? Vector2.zero : _lookInput; - float mouseX = delta.x * _firstPerson.SensitivityX; - float mouseY = delta.y * _firstPerson.SensitivityY * -1; + if (_settings.AllowLook) + { + float mouseX = delta.x * _firstPerson.SensitivityX; + float mouseY = delta.y * _firstPerson.SensitivityY * -1; - State.Yaw += mouseX; - State.Pitch = Mathf.Clamp(State.Pitch + mouseY, _firstPerson.MinPitch, _firstPerson.MaxPitch); + State.Yaw += mouseX; + State.Pitch = Mathf.Clamp(State.Pitch + mouseY, _firstPerson.MinPitch, _firstPerson.MaxPitch); + } if (State.Driver) State.Driver.ApplyLookInfluence(State.Yaw, State.Pitch, Time.deltaTime, out State.Yaw, out State.Pitch); - transform.rotation = Quaternion.Euler(0, State.Yaw, 0); - cam.transform.localRotation = Quaternion.Euler(State.Pitch, 0, 0); + Quaternion YawRot = Quaternion.Euler(0, State.Yaw, 0); + Quaternion PitchRot = Quaternion.Euler(State.Pitch, 0, 0); + + transform.rotation = YawRot; + cam.transform.localRotation = PitchRot; } break; @@ -421,22 +358,22 @@ namespace OctoCore.Components if (_moveInertia.magnitude > .002f) { Vector3 offset = _moveInertia - _moveDirection; - offset *= _moveInertia.magnitude * _runInertia; - offset = Vector3.ClampMagnitude(offset, 1f); - Vector3 up = (Vector3.up - offset).normalized; + offset *= _moveInertia.magnitude * _runInertia; + offset = Vector3.ClampMagnitude(offset * 1f, 1f); + Vector3 up = (Vector3.up - offset).normalized; Quaternion lookRot = Quaternion.LookRotation(_moveInertia, up); - targetRot = Quaternion.Lerp(targetRot, lookRot, t * 30); + targetRot = Quaternion.Lerp(targetRot, lookRot, t * 30); } transform.rotation = targetRot; break; } } - // ── Reset ─────────────────────────────────────────────────────────── + // Reset _moveInput = Vector2.zero; _lookInput = Vector2.zero; - _runInput = false; + _runInput = false; } private void SetMode() @@ -452,5 +389,11 @@ namespace OctoCore.Components break; } } + + /*public static float Arc(float x) + { + x = Mathf.Clamp01(x) * 2 - 1f; + return Mathf.Sqrt(1f - x * x); + }*/ } } \ No newline at end of file diff --git a/Packages/OctoCore/Runtime/Scripts/Components/OctoPlayerDriver.cs b/Packages/OctoCore/Runtime/Scripts/Components/OctoPlayerDriver.cs index fa1507a1..32ca607c 100644 --- a/Packages/OctoCore/Runtime/Scripts/Components/OctoPlayerDriver.cs +++ b/Packages/OctoCore/Runtime/Scripts/Components/OctoPlayerDriver.cs @@ -8,6 +8,7 @@ namespace OctoCore.Components [System.Serializable] public class State { + public bool ForcePlayerToFollowTarget; [Range(0, 1)] public float MoveInfluence; [Range(0, 1)] public float LookInfluence; [Range(0, 180)] public float YawRange = 180; @@ -91,6 +92,11 @@ namespace OctoCore.Components _events.OnDrive?.Invoke(); } + public void ForcePlayerToFollowTarget(bool force) + { + _state.ForcePlayerToFollowTarget = force; + } + public void ReleasePlayer() { OctoPlayer.Instance.ReleaseDrive(); @@ -109,7 +115,7 @@ namespace OctoCore.Components return; } - _state.MoveInfluence = Mathf.Clamp01(_state.MoveInfluence + delta * _settings.DriveStrength); + _state.MoveInfluence = Mathf.Clamp01(_state.MoveInfluence + delta * (_state.ForcePlayerToFollowTarget ? 1 : inMove.magnitude) * _settings.DriveStrength); float moveInfluence = _settings.DriveCurve.Evaluate(_state.MoveInfluence); if (!_fullInfluenceReached && _state.MoveInfluence >= 1) @@ -126,7 +132,7 @@ namespace OctoCore.Components Vector3 driveMove = offset; driveMove.y = 0; - driveMove = driveMove.normalized * inMove.magnitude; + driveMove = driveMove.normalized * (_state.ForcePlayerToFollowTarget ? 1 : inMove.magnitude); driveMove = Vector3.Lerp(driveMove, Vector3.zero, driveAtten); outMove = Vector3.Lerp(inMove, driveMove, moveInfluence);