Limitations and Gotchas

Many of these limitations and gotchas only apply to Prediction v1. Version 2 is nearing completion and a new guide will be made upon release.

Default Prediction Datas

On occasion datas inside your prediction methods may be default. This can occur when there are no inputs in queue to pull from, be it on the client or server. Even though there are no queued inputs prediction methods must still run because you may want to perform actions that do not specifically require inputs. If this would cause an issue for your project consider checking if the prediction data is default and exiting early from the method if so.

Offline Rigidbodies

In addition to networked rigidbodies, many projects use offline rigidbodies that do not neccesarily impact the network simulation. For example, you may use offline rigidbodies to roll rocks down a mountain which are not meant to impact the player or their movement. When rigidbodies are intended to be used for offline use be sure to add the OfflineRigidbody component to them.

Predicting Rigidbodies Without an Owned Object

In order for other objects to be predicted the owning player must also have an active object predicting, as if they were applying prediction for their own controller. The prediction method does not need to send any data or perform any logic, but must simply exists to keep the client in synchronization with the server.

Example code:

[Replicate]
private void EmptyReplicate(EmptyReplicateData ed, bool asServer, Channel channel = Channel.Unreliable, bool replaying = false)
{}

[Reconcile]
private void Reconcile(EmptyReconcileData ed, bool asServer, Channel channel = Channel.Unreliable)
{}

Client-side Predicting Multiple Objects

A client might have to move multiple objects at once, such as their player and a pet. This is possible but both objects must be predicted in the same method if they are to both expected to run at the same time, or same tick.

Since both objects are controlled in the same replicate method, this technique will work.

[Replicate]
private void MoveObjects(MoveData md, bool asServer, Channel channel = Channel.Unreliable, bool replaying = false)
{
    float delta = (float)base.TimeManager.TickDelta;
    _petTransform.position += (md.PetDirection * delta);
    _playerTransform.position += (md.PlayerDirection * delta);
}

Below both the pet and player have their own replicate method. If these were to both run on the same tick replication would create artifacts, and fail to work properly.

//PlayerMotor.cs
[Replicate]
private void PlayerMove(PlayerMoveData pmd, bool asServer, Channel channel = Channel.Unreliable, bool replaying = false)
{
    float delta = (float)base.TimeManager.TickDelta;
    _player.position += (pmd.Direction * delta);
}

//PetMotor.cs
[Replicate]
private void PetMove(PetMoveData pmd, bool asServer, Channel channel = Channel.Unreliable, bool replaying = false)
{
    float delta = (float)base.TimeManager.TickDelta;
    _pet.position += (pmd.Direction * delta);
}

We would like to have both approaches supported by the end of version 3x.

Triggers and Collisions

We already covered that when using Client-Side Prediction past inputs are replayed for the object's owner. Because of this, trigger and collision events may occur multiple times in a single frame or even over consecutive ticks. When using such events with CSP consider checking PredictionManager.IsReplaying() before processing logic, and only process if IsReplaying is false.

If you are also relying on exit conditions, you may want to consider using OnStay conditions instead. Exit conditions such as OnTriggerExit do not always execute when using CSP. This is unfortunately another limitation of the physics system within Unity.

Rigidbodies

In most cases you will want to leave Rigidbody interpolation disabled. The PredictedObject component will interpolate the graphics for you.

Last updated