@@ -63,14 +63,16 @@ public Vector3 Velocity
6363 set
6464 {
6565 _velocity = value ;
66- var inv = Quaternion . Invert ( Orientation ) ;
66+
67+ var inv = Quaternion . Invert ( GlobalBasis ) ;
6768 value = inv * value ;
6869 MoveVector = new Vector2 ( value . X , value . Z ) / Speed ;
6970 }
7071 }
7172
7273 /// <summary>
7374 /// The current movement direction of this component, it is local to its <see cref="BodyComponent.Orientation"/>
75+ /// where +X is left, -X is right, +Y is forward and -Y is backward. This is similar to how the arrow Gizmo in the editor is laid out.
7476 /// </summary>
7577 /// <remarks>
7678 /// The input is scaled by <see cref="Speed"/> before usage<br/>
@@ -83,7 +85,7 @@ public Vector2 MoveVector
8385 set
8486 {
8587 field = value ;
86- _velocity = Orientation * new Vector3 ( value . X , 0 , value . Y ) * Speed ;
88+ _velocity = GlobalBasis * new Vector3 ( value . X , 0 , value . Y ) * Speed ;
8789 }
8890 }
8991
@@ -128,6 +130,8 @@ public bool IsJumping
128130 [ DataMemberIgnore , Obsolete ( $ "Contacts are no longer collected, add your own { nameof ( ContactEventHandler ) } ") ]
129131 public List < ( CollidableComponent Source , Contact Contact ) > Contacts { get ; } = new ( ) ;
130132
133+ private Quaternion GlobalBasis => Quaternion . LookRotation ( Orientation * Vector3 . UnitZ , Orientation * LocalUp ) ;
134+
131135 public CharacterComponent ( )
132136 {
133137 InterpolationMode = InterpolationMode . Interpolated ;
@@ -144,7 +148,7 @@ public CharacterComponent()
144148 public virtual void Move ( Vector3 direction )
145149 {
146150 // Note that this method should be thread safe, see usage in RecastPhysicsNavigationProcessor
147- var inv = Quaternion . Invert ( Orientation ) ;
151+ var inv = Quaternion . Invert ( GlobalBasis ) ;
148152 direction = inv * direction ;
149153 MoveVector = new Vector2 ( direction . X , direction . Z ) ;
150154 }
@@ -165,8 +169,6 @@ public virtual void TryJump()
165169 /// <inheritdoc/>
166170 protected override void SimulationUpdate ( BepuSimulation sim , float simTimeStep , ref InternalCharacterData character , in BodyReference characterBody , out bool wakeupBody )
167171 {
168- /*Entity.Transform.UpdateWorldMatrix();
169- var viewDirection = (NVector3)Entity.Transform.WorldMatrix.Backward;*/
170172 var viewDirection = ( NVector3 ) ( Orientation * Vector3 . UnitZ ) ;
171173
172174 var newTargetVelocity = new System . Numerics . Vector2 ( MoveVector . X , MoveVector . Y ) * Speed ;
@@ -204,13 +206,13 @@ protected override void SimulationUpdate(BepuSimulation sim, float simTimeStep,
204206 if ( ! character . Supported && newTargetVelocity . LengthSquared ( ) > 0 )
205207 {
206208 QuaternionEx . Transform ( character . LocalUp , characterBody . Pose . Orientation , out var characterUp ) ;
207- var characterRight = Vector3 . Cross ( character . ViewDirection , characterUp ) ;
208- var rightLengthSquared = characterRight . LengthSquared ( ) ;
209+ var characterLeft = Vector3 . Cross ( characterUp , character . ViewDirection ) ;
210+ var rightLengthSquared = characterLeft . LengthSquared ( ) ;
209211 if ( rightLengthSquared > 1e-10f )
210212 {
211- characterRight /= MathF . Sqrt ( rightLengthSquared ) ;
212- var characterForward = Vector3 . Cross ( characterUp , characterRight ) ;
213- var worldMovementDirection = characterRight * newTargetVelocity . X + characterForward * newTargetVelocity . Y ;
213+ characterLeft /= MathF . Sqrt ( rightLengthSquared ) ;
214+ var characterForward = Vector3 . Cross ( characterLeft , characterUp ) ;
215+ var worldMovementDirection = characterLeft * newTargetVelocity . X + characterForward * newTargetVelocity . Y ;
214216 var currentVelocity = Vector3 . Dot ( characterBody . Velocity . Linear , worldMovementDirection ) ;
215217 //We'll arbitrarily set air control to be a fraction of supported movement's speed/force.
216218 var airAccelerationDt = characterBody . LocalInertia . InverseMass * character . MaximumHorizontalForce * AirControlForceScale * simTimeStep ;
@@ -219,7 +221,7 @@ protected override void SimulationUpdate(BepuSimulation sim, float simTimeStep,
219221 //While we shouldn't allow the character to continue accelerating in the air indefinitely, trying to move in a given direction should never slow us down in that direction.
220222 var velocityChangeAlongMovementDirection = MathF . Max ( 0 , targetVelocity - currentVelocity ) ;
221223 characterBody . Velocity . Linear += worldMovementDirection * velocityChangeAlongMovementDirection ;
222- Debug . Assert ( characterBody . Awake , "Velocity changes don't automatically update objects; the character should have already been woken up before applying air control." ) ;
224+ Debug . Assert ( characterBody . Awake || wakeupBody , "Velocity changes don't automatically update objects; the character should have already been woken up before applying air control." ) ;
223225 }
224226 }
225227 }
0 commit comments