在游戏中,场景里存在大量的物体.如果我们把所有物体的变化都广播给玩家.那客户端很难承受这么大的压力.因此我们肯定会做优化.把不必要的信息过滤掉.如只关心玩家视野所看到的.减轻客户端的压力,给玩家更流畅的体验.
优化的思路一般是: 第一个是尽量降低向客户端同步对象的数量,第二个是尽量降低单个对象向客户端同步的数据.
"九宫格"是最常见的视野管理算法了.它的优点在于原理和实现都非常简单.
// AOI 管理器
type AOIManager interface {
GetWidth() int
GetHeight() int
OnEnter(obj scene.GameObject, enterPos *geom.Vector2d) bool
OnLeave(obj scene.GameObject) bool
OnMove(obj scene.GameObject, movePos *geom.Vector2d) bool
OnSync()
}
一 . 定义管理器接口:
1. 进入区域 2. 离开区域 3. 在区域移动 4. 同步信息
具体实现:
type TowerAOIManager struct {
minX, maxX, minY, maxY float64 // 单位 m
towerRange float64 // 格子大小
towers [][]tower
xTowerNum, yTowerNum int
}
划分格子: 按照实际情况出发,规定格子大小 towerRange. (一般 九个格子的范围需大于屏幕看到的视野范围) 这样才能保证客户端场景物体的生成和消失在玩家屏幕外.不会突然出现.
// 构造结构
func NewTowerAOIManager(minX, maxX, minY, maxY float64, towerRange float64) AOIManager {
mgr := &TowerAOIManager{minX: minX, maxX: maxX, minY: minY, maxY: maxY, towerRange: towerRange}
mgr.init()
return mgr
}
func (m *TowerAOIManager) init() {
numXSlots := int((m.maxX-m.minX)/m.towerRange) + 1
m.xTowerNum = numXSlots
numYSlots := int((m.maxY-m.minY)/m.towerRange) + 1
m.yTowerNum = numYSlots
m.towers = make([][]tower, numXSlots)
for i := 0; i < numXSlots; i++ {
m.towers[i] = make([]tower, numYSlots)
for j := 0; j < numYSlots; j++ {
key := NewKey(int64(i), int64(j))
m.towers[i][j].init(int64(key))
}
}
}
二 . 定义区域 tower :
type tower struct {
towerId int64
context *TowerSyncContext
mapId2O