interpolate

package
v0.9.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

Documentation

Overview

Package interpolate 提供客户端渲染侧的状态插值与抖动缓冲。

解决的问题:服务器以固定 tick 下发 Delta(如 20Hz/50ms),但客户端渲染跑 60fps。 如果直接"收到就显示",表现为:网络好时 50ms 一跳,网络抖时更不规则。 玩家感知为"卡顿"或"瞬移"。

本包的方案:客户端始终渲染"过去 T 毫秒"的世界状态,在两个已知快照之间做 平滑插值。T 称为"渲染延迟"(render delay / interpolation window),通常 取 2~3 个 tick 间隔(如 100~150ms)。代价是多了固定延迟,但换来丝滑。

三大组件:

  • Buffer: 接收服务器快照,按服务器时间戳排序存储;
  • Interpolator: 给定"渲染时间",从 Buffer 中找前后两帧做线性插值;
  • TimeLine: 客户端本地时钟 → 服务器时间轴的映射(含抖动吸收)。

并发:Buffer 并发安全(网络线程写、渲染线程读);Interpolator/TimeLine 为值或 单线程使用(渲染循环内)。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Buffer

type Buffer struct {
	// contains filtered or unexported fields
}

Buffer 是带抖动吸收的快照缓冲。网络线程 Push,渲染线程 Sample。 并发安全。

func NewBuffer

func NewBuffer(capacity int) *Buffer

NewBuffer 创建缓冲区。capacity 为保留的最大帧数(推荐 32~64)。

func (*Buffer) Bracket

func (b *Buffer) Bracket(renderTime time.Duration) (before, after Frame, t float64, ok bool)

Bracket 返回 renderTime 前后两帧及插值因子 t∈[0,1]。 若缓冲不足(尚无两帧跨 renderTime),返回 ok=false。

func (*Buffer) Latest

func (b *Buffer) Latest() time.Duration

Latest 返回缓冲中最新帧的服务器时间。无帧时返回 0。

func (*Buffer) Len

func (b *Buffer) Len() int

Len 返回缓冲帧数。

func (*Buffer) Push

func (b *Buffer) Push(f Frame)

Push 插入一帧服务器快照。帧按 ServerTime 单调递增;乱序帧被插入到正确位置。

type Frame

type Frame struct {
	ServerTime time.Duration // 服务器时间轴上的时间戳
	Entities   []Snapshot
}

Frame 是一帧服务器下发的世界快照(含时间戳)。

type Snapshot

type Snapshot struct {
	ID      string
	X, Y    float64
	VX, VY  float64 // 可选:速度(用于 Hermite 插值或外推)
	Angle   float64 // 可选:朝向角度
	Payload any     // 业务扩展字段(不参与插值)
}

Snapshot 表示一个可插值的实体状态快照。

func HermiteSnapshot

func HermiteSnapshot(a, b Snapshot, t, dt float64) Snapshot

HermiteSnapshot 三次 Hermite 插值(使用速度作为切线)。t∈[0,1]。 dt 为两帧时间间隔(秒),用于将速度转为位移量级。

func InterpolateFrame

func InterpolateFrame(before, after Frame, t float64) []Snapshot

InterpolateFrame 对两帧做全实体线性插值。t∈[0,1]。 只对两帧中都存在的实体做插值;仅在 after 中出现的直接取 after;仅在 before 中的忽略。

func LerpSnapshot

func LerpSnapshot(a, b Snapshot, t float64) Snapshot

LerpSnapshot 对两个 Snapshot 做线性插值。t∈[0,1] 时为插值;t>1 时外推。

type TimeLine

type TimeLine struct {
	// contains filtered or unexported fields
}

TimeLine 维护客户端本地时钟到服务器时间轴的映射。 核心思路:服务器每个包附带 serverTime,客户端收到后校准偏移量。 渲染时间 = 本地时间 - 偏移量 - renderDelay。

func NewTimeLine

func NewTimeLine(opts ...TimeLineOption) *TimeLine

NewTimeLine 创建时间轴。epoch 为本地起始时间(通常 time.Now())。

func (*TimeLine) OnServerFrame

func (tl *TimeLine) OnServerFrame(serverTime time.Duration)

OnServerFrame 收到服务器帧时调用:用本地收到时间和帧的服务器时间校准偏移。

func (*TimeLine) RenderDelay

func (tl *TimeLine) RenderDelay() time.Duration

RenderDelay 返回当前配置的渲染延迟。

func (*TimeLine) RenderTime

func (tl *TimeLine) RenderTime() time.Duration

RenderTime 返回当前应渲染的服务器时间(= 本地流逝 - offset - renderDelay)。

func (*TimeLine) SetRenderDelay

func (tl *TimeLine) SetRenderDelay(d time.Duration)

SetRenderDelay 动态调整渲染延迟(如根据抖动自适应)。

type TimeLineOption

type TimeLineOption func(*TimeLine)

TimeLineOption 配置 TimeLine。

func WithNow

func WithNow(fn func() time.Time) TimeLineOption

WithNow 注入时钟(测试用)。

func WithRenderDelay

func WithRenderDelay(d time.Duration) TimeLineOption

WithRenderDelay 设置渲染延迟(默认 100ms)。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL