fixed movement and dash constraints

This commit is contained in:
Nilton Constantino 2026-06-05 09:30:56 +01:00
parent 6cfb53adc6
commit f9fe2728ca
No known key found for this signature in database
22 changed files with 167 additions and 40 deletions

View File

@ -2996,6 +2996,7 @@ GameObject:
serializedVersion: 6
m_Component:
- component: {fileID: 1179841130}
- component: {fileID: 1179841131}
- component: {fileID: 1179841129}
m_Layer: 0
m_Name: Brain
@ -3018,6 +3019,7 @@ MonoBehaviour:
m_EditorClassIdentifier: Assembly-CSharp::Intrepid.Gameplay.Entities.Sentinel.SentinelBrain
subscriptionId: 53c694ecee4d49be8b1852bf3047ed0e
rootEntity: {fileID: 1478155985}
controls: {fileID: 1179841131}
--- !u!4 &1179841130
Transform:
m_ObjectHideFlags: 0
@ -3034,6 +3036,20 @@ Transform:
- {fileID: 1809909214}
m_Father: {fileID: 2054429927}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1179841131
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1179841128}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c03b6f34733d48c18d0373cc1ca3d338, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::Intrepid.Gameplay.Entities.Sentinel.SentinelControls
dashBreakingThreshold: 2
dashCounter: 0
--- !u!1 &1187971235
GameObject:
m_ObjectHideFlags: 0
@ -3209,8 +3225,8 @@ MonoBehaviour:
Damping: {x: 1, y: 0, z: 1}
Lookahead:
Enabled: 1
Time: 0.5
Smoothing: 15
Time: 0.3
Smoothing: 10
IgnoreY: 1
--- !u!114 &1223120093
MonoBehaviour:
@ -5794,6 +5810,7 @@ MonoBehaviour:
dashLanding: {fileID: 9206814923105168154, guid: 208cb7d0ce6444ed7b55f4c4b4e632aa, type: 3}
speed: 15
targetTime: 0.2
dashMaxAngleFromForward: 60
--- !u!1 &2128748248
GameObject:
m_ObjectHideFlags: 0

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 608292f83d96477ebe6397a317ea947f
timeCreated: 1779259704

View File

