Class CharacterPositionHistory
Server-side ring buffer of where a character's collider was on each recent tick.
public class CharacterPositionHistory : NetworkBehaviour
- Inheritance
-
ObjectComponentBehaviourMonoBehaviourNetworkBehaviourCharacterPositionHistory
- Inherited Members
-
NetworkBehaviour.IsSpawnedNetworkBehaviour.ComponentIndexNetworkBehaviour.NetworkObjectNetworkBehaviour.MAXIMUM_NETWORKBEHAVIOURSNetworkBehaviour.UNSET_NETWORKBEHAVIOUR_IDNetworkBehaviour.ToString()NetworkBehaviour.Reset()NetworkBehaviour.OnValidate()NetworkBehaviour.IsBehaviourReconcilingNetworkBehaviour.ClearReplicateCache()NetworkBehaviour.CreateReconcile()NetworkBehaviour.Reconcile_Reader<T>(PooledReader, ref T)NetworkBehaviour.OnStartServerCalledNetworkBehaviour.OnStartClientCalledNetworkBehaviour.WritePayload(NetworkConnection, Writer)NetworkBehaviour.ReadPayload(NetworkConnection, Reader)NetworkBehaviour.OnStartNetwork()NetworkBehaviour.OnStopNetwork()NetworkBehaviour.OnOwnershipServer(NetworkConnection)NetworkBehaviour.OnSpawnServer(NetworkConnection)NetworkBehaviour.OnDespawnServer(NetworkConnection)NetworkBehaviour.OnStartClient()NetworkBehaviour.OnStopClient()NetworkBehaviour.OnOwnershipClient(NetworkConnection)NetworkBehaviour.ClearBuffedRpcs()NetworkBehaviour.ExcludeOwnerFromUnbufferedObserversRpcsNetworkBehaviour.IsClientOnlyNetworkBehaviour.IsServerOnlyNetworkBehaviour.IsHostNetworkBehaviour.IsClientNetworkBehaviour.IsServerNetworkBehaviour.IsDeinitializingNetworkBehaviour.NetworkManagerNetworkBehaviour.ServerManagerNetworkBehaviour.ClientManagerNetworkBehaviour.ObserverManagerNetworkBehaviour.TransportManagerNetworkBehaviour.TimeManagerNetworkBehaviour.SceneManagerNetworkBehaviour.PredictionManagerNetworkBehaviour.RollbackManagerNetworkBehaviour.NetworkObserverNetworkBehaviour.IsClientInitializedNetworkBehaviour.IsClientStartedNetworkBehaviour.IsClientOnlyInitializedNetworkBehaviour.IsClientOnlyStartedNetworkBehaviour.IsServerInitializedNetworkBehaviour.IsServerStartedNetworkBehaviour.IsServerOnlyInitializedNetworkBehaviour.IsServerOnlyStartedNetworkBehaviour.IsHostInitializedNetworkBehaviour.IsHostStartedNetworkBehaviour.IsOfflineNetworkBehaviour.IsNetworkedNetworkBehaviour.GetIsNetworked()NetworkBehaviour.IsManagerReconcilingNetworkBehaviour.ObserversNetworkBehaviour.IsOwnerNetworkBehaviour.IsControllerNetworkBehaviour.HasAuthorityNetworkBehaviour.OwnerNetworkBehaviour.OwnerIdNetworkBehaviour.ObjectIdNetworkBehaviour.LocalConnectionNetworkBehaviour.OwnerMatches(NetworkConnection)NetworkBehaviour.Despawn(GameObject, DespawnType?)NetworkBehaviour.Despawn(NetworkObject, DespawnType?)NetworkBehaviour.Despawn(DespawnType?)NetworkBehaviour.Spawn(GameObject, NetworkConnection, Scene)NetworkBehaviour.Spawn(NetworkObject, NetworkConnection, Scene)NetworkBehaviour.RemoveOwnership()NetworkBehaviour.GiveOwnership(NetworkConnection)NetworkBehaviour.GetInstance<T>()NetworkBehaviour.TryRegisterInstance<T>(T)NetworkBehaviour.UnregisterInstance<T>()NetworkBehaviour.CanLog(LoggingType)MonoBehaviour.IsInvoking()MonoBehaviour.CancelInvoke()MonoBehaviour.StopCoroutine(Coroutine)MonoBehaviour.StopAllCoroutines()MonoBehaviour.destroyCancellationTokenMonoBehaviour.useGUILayoutMonoBehaviour.didStartMonoBehaviour.didAwakeMonoBehaviour.runInEditModeBehaviour.enabledBehaviour.isActiveAndEnabledComponent.GetComponent<T>()Component.TryGetComponent<T>(out T)Component.GetComponentInChildren<T>()Component.GetComponentsInChildren<T>()Component.GetComponentInParent<T>()Component.GetComponentsInParent<T>()Component.GetComponents<T>()Component.GetComponentIndex()Component.CompareTag(TagHandle)Component.transformComponent.transformHandleComponent.gameObjectComponent.tagObject.GetEntityId()Object.GetInstanceID()Object.GetHashCode()Object.InstantiateAsync<T>(T)Object.InstantiateAsync<T>(T, Transform)Object.InstantiateAsync<T>(T, Vector3, Quaternion)Object.InstantiateAsync<T>(T, Transform, Vector3, Quaternion)Object.Instantiate(Object, Vector3, Quaternion)Object.Instantiate(Object, Vector3, Quaternion, Transform)Object.Instantiate(Object)Object.Instantiate(Object, Scene)Object.Instantiate<T>(T, InstantiateParameters)Object.Instantiate<T>(T, Vector3, Quaternion, InstantiateParameters)Object.Instantiate(Object, Transform)Object.Instantiate<T>(T)Object.Instantiate<T>(T, Vector3, Quaternion)Object.Instantiate<T>(T, Vector3, Quaternion, Transform)Object.Instantiate<T>(T, Transform)Object.Destroy(Object)Object.DestroyImmediate(Object)Object.DontDestroyOnLoad(Object)Object.DestroyObject(Object)Object.FindObjectsOfType<T>()Object.FindObjectsByType<T>(FindObjectsSortMode)Object.FindObjectsByType<T>(FindObjectsInactive, FindObjectsSortMode)Object.FindObjectOfType<T>()Object.FindFirstObjectByType<T>()Object.FindAnyObjectByType<T>()Object.FindFirstObjectByType<T>(FindObjectsInactive)Object.FindAnyObjectByType<T>(FindObjectsInactive)Object.FindObjectsByType<T>()Object.FindObjectsByType<T>(FindObjectsInactive)Object.nameObject.hideFlags
Remarks
Why this exists. Hits resolve on the server against current positions, while a client aims at peers it renders behind the server by its interpolation buffer plus its own latency. The gap is the peer's speed times that staleness — measured at 0.64 m for a 40 ms connection and 2.2 m at 300 ms — against ability hitboxes authored at half a metre. No amount of tuning closes that. The server has to be able to ask "where was this character when the shooter saw it", and this is what lets it.
Server only, by construction. Recording starts in OnStartServer() and the tick subscription is never taken on a client. Rewinding is a server-side query against authoritative history; it is deliberately not part of the deterministic simulation, so it cannot influence what clients predict and cannot desynchronise them.
Cost. One CharacterPositionHistory.Snapshot per tick per character, in a pre-allocated ring — no per-tick allocation. At the default window that is a fixed 28 bytes times the buffer length per character, held for the character's lifetime.
Properties
Capacity
Capacity of the ring, for diagnostics and tests.
public int Capacity { get; }
Property Value
IsRewound
True while this character's collider is displaced by a rewind.
public bool IsRewound { get; }
Property Value
MaximumRewindMilliseconds
Maximum rewind window, in milliseconds.
public float MaximumRewindMilliseconds { get; }
Property Value
RecordedTicks
Number of ticks currently held, for diagnostics and tests.
public int RecordedTicks { get; }
Property Value
Methods
OnStartServer()
Called on the server after initializing this object. SyncTypes modified before or during this method will be sent to clients in the spawn message.
public override void OnStartServer()
OnStopServer()
Called on the server before deinitializing this object.
public override void OnStopServer()
TryResolve(RewindTarget, out Snapshot)
Resolves where this character was at tick, interpolating between the
two recorded ticks that bracket it.
public bool TryResolve(RewindTarget target, out CharacterPositionHistory.Snapshot snapshot)
Parameters
targetRewindTargetThe point in the past to resolve.
snapshotCharacterPositionHistory.SnapshotThe resolved transform.
Returns
- bool
True when history covers the requested tick.
Remarks
The whole-tick overload below is what actually reads the ring; this blends the two samples the target sits between. A client's view of a peer comes from interpolation and lands between ticks, so resolving only on tick boundaries reproduced a pose it never rendered. With a zero fraction the bounds collapse and this is exactly the whole-tick result.
TryResolve(uint, out Snapshot)
public bool TryResolve(uint tick, out CharacterPositionHistory.Snapshot snapshot)
Parameters
tickuintsnapshotCharacterPositionHistory.Snapshot