docs.unity3d.com
Search Results for

    Show / Hide Table of Contents

    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;
        }
    }
    
    In This Article
    Back to top
    Copyright © 2025 Unity Technologies — Trademarks and terms of use
    • Legal
    • Privacy Policy
    • Cookie Policy
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)