补充输入重放
输入重放是指当收到一个服务器状态包时以那个包为初始状态,然后重新计算所有未确认的输入来得到当前帧的状态,然后再对当前角色的位置进行插值移动。服务器状态包只能给出前几帧的权威数据,而当前帧的状态则需要通过输入回放来得到
This commit is contained in:
+36
@@ -0,0 +1,36 @@
|
||||
# local-player-presentation-state Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
Define how the local player's presentation layer holds current display state and smoothly interpolates toward the simulation layer's target state each frame.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Presentation layer holds current and target state
|
||||
|
||||
The local player's presentation layer SHALL maintain `_currentPosition` and `_currentRotation` (the actively displayed state) separately from `_targetPosition` and `_targetRotation` (the simulation layer's output).
|
||||
|
||||
#### Scenario: Presentation state initializes from first simulation target
|
||||
- **WHEN** the presentation layer is initialized or first receives a simulation target
|
||||
- **THEN** `_currentPosition` and `_currentRotation` are set equal to the initial target
|
||||
- **THEN** subsequent updates lerp toward the target
|
||||
|
||||
### Requirement: Presentation layer lerps toward target each frame
|
||||
|
||||
The presentation layer SHALL each frame interpolate `_currentPosition` and `_currentRotation` toward `_targetPosition` and `_targetRotation` using linear interpolation, then apply the result to the Rigidbody.
|
||||
|
||||
#### Scenario: Lerp position and rotation toward target
|
||||
- **WHEN** the presentation layer updates each frame with interpolation alpha α
|
||||
- **THEN** `_currentPosition` is updated to `Vector3.Lerp(_currentPosition, _targetPosition, α)`
|
||||
- **THEN** `_currentRotation` is updated to `Quaternion.Slerp(_currentRotation, _targetRotation, α)`
|
||||
- **THEN** `_rigid.position` and `_rigid.rotation` are set to `_currentPosition` and `_currentRotation`
|
||||
|
||||
### Requirement: Presentation layer snaps when target error exceeds threshold
|
||||
|
||||
When the distance between `_currentPosition` and `_targetPosition` exceeds the snap threshold, the presentation layer SHALL immediately snap `_currentPosition` to `_targetPosition` without lerping.
|
||||
|
||||
#### Scenario: Snap when error exceeds threshold
|
||||
- **WHEN** `Vector3.Distance(_currentPosition, _targetPosition) > SnapThreshold`
|
||||
- **THEN** `_currentPosition` is set equal to `_targetPosition`
|
||||
- **THEN** `_currentRotation` is set equal to `_targetRotation`
|
||||
- **THEN** no lerping occurs in this frame
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
# local-player-simulation-state Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
Define how the simulation layer maintains authoritative state, pending inputs, and computes the presentation target when receiving server PlayerState messages.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Simulation layer maintains authoritative baseline
|
||||
|
||||
The simulation layer SHALL maintain `_lastAuthoritativePosition`, `_lastAuthoritativeRotation`, and `_lastAcknowledgedTick` as the authoritative baseline. These are updated when the server acknowledges input through a PlayerState message.
|
||||
|
||||
#### Scenario: Authoritative baseline updates on PlayerState
|
||||
- **WHEN** the client receives a PlayerState with tick T
|
||||
- **THEN** `_lastAuthoritativePosition` is set to the PlayerState position
|
||||
- **THEN** `_lastAuthoritativeRotation` is set to the PlayerState rotation
|
||||
- **THEN** `_lastAcknowledgedTick` is set to T
|
||||
|
||||
### Requirement: Simulation layer maintains pending inputs
|
||||
|
||||
The simulation layer SHALL maintain a list of pending inputs that have been recorded locally but not yet acknowledged by the server.
|
||||
|
||||
#### Scenario: Pending inputs are pruned on acknowledgment
|
||||
- **WHEN** the client receives a PlayerState with AcknowledgedMoveTick N
|
||||
- **THEN** all pending inputs with tick <= N are removed from the pending list
|
||||
- **THEN** remaining pending inputs (tick > N) are preserved for replay
|
||||
|
||||
### Requirement: Simulation layer computes presentation target on PlayerState
|
||||
|
||||
When receiving a server PlayerState, the simulation layer SHALL compute the presentation target by replaying unacknowledged pending inputs from the authoritative baseline, and update the `_presentationTarget`.
|
||||
|
||||
#### Scenario: Presentation target is computed after replay
|
||||
- **WHEN** the client receives a PlayerState
|
||||
- **THEN** all acknowledged inputs are pruned (tick <= AcknowledgedMoveTick)
|
||||
- **THEN** remaining pending inputs are replayed starting from the authoritative position using 50ms fixed-step substeps
|
||||
- **THEN** `_presentationTarget` is set to (authoritative position + replay displacement, authoritative rotation + replay rotation delta)
|
||||
|
||||
### Requirement: Simulation layer updates presentation target only on PlayerState
|
||||
|
||||
The simulation layer SHALL only update `_presentationTarget` when a new PlayerState is received. Between PlayerState messages, the presentation target remains constant.
|
||||
|
||||
#### Scenario: Presentation target is stable between PlayerState messages
|
||||
- **WHEN** the client receives a PlayerState and computes `_presentationTarget`
|
||||
- **AND** no further PlayerState is received in the following frames
|
||||
- **THEN** `_presentationTarget` remains unchanged
|
||||
- **THEN** the presentation layer continues lerping toward the same target
|
||||
Reference in New Issue
Block a user