Teleporting

Teleporting using prediction can be done typically one of two ways, using replicate or a server remote procedure call.

Ideally, as mentioned many times before, when using prediction your actions should be performed inside the replicate method. This will ensure that inputs are processed in order, even including teleports. Below is an example of how you may teleport using the replicate method.

public class MyCSP : NetworkBehaviour
{
    public struct MoveData : IReplicateData
    {
        private uint _tick;
        public void Dispose() { }
        public uint GetTick() => _tick;
        public void SetTick(uint value) => _tick = value;
    }
    public struct ReconcileData : IReconcileData
    {
        private uint _tick;
        public void Dispose() { }
        public uint GetTick() => _tick;
        public void SetTick(uint value) => _tick = value;
    }

    [Replicate]
    private void Move(MoveData md, bool asServer, Channel channel = Channel.Unreliable, bool replaying = false)
    {
        /* Player has moved! If player should be teleported then
         * call the teleport method with the position desired.
         * What determines if a teleport occurs is entirely up
         * to you. Teleporting inside the replicate method ensures
         * the teleport will be processed in order of inputs. */

        /* If should teleport then
         * teleport to V3.zero. */
        Teleport(Vector3.zero);
    }

    [Reconcile]
    private void Reconciliation(ReconcileData rd, bool asServer, Channel channel = Channel.Unreliable)
    {
        /* Reconcile does not matter in this example.
         * Your reconcile code would run normally. */
    }

    private void Teleport(Vector3 position)
    {
        //Teleport the transform to the new position.
        transform.position = position;
    }
}

Above is the recommended way to teleport with client-side prediction, below is an example of using server RPCs, as well an explanation as to why using a remote procedure call rather than the replicate method may be problematic.

public class MyCSP : NetworkBehaviour
{
    /* Teleport upon entering a trigger. This is not a requirement
     * rather just an example of when you may teleport. */
    private void OnTriggerEnter(Collider other)
    {
        //Only process if not replaying.
        if (base.PredictionManager.IsReplaying())
            return;
        //Let the client send the teleport request.
        if (!base.IsClient)
            return;

        ServerTeleport(Vector3.one);
    }

    /* RunLocally as true so that the client runs the RPC logic,
     * as well the server. */
    [ServerRpc(RunLocally = true)]
    private void ServerTeleport(Vector3 position)
    {
        transform.position = position;
        /* Clear cache for both server and client.
         * RPCs are processed immediately and may be performed
         * before queued inputs. In other words, if the client were
         * to have two inputs queued from previous packets and sent
         * a server RPC, the RPC would run immediately and those
         * queued inputs would very likely run after the RPC.
         * In result the server may run inputs after the RPC
         * which the client intended to perform before the RPC.
         * 
         * Rather than risk a very potential desynchronization simply
         * clear the inputs for both client and server so that no
         * queued inputs run after the server rpc is received and performed. 
         *
         * Because of this gotcha, it may be best to teleport inside your
         * replicate method as shown in the previous example. */
        base.ClearReplicateCache();
    }
}

Last updated