Fish-Net: Networking Evolved
  • Introduction
    • Getting Started
    • Showcase
      • Upcoming Releases
    • Legal Restrictions
    • Pro, Projects, and Support
    • Business Support
    • Branding
  • Manual
    • General
      • Unity Compatibility
      • Changelog
        • Development Road Map
        • Major Version Update Solutions
      • Development
      • Performance
        • Benchmark Setup
        • Fish-Networking Vs Mirror
      • Terminology
        • Miscellaneous
        • Communicating
        • Server, Client, Host
      • Transports
      • Add-ons
        • Edgegap and other Hosting
        • Fish-Network-Discovery
      • Feature Comparison
      • Upgrading To Fish-Networking
    • Guides
      • Frequently Asked Questions (FAQ)
      • Creating Bug Reports
        • Report Example
      • Technical Limitations
      • Third-Party
      • Getting Started
        • Commonly Used Guides
        • Ownership - Moving Soon
        • Step-by-Step
          • Getting Connected
          • Preparing Your Player
      • Components
        • Managers
          • NetworkManager
          • TimeManager
          • PredictionManager
          • ServerManager
          • ClientManager
          • SceneManager
          • TransportManager
            • IntermediateLayer
          • StatisticsManager
          • ObserverManager
            • HashGrid
          • RollbackManager (Pro Feature)
        • Transports
          • FishyWebRTC
          • Bayou
          • FishyEOS (Epic Online Services)
          • FishyFacepunch (Steam)
          • FishyRealtime
          • FishySteamworks (Steam)
          • FishyUnityTransport
          • Multipass
          • Tugboat
          • Yak (Pro Feature)
        • Prediction
          • Network Collider
            • NetworkCollision
            • NetworkCollision2D
            • NetworkTrigger
            • NetworkTrigger2D
          • OfflineRigidbody
          • PredictedOwner
          • PredictedSpawn
        • Utilities
          • Tick Smoothers
            • NetworkTickSmoother
            • OfflineTickSmoother
          • MonoTickSmoother [Obsolete]
          • DetachableNetworkTickSmoother [Obsolete]
          • BandwidthDisplay
          • DefaultScene
          • PingDisplay
        • Authenticator
        • ColliderRollback
        • NetworkAnimator
        • NetworkBehaviour
        • NetworkTransform
        • NetworkObject
        • NetworkObserver
      • InstanceFinder
      • Ownership
        • Using Ownership To Read Values
      • Spawning and Despawning
        • Predicted Spawning
        • Nested NetworkObjects
        • Object Pooling
      • Components
      • NetworkBehaviour
      • NetworkObjects
      • Attributes, Quality of Life
      • Remote Procedure Calls
        • Broadcast
      • SyncTypes
        • Customizing Behavior
        • SyncVar
        • SyncList
        • SyncHashSet
        • SyncDictionary
        • SyncTimer
        • SyncStopwatch
        • Custom SyncType
      • Observers
        • Modifying Conditions
        • Custom Conditions
      • Automatic Serializers
      • Custom Serializers
        • Interface Serializers
        • Inheritance Serializers
      • Addressables
      • Scene Management
        • Scene Events
        • Scene Data
          • SceneLookupData
          • SceneLoadData
          • SceneUnloadData
        • Loading Scenes
        • Unloading Scenes
        • Scene Stacking
        • Scene Caching
        • Scene Visibility
        • Persisting NetworkObjects
        • Custom Scene Processors
          • Addressables
      • Transports
        • Multipass
      • Prediction
        • What Is Client-Side Prediction
        • Configuring PredictionManager
        • Configuring TimeManager
        • Configuring NetworkObject
        • Offline Rigidbodies
        • Interpolations
        • Creating Code
          • Controlling An Object
          • Non-Controlled Object
          • Understanding ReplicateState
            • Using States In Code
            • Predicting States In Code
          • Advanced Controls
        • Custom Comparers
        • PredictionRigidbody
        • Using NetworkColliders
      • Lag Compensation
        • States
        • Raycast
        • Projectiles
    • Server Hosting
      • Edgegap - Official Partner
        • Getting Started with Edgegap
      • Hathora
        • Getting Started with Hathora
      • Amazon Web Services (AWS)
        • Getting Started with AWS
    • API
Powered by GitBook
On this page
  1. Manual
  2. Guides
  3. Prediction
  4. Creating Code
  5. Understanding ReplicateState

Predicting States In Code

Due to the unpredictability of the Internet inputs may drop or arrive late. Predicting states is a simple way to compensate for these events.

