Prediction smoothing
Prediction errors can occur for a number of reasons: Variations in logic between clients and the server, packet drops, quantization errors, and so on. For predicted entities the net effect is that when rolling back and resimulating from the latest available snapshot, there can be a significant difference between the recomputed values and the originally predicted values.
The GhostPredictionSmoothingSystem
system provides a way of reconciling and reducing these errors over time, to make the transitions between the two states smoother. For each component, you can configure how to manage these errors by registering a Smoothing Action Function
on the GhostPredictionSmoothing
singleton which will smooth the error out over time.
public delegate void SmoothingActionDelegate(void* currentData, void* previousData, void* userData);
//pass null as user data
GhostPredictionSmoothing.RegisterSmoothingAction<Translation>(EntityManager, MySmoothingAction);
//will pass as user data a pointer to a MySmoothingActionParams chunk component
GhostPredictionSmoothing.RegisterSmoothingAction<Translation, MySmoothingActionParams>(EntityManager, DefaultTranslateSmoothingAction.Action);
The user data must be a chunk-component present in the entity. A default implementation for smoothing out any Translation prediction errors is provided by the package.
world.GetSingleton<GhostPredictionSmoothing>().RegisterSmootingAction<Translation>(EntityManager, CustomSmoothing.Action);
[BurstCompile]
public unsafe class CustomSmoothing
{
public static readonly PortableFunctionPointer<GhostPredictionSmoothing.SmoothingActionDelegate>
Action =
new PortableFunctionPointer<GhostPredictionSmoothing.SmoothingActionDelegate>(SmoothingAction);
[BurstCompile(DisableDirectCall = true)]
private static void SmoothingAction(void* currentData, void* previousData, void* userData)
{
ref var trans = ref UnsafeUtility.AsRef<Translation>(currentData);
ref var backup = ref UnsafeUtility.AsRef<Translation>(previousData);
var dist = math.distance(trans.Value, backup.Value);
//UnityEngine.Debug.Log($"Custom smoothing, diff {trans.Value - backup.Value}, dist {dist}");
if (dist > 0)
trans.Value = backup.Value + (trans.Value - backup.Value) / dist;
}
}