Hello everyone,
For a game of mine, since it’s mainly just doing some 3D physics stuff that’s supposed to be playable in a multiplayer, I started to use the NetCode package, and thus the DOTS including the DOTS Physics.
As I figured out after a while, setting values directly like rotation or velocity causes visible issues like stuttering, which are resolved as soon as the code isn’t executed anymore. To give an example, I was able to replace the rotation freeze (setting the x and z rotation back to 0) by setting InverseInertia
instead, but I still need to adjust e. g. velocity and rotation to implement the acceleration and steering. But if I do so by just calculating and assigning the values, the result is basically unusable (stuttering movement, floating above the ground, etc.).
The Code is contained in a ComponentSystem
with the attributes [UpdateInWorld(UpdateInWorld.TargetWorld.ClientAndServer)]
and [UpdateInGroup(typeof(GhostPredictionSystemGroup))]
. The code in question:
this.Entities.ForEach((ref PhysicsVelocity velocity, ref CharacterBaseComponent character, ref PredictedGhostComponent prediction) =>
{
if (GhostPredictionSystemGroup.ShouldPredict(tick, prediction))
{
if (character.isGrounded)
{
// positions.Add(translation.Value);
var forward = character.forward;
var groundNormal = character.groundNormal;
// normals.Add(groundNormal);
var dot = math.dot((float3)forward, (float3)groundNormal);
var groundForward = forward - dot * groundNormal;
var factor = -math.dot(groundForward, math.up());
var acceleration = groundForward * factor * character.acceleration;
velocity.Linear += acceleration * deltaTime;
}
}
});
this.Entities.ForEach((DynamicBuffer<CharacterInputCommand> inputBuffer, ref Rotation rotation, ref PhysicsVelocity velocity, ref CharacterBaseComponent character, ref PredictedGhostComponent prediction) =>
{
if (GhostPredictionSystemGroup.ShouldPredict(tick, prediction))
{
CharacterInputCommand input;
inputBuffer.GetDataAtTick(tick, out input);
var steeringRotation = quaternion.AxisAngle(math.up(), input.horizontal * character.steeringSpeed);
rotation.Value = math.mul(steeringRotation, rotation.Value);
// speed adjustment after steering
float3 forwardSpeed = velocity.Linear * math.dot(velocity.Linear, character.forward);
velocity.Linear -= forwardSpeed;
float3 rotatedVelocity = math.rotate(steeringRotation, forwardSpeed);
velocity.Linear += rotatedVelocity * 0.25f + forwardSpeed * 0.75f;
}
});
Regarding the first example: If I set the friction to 0+Minimum (instead of 1+Maximum as it is right now) and don’t accelerate the character manually (basically disable the first code snippet) but rather let the physics do this, and also disable the steering (2nd code snippet), then the movement is smooth as expected. But on the other hand, I’d still need to add enough “sideways friction” manually later on to get back to the desired behavior - e. g. by reducing the velocity - recreating the same issues I have right now.
What do I have to do to get the desired behavior?