PreviousUsing States In CodeNextAdvanced Controls

Last updated 11 months ago

If your game is fast-paced and reaction based, even if not using physics, predicting states can be useful to predict the next inputs you'll get from the server before you actually get them.

Both the server and client can predict inputs.

The server may predict inputs to accommodate for clients with unreliable connections.

Clients would predict inputs on objects they do not own, or as we often call them "spectated objects".

By predicting inputs you can place objects in the future of where you know them to be, and even make them entirely real-time with the client. Keep in mind however, when predicting the future, if you guess wrong there will be a de-synchronization which may be seen as jitter when it's corrected in a reconcile.

Below is an example of a simple replicate method.

//What data does is irrelevant in this example.
//We're only interested in how to predict a future state.
[Replicate]
private void RunInputs(ReplicateData data, ReplicateState state = ReplicateState.Invalid, Channel channel = Channel.Unreliable)
{ 
    float delta = (float)base.TimeManager.TickDelta;
    transform.position += new Vector3(data.Horizontal, 0f, data.Vertical) * _moveRate * delta;
}

Before we go any further you must first understand what each ReplicateState is. These change based on if input is known, replaying inputs or not, and more. You can check out the which will explain thoroughly. You can also find this information right in the source of FishNet.

If you've read through ReplicateState and do not fully understand them please continue reading as they become more clear as this guide progresses. You can also visit us on Discord for questions!

Covered in the ReplicateStates API: CurrentCreated will only be seen on clients if they own the object. When inputs are received on spectated objects clients run them in the reconcile, which will have the state ReplayedCreated. Clients will also see ReplayedFuture and CurrentFuture on spectated objects.

A state ending in 'Future' essentially means input has not been received yet, and these are the states you could predict.

Let's assume your game has a likeliness that players will move in the same direction regularly enough. If a player was holding forward for three ticks the input would look like this...

(data.Vertical == 1)
(data.Vertical == 1)
(data.Vertical == 1)

But what if one of the inputs didn't arrive, or arrived late? The chances of inputs not arriving at all are pretty slim, but arriving late due to network variance is extremely common. If perhaps an input did arrive late the values may appear as something of this sort...

(data.Vertical == 1)
(data.Vertical == 1)
(data.Vertical == 0) //Didn't arrive here, but will arrive late next tick.
(data.Vertical == 1) //This was meant to arrive the tick before, but arrived late.

Below is a simple way to track and use known inputs to create predicted ones.

private ReplicateData _lastCreatedInput = default;

[Replicate]
private void RunInputs(ReplicateData data, ReplicateState state = ReplicateState.Invalid, Channel channel = Channel.Unreliable)
{ 
    //If inputs are not known. You could predict
    //all the way into CurrentFuture, which would be
    //real-time with the client. Though the more you predict
    //in the future the more you are likely to mispredict.
    if (state.IsFuture())
    {
        uint lastCreatedTick = _lastCreatedInput.GetTick();
        //If it's only been 2 ticks since the last created
        //input then run the logic below.
        //This essentially means if the last created tick
        //was 100, this logic would run if the future tick was 102
        //or less. This is an example of a basic approach to only
        //predict a certain number of inputs.
        uint thisTick = data.GetTick();
        if ((data.GetTick() - lastCreatedTick) <= 2)
        {
            //We do not necessarily want to predict all states.
            //For example, it probably wouldn't make sense to predict
            //multiple jumps in a row. In this example only the movement
            //inputs are predicted.
            data.Vertical = _lastCreatedInput.Vertical;
        }
    }
    //If created data then set as lastCreatedInput.
    else if (state == ReplicateState.ReplayedCreated)
    {
        //If ReplicateData contains fields which could generate garbage you
        //probably want to dispose of the lastCreatedInput
        //before replacing it. This step is optional.
        _lastCreatedInput.Dispose();
        //Assign newest value as last.
        _lastCreatedInput = data;
    }
    
    float delta = (float)base.TimeManager.TickDelta;
    transform.position += new Vector3(data.Horizontal, 0f, data.Vertical) * _moveRate * delta;
}

If your ReplicateData allocates do not forget to dispose of the lastCreatedInput when the network is stopped.

Because of this interruption the player may seem to move forward twice, pause, then forward again. Realistically to help cover this up you will have interpolation on your graphicalObject as shown under the prediction settings for The also offers QueuedInputs which can give you even more of a buffer. For the sake of this guide though we're going to pretend both of those didn't get the job done, and you need to account for the late input.

ReplicateState API
NetworkObject.
PredictionManager