
回复
ECS架构就像游戏开发的乐高积木——用对了能搭出摩天大楼,用错了就是一堆零件。本文结合车载游戏项目经验,分享ECS在鸿蒙下的性能优化秘籍。
用元组定义组件就像拼乐高小块,每个组件只做一件事:
// 位置组件(2个Float,8字节)
typealias Position = (x: Float, y: Float)
// 动画组件(仅状态标识,1字节)
enum AnimState { | Idle | Run | Jump }
// 角色实体(组合两个组件)
let playerEntity = (position: Position(x: 10.5, y: 20.3), animState: AnimState.Run)
优化点:
在赛车游戏中,复用组件比新建更高效:
// 组件池设计
class ComponentPool<T> {
private var pool: [T] = []
func borrow() -> T {
if pool.isEmpty {
return createNew()
} else {
return pool.popLast()!
}
}
func recycle(component: T) {
pool.append(component)
}
}
// 使用示例(粒子效果组件池)
let particlePool = ComponentPool<Position>()
在怪物AI系统中,分块处理比单线程快3倍:
func MonsterAISystem(monsters: [Entity]) {
let threadCount = 4
let chunkSize = monsters.count / threadCount
let tasks = (0..threadCount).map { idx in
async {
let start = idx * chunkSize
let end = (idx == threadCount-1) ? monsters.count : (idx+1)*chunkSize
for i in start..end {
updateMonsterAI(monsters[i])
}
}
}
awaitAll(tasks)
}
用不可变组件避免锁竞争(适用于渲染系统):
// 不可变位置组件
typealias ImmutablePos = (x: Float, y: Float)
// 线程安全的更新方式
func moveEntity(entity: inout (pos: ImmutablePos, anim: AnimState), dx: Float, dy: Float) {
entity.pos = (x: entity.pos.x + dx, y: entity.pos.y + dy)
}
在射击游戏中,SoA比AoS的渲染效率高40%:
// AoS模式(传统布局)
struct EntityAoS {
var pos: Position
var health: Int
}
// SoA模式(缓存友好)
typealias PosArray = [Position]
typealias HealthArray = [Int]
let allPositions: PosArray = [...]
let allHealths: HealthArray = [...]
从AoS到SoA的转换函数(减少内存碎片):
func convertToSoA(entities: [EntityAoS]) -> (PosArray, HealthArray) {
let positions = entities.map { $0.pos }
let healths = entities.map { $0.health }
return (positions, healths)
}
// 赛车组件(轻量级元组)
typealias CarControl = (steer: Float, throttle: Float)
typealias CarPhysics = (speed: Float, angle: Float)
typealias CarRender = (modelId: Int, color: UInt32)
// 赛车实体(组合三个组件)
let raceCar = (control: CarControl(steer: 0, throttle: 1),
physics: CarPhysics(speed: 0, angle: 0),
render: CarRender(modelId: 101, color: 0xFF00FF00))
// 物理系统(分块计算)
func PhysicsSystem(cars: [Entity]) {
let chunks = divideIntoChunks(cars, chunkCount: 4)
let tasks = chunks.map { chunk in
async {
for car in chunk {
updatePhysics(car)
}
}
}
awaitAll(tasks)
}