文档目标:解析如何在 Unity 中实现同屏 500+ 敌人的高性能逻辑,参考 Vampire Survivors 的优化思路,并映射到 Unity DOTS (Data-Oriented Technology Stack) 的最佳实践。同时结合本项目特有的 GAS (Gameplay Ability System) 进行混合架构设计。
在传统的 MonoBehaviour 方式中,每个怪物都是一个 GameObject。
Enemy 类) 散落在堆内存的各个角落。EnemyA 时,它会将附近内存块加载到 L1/L2 缓存(Prefetching)。但如果 EnemyB 在内存的另一头,预取失效,CPU 必须停下来等待内存读取(Cache Miss)。这是性能的头号杀手。transform.position 交互有封送(Marshalling)开销。Update() 方法的虚函数调用本身就是巨大的 CPU 负担。Data-Oriented Design (DOD) 的核心思想是:CPU 喜欢处理连续的、简单的数据块。
[ {HP, Pos, Speed}, {HP, Pos, Speed}, ... ]Pos: [P1, P2, P3...]Speed: [S1, S2, S3...]HP: [H1, H2, H3...]虽然 Vampire Survivors 早期是基于 Phaser (JS) 开发的,但其优化逻辑通用:
不要给 500 个怪物挂 Rigidbody 或 BoxCollider。
DistanceSquared(A, B) < (R1+R2)^2。避免开方运算。不使用完整的 Entities 包,仅用 Job System 优化计算。
逻辑再快,渲染 500 个 DrawCall 也会死。
Graphics.DrawMeshInstanced 或 DrawMeshInstancedIndirect。ComputeBuffer,一次提交给 GPU。IComponentData (struct),如 MoveSpeedData, HealthData。SystemBase 或 ISystem,只负责逻辑。在 Project Vampirefall 中,我们结合 Gameplay Ability System (GAS) 设计,采用混合架构。
MonoBehaviour + AbilitySystemComponent (C# Class)。处理复杂逻辑、动画状态机。ECS Entity + BuffBuffer (DynamicBuffer)。处理移动、简单攻击、Buff 状态。场景: 特斯拉电塔释放“连锁闪电”,击中 50 个敌人,造成伤害并施加“感电” Debuff。
流程:
GA_ChainLightning 触发。EntityQuery 瞬间找到范围内最近的 50 个带有 Tag_Enemy 的实体。ApplyEffectJob。Health -= Damage)。BuffBuffer 添加 GE_Shock (感电) 的 ID。代码片段:Buff 处理系统 (ECS)
[BurstCompile]
public partial struct BuffProcessingSystem : ISystem
{
public void OnUpdate(ref SystemState state)
{
float dt = SystemAPI.Time.DeltaTime;
// 遍历所有拥有 Buff 缓冲区的实体
foreach (var buffBuffer in SystemAPI.Query<DynamicBuffer<ActiveBuff>>())
{
for (int i = 0; i < buffBuffer.Length; i++)
{
// 处理持续时间
var buff = buffBuffer[i];
buff.RemainingTime -= dt;
// 处理 Buff 逻辑 (例如:每秒伤害)
if (buff.TypeId == BuffIDs.Poison) {
// ... Apply Damage Logic ...
}
// 移除过期 Buff
if (buff.RemainingTime <= 0) {
buffBuffer.RemoveAt(i);
i--;
}
}
}
}
}
struct 以利用 SoA 优势。| 平台 | 同屏目标 (60FPS) | DrawCalls 限制 | 物理计算耗时 | | :— | :— | :— | :— | | PC (Mid) | 2000+ | < 1500 (Batching后) | < 3ms | | Mobile (High) | 500+ | < 300 | < 4ms | | Mobile (Low) | 100+ | < 100 | < 5ms |