@ -2,19 +2,25 @@ using Intrepid.Core.Entities;
using Intrepid.Gameplay.Entities.Sentinel.StateMachine;
using Intrepid.Integration.Input;
using Intrepid.Structures;
using Intrepid.Utilities;
using UnityEngine;
namespace Intrepid.Gameplay.Entities.Sentinel
{
public class SentinelBrain : EntityBrain
{
[GroupInjections, SerializeField] private SentinelControls controls;
protected SentinelStateMachine StateMachine { get; private set; }
public SentinelEntity Entity => RootEntity as SentinelEntity;
public SentinelInputs Inputs => InputService.Instance.BuildSentinelInputs();
public SentinelInputs Inputs { get; private set; }
public SentinelStateType CurrentState => StateMachine.CurrentImplementation.GetStateKey();
public SentinelControls Controls => controls;
protected override void InitializeVariables()
{
Inputs = InputService.Instance.BuildSentinelInputs();
StateMachine = GetComponentInChildren<SentinelStateMachine>();
foreach (var sentinelState in GetComponentsInChildren<SentinelState>())
{

View File

@ -1,8 +1,19 @@
namespace Intrepid.Gameplay.Entities.Sentinel
{
public sealed class SentinelConstants
public static class SentinelConstants
{
public sealed class Parameters
public static class Thresholds
{
public static class Movement
{
public const float DeadZone = 0.1f;
public const float DeadZoneSqrt = DeadZone * DeadZone;
public const float WalkZone = 0.65f;
public const float WalkZoneSqrt = WalkZone * WalkZone;
}
}
public static class Parameters
{
public const string KnockdownForce = "KnockdownForce";
}

View File

@ -0,0 +1,28 @@
using Intrepid.Utilities;
using UnityEngine;
namespace Intrepid.Gameplay.Entities.Sentinel
{
public class SentinelControls : MonoBehaviour
{
[GroupConfigurations, SerializeField, Range(0, 3)] private int dashBreakingThreshold = 2;
[GroupDebug, SerializeField] private int dashCounter;
public int DashCounter => dashCounter;
public void DashCounterInc()
{
dashCounter++;
}
public void ResetDash()
{
dashCounter = 0;
}
public bool DashShouldBreak()
{
return DashCounter >= dashBreakingThreshold;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c03b6f34733d48c18d0373cc1ca3d338
timeCreated: 1780645811

View File

@ -1,4 +1,3 @@
using System;
using Intrepid.Core.Entities;
using Intrepid.GameManagers;
using Intrepid.Gameplay.Messages.Events;
@ -27,7 +26,7 @@ namespace Intrepid.Gameplay.Entities.Sentinel
public EntityModelAnimation ModelAnimation => modelAnimation;
public Vector2 DesiredVelocity { get; set; }
public Vector3 LinearVelocity { get; private set; }
public Vector2 Forward => new(_desiredForward.x, _desiredForward.z);
public Vector2 Forward => new Vector2(_desiredForward.x, _desiredForward.z).normalized;
public override void DeployEntity(Vector2 position)
{
@ -39,7 +38,7 @@ namespace Intrepid.Gameplay.Entities.Sentinel
public void ChangeOrientation(Vector2 direction)
{
if (direction.sqrMagnitude <= 0.01f)
if (direction.sqrMagnitude <= GonConstants.CommonZeroSqrt)
{
return;
}

View File

@ -8,8 +8,8 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
public class SentinelStateDash : SentinelState
{
[GroupConfigurations, SerializeField] private AnimationClip dash;
[GroupConfigurations, SerializeField, Range(0, 100)] private float speed = 30;
[GroupConfigurations, SerializeField, Range(0, 10)] private float targetTime = .15f;
[GroupConfigurations, SerializeField, Range(0, 100)] private float speed = 35;
[GroupConfigurations, SerializeField, Range(0, 10)] private float targetTime = .125f;
private Timer Timer { get; } = new();
@ -29,7 +29,7 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
protected override void RunOnEnter(ParameterStore parameterStore)
{
Brain.Entity.ChangeOrientation(Brain.Inputs.Movement());
Brain.Controls.DashCounterInc();
Brain.Entity.ModelAnimation.CrossFade(dash, 0.01f);
Timer.Start();
}

View File

@ -7,8 +7,8 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
public class SentinelStateDashBreaking : SentinelState
{
[GroupConfigurations, SerializeField] private AnimationClip dashBreaking;
[GroupConfigurations, SerializeField, Range(5, 30)] private float speed = 10;
[GroupConfigurations, SerializeField, Range(0, 2)] private float extraTime = 0.5f;
[GroupConfigurations, SerializeField, Range(5, 30)] private float speed = 5;
[GroupConfigurations, SerializeField, Range(0, 2)] private float extraTime = 0.4f;
[GroupConfigurations, SerializeField] private AnimationCurve speedCurve;
private Timer Timer { get; } = new();

View File

@ -8,7 +8,8 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
{
[GroupConfigurations, SerializeField] private AnimationClip dashLanding;
[GroupConfigurations, SerializeField, Range(0, 30)] private float speed = 15;
[GroupConfigurations, SerializeField, Range(0, 10)] private float targetTime = .25f;
[GroupConfigurations, SerializeField, Range(0, 10)] private float targetTime = .2f;
[GroupConfigurations, SerializeField, Range(15, 90)] private float dashMaxAngleFromForward = 60f;
private Timer Timer { get; } = new();
@ -30,6 +31,11 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
protected override void RunOnExit()
{
Timer.Stop();
var movement = Brain.Inputs.Movement();
var forward = Brain.Entity.Forward;
var direction = GonFunctions
.ConstrainDirectionToForwardCone(movement, forward, dashMaxAngleFromForward);
Brain.Entity.ChangeOrientation(direction);
}
public override void RunOnUpdate()
@ -37,7 +43,9 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
if (CheckDash()) return;
if (Timer.IsNotRunning)
{
Brain.ChangeState(SentinelStateType.DashBreaking);
Brain.ChangeState(Brain.Controls.DashShouldBreak()
? SentinelStateType.DashBreaking
: SentinelStateType.Idle);
return;
}
Timer.Update(Time.deltaTime);
@ -58,5 +66,10 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
}
return false;
}
}
}

View File

@ -7,6 +7,7 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
public class SentinelStateIdle : SentinelState
{
[GroupConfigurations, SerializeField] private AnimationClip idle;
private Vector2 Movement { get; set; }
public override SentinelStateType GetStateKey()
@ -20,6 +21,7 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
protected override void RunOnEnter(ParameterStore parameterStore)
{
Brain.Controls.ResetDash();
Brain.Entity.ModelAnimation.CrossFade(idle, 0.2f);
Brain.Entity.DesiredVelocity = Vector2.zero;
}
@ -45,10 +47,10 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
{
switch (Movement.sqrMagnitude)
{
case > 0.1f and < 0.65f:
case > SentinelConstants.Thresholds.Movement.DeadZoneSqrt and < SentinelConstants.Thresholds.Movement.WalkZoneSqrt:
Brain.ChangeState(SentinelStateType.Walk);
return true;
case >= 0.65f:
case >= SentinelConstants.Thresholds.Movement.WalkZoneSqrt:
Brain.ChangeState(SentinelStateType.Run);
return true;
default:

View File

@ -9,8 +9,8 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
[GroupConfigurations, SerializeField] private AnimationClip knockdown;
[GroupConfigurations, SerializeField] private AnimationClip knockout;
[GroupConfigurations, SerializeField] private float KnockoutTimeMultiplier = 0.1f;
[GroupConfigurations, SerializeField, Range(0, 3)] private float knockdownTime = 2.0f;
[GroupConfigurations, SerializeField, Range(0, 3)] private float recoverTime = 1.5f;
[GroupConfigurations, SerializeField, Range(0, 3)] private float knockdownTime = .1f;
[GroupConfigurations, SerializeField, Range(0, 3)] private float recoverTime = .5f;
private Vector2 KnockdownForce { get; set; }
private float KnockoutTime { get; set; }

View File

@ -27,6 +27,7 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
protected override void RunOnExit()
{
Brain.Entity.ChangeOrientation(Movement);
}
public override void RunOnUpdate()
@ -52,10 +53,10 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
{
switch (Movement.sqrMagnitude)
{
case <= 0.1f:
case <= SentinelConstants.Thresholds.Movement.DeadZoneSqrt:
Brain.ChangeState(SentinelStateType.Idle);
return true;
case < 0.65f:
case < SentinelConstants.Thresholds.Movement.WalkZoneSqrt:
Brain.ChangeState(SentinelStateType.Walk);
return true;
default:

View File

@ -27,6 +27,7 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
protected override void RunOnExit()
{
Brain.Entity.ChangeOrientation(Movement);
}
public override void RunOnUpdate()
@ -52,10 +53,10 @@ namespace Intrepid.Gameplay.Entities.Sentinel.StateMachine.States
{
switch (Movement.sqrMagnitude)
{
case <= 0.1f:
case <= SentinelConstants.Thresholds.Movement.DeadZoneSqrt:
Brain.ChangeState(SentinelStateType.Idle);
return true;
case >= 0.65f:
case >= SentinelConstants.Thresholds.Movement.WalkZoneSqrt:
Brain.ChangeState(SentinelStateType.Run);
return true;
default:

View File

@ -94,7 +94,7 @@ public partial class @InputActions: IInputActionCollection2, IDisposable
""actions"": [
{
""name"": ""Movement"",
""type"": ""Value"",
""type"": ""PassThrough"",
""id"": ""9e2d6670-978a-4e07-847e-8763e3a9a503"",
""expectedControlType"": ""Vector2"",
""processors"": """",
@ -126,7 +126,7 @@ public partial class @InputActions: IInputActionCollection2, IDisposable
{
""name"": ""2D Vector"",
""id"": ""247b8d8e-671f-4160-be10-4d99b4cf0661"",
""path"": ""2DVector"",
""path"": ""2DVector(mode=1)"",
""interactions"": """",
""processors"": """",
""groups"": """",
@ -140,7 +140,7 @@ public partial class @InputActions: IInputActionCollection2, IDisposable
""path"": ""<Keyboard>/w"",
""interactions"": """",
""processors"": """",
""groups"": """",
""groups"": "";Keyboard & Mouse"",
""action"": ""Movement"",
""isComposite"": false,
""isPartOfComposite"": true
@ -151,7 +151,7 @@ public partial class @InputActions: IInputActionCollection2, IDisposable
""path"": ""<Keyboard>/s"",
""interactions"": """",
""processors"": """",
""groups"": """",
""groups"": "";Keyboard & Mouse"",
""action"": ""Movement"",
""isComposite"": false,
""isPartOfComposite"": true
@ -162,7 +162,7 @@ public partial class @InputActions: IInputActionCollection2, IDisposable
""path"": ""<Keyboard>/a"",
""interactions"": """",
""processors"": """",
""groups"": """",
""groups"": "";Keyboard & Mouse"",
""action"": ""Movement"",
""isComposite"": false,
""isPartOfComposite"": true
@ -173,7 +173,7 @@ public partial class @InputActions: IInputActionCollection2, IDisposable
""path"": ""<Keyboard>/d"",
""interactions"": """",
""processors"": """",
""groups"": """",
""groups"": "";Keyboard & Mouse"",
""action"": ""Movement"",
""isComposite"": false,
""isPartOfComposite"": true

View File

@ -8,7 +8,7 @@
"actions": [
{
"name": "Movement",
"type": "Value",
"type": "PassThrough",
"id": "9e2d6670-978a-4e07-847e-8763e3a9a503",
"expectedControlType": "Vector2",
"processors": "",
@ -40,7 +40,7 @@
{
"name": "2D Vector",
"id": "247b8d8e-671f-4160-be10-4d99b4cf0661",
"path": "2DVector",
"path": "2DVector(mode=1)",
"interactions": "",
"processors": "",
"groups": "",
@ -54,7 +54,7 @@
"path": "<Keyboard>/w",
"interactions": "",
"processors": "",
"groups": "",
"groups": ";Keyboard & Mouse",
"action": "Movement",
"isComposite": false,
"isPartOfComposite": true
@ -65,7 +65,7 @@
"path": "<Keyboard>/s",
"interactions": "",
"processors": "",
"groups": "",
"groups": ";Keyboard & Mouse",
"action": "Movement",
"isComposite": false,
"isPartOfComposite": true
@ -76,7 +76,7 @@
"path": "<Keyboard>/a",
"interactions": "",
"processors": "",
"groups": "",
"groups": ";Keyboard & Mouse",
"action": "Movement",
"isComposite": false,
"isPartOfComposite": true
@ -87,7 +87,7 @@
"path": "<Keyboard>/d",
"interactions": "",
"processors": "",
"groups": "",
"groups": ";Keyboard & Mouse",
"action": "Movement",
"isComposite": false,
"isPartOfComposite": true

View File

@ -59,7 +59,7 @@ namespace Intrepid.Integration.Input
return new SentinelInputs
{
Movement = () => Locking.IsNotLocked
? InputActions.sentinel.Movement.ReadValue<Vector2>().normalized
? InputActions.sentinel.Movement.ReadValue<Vector2>()
: Vector2.zero,
Dash = () => Locking.IsNotLocked && InputActions.sentinel.Dash.WasPressedThisFrame(),
};

View File

@ -1,7 +1,10 @@
namespace Intrepid.Core
namespace Intrepid.Utilities
{
public static class GonConstants
{
public static float CommonZero => 0.001f;
public static float CommonZeroSqrt => CommonZero * CommonZero;
public static class ExecutionOrder
{
public const int ASAP = -10000;

View File

@ -0,0 +1,20 @@
using UnityEngine;
namespace Intrepid.Utilities
{
public static class GonExtensions
{
public static Vector2 Rotate(this Vector2 v, float degrees)
{
var radians = degrees * Mathf.Deg2Rad;
var sin = Mathf.Sin(radians);
var cos = Mathf.Cos(radians);
return new Vector2(
v.x * cos - v.y * sin,
v.x * sin + v.y * cos
);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cdba58dc758948c8a2a233692247eb65
timeCreated: 1780647310

View File

@ -0,0 +1,20 @@
using UnityEngine;
namespace Intrepid.Utilities
{
public static class GonFunctions
{
public static Vector2 ConstrainDirectionToForwardCone(
Vector2 direction,
Vector2 forward,
float maxAngleDegrees)
{
var clampedAngle = Mathf.Clamp(
Vector2.SignedAngle(forward, direction),
-maxAngleDegrees,
maxAngleDegrees
);
return forward.Rotate(clampedAngle).normalized;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 046061aab07741c7b4066d5c7a91ce37
timeCreated: 1780647513