Skip to main content

⚡ 性能预算与优化标准

为了确保游戏在目标平台(PC 中低配 / Steam Deck / 潜在的主机)上稳定运行 60FPS,必须严格执行此预算。

1. 概述与目标 (Overview & Targets)

目标平台规格 (Target Specs)

  • 基准平台: GTX 1060 / Steam Deck.
  • 目标帧率: 60 FPS (16.6ms per frame).
  • 分辨率: 1080p.

性能分级策略 (LOD Policy)

设置阴影抗锯齿怪物数量粒子密度
Low仅主角FXAA200 (超过不再生成)50%
Med实时硬阴影SMAA35075%
High软阴影 (Cascade)TAA500100%

时间感知速查表

将各种操作放入同一个时间尺度中理解:
操作耗时量级16.6ms 帧预算占比直觉类比
L1 Cache 访问1 ns0.00006%眨眼的 1/1,000,000
L2 Cache 访问4 ns0.00024%
主内存访问100 ns0.0006%
SSD 读取100 us0.6%
HDD 读取10 ms60% ⚠️半帧没了
网络延迟 (同城)5 ms30%
网络延迟 (跨国)200 ms1200%12 帧!
完整 GC50 ms300%3 帧全卡

2. 内存预算 (Memory Budget)

内存预算 (Memory Budget)

  • 总内存: < 4GB (System RAM).
  • 显存 (VRAM): < 2GB.
  • 纹理:
    • 角色: 2048x2048 (Atlas).
    • 环境: 1024x1024 (Tiling).
    • 杂兵: 512x512 或 1024 合集。
    • 压缩: PC 使用 DXT5/BC7, 移动端使用 ASTC。

内存微观基准 (Memory Micro-Benchmarks)

以下数据为 近似值,用于估算内存占用。

1. 基础数据类型 (C#)

类型 (C#)大小 (Bytes)备注
bool1 (or 4)单个字段通常对齐到 4 字节,数组中为 1 字节。
byte / sbyte1最小单位。
char2UTF-16 字符。
short / ushort2
int / uint4最常用的整数。
float4物理、坐标常用。
long / ulong8大数。
double8高精度计算。
Reference (引用)864 位系统指针大小。Class 的引用。
Object Header~16-24每个 class 对象实例的额外开销 (SyncBlock + TypeHandle)。
⚠️ 小对象陷阱: 创建一个只包含 1 个 intclass 实例,其实际占用可能高达 24-32 bytes (Header + int + Padding)。大量小对象必须用 struct

1.1 Struct vs Class 内存深度对比

特性Class (引用类型)Struct (值类型)备注
分配位置堆 (Heap)栈 (Stack) 或 嵌入在父对象中Class 导致内存碎片和 GC。
额外开销 (Overhead)~16-24 Bytes (Header)0 BytesStruct 没有对象头。
引用开销8 Bytes (64 位指针)0 BytesClass 变量存的是指针,Struct 存的是数据本身。
数组内存布局指针数组: [Ptr1, Ptr2, ...]连续数据: [Data1, Data2, ...]Struct 数组对 CPU Cache 极其友好。
GC 压力: 需回收对象头: 随栈/父对象销毁只要不装箱 (Boxing),Struct 零 GC。
内存布局示例 (含 2 个 int 的对象):
Class Point { int x; int y; }  // 堆上: [Header 16B] + [x 4B] + [y 4B] = 24 Bytes + [栈上指针 8B] = 32 Bytes
Struct Point { int x; int y; } // 栈上/数组内: [x 4B] + [y 4B] = 8 Bytes (纯数据, 无额外开销)

2. Unity 对象开销 (空对象)

对象类型内存占用 (估算)备注
GameObject (Empty)~100 - 200 BytesC++ 原生非托管内存 + C# 包装器。
Transform~400 - 500 Bytes含 Position, Rotation, Scale, 矩阵缓存, 父子指针。很重!
Empty GameObject~0.5 - 1 KB一个空的 GameObject + Transform 的总开销。
MeshFilter~100 Bytes仅引用 Mesh。
MeshRenderer~300 Bytes引用材质和 AABB。

3. 纹理内存 (Texture Memory)

公式: 宽 x 高 x BytesPerPixel
格式Bits/PixelBytes/Pixel1024x1024 大小说明
RGBA 32 bit3244 MB无压缩,最高画质。UI/图标常用。
RGB 24 bit2433 MB无透明通道。不推荐 (对齐问题)。
RGBA 16 bit1622 MB抖动明显 (Dither)。复古风可用。
Alpha 8811 MB单通道掩码/SDF。
DXT1 / BC140.50.5 MB (1/8)PC 标准压缩 (无透明/Cutout)。
DXT5 / BC3811 MB (1/4)PC 标准压缩 (全透明)。
BC7811 MB (1/4)PC 高质量压缩 (推荐)。
ASTC 4x4811 MB (1/4)移动端高质量。
ASTC 6x63.56~0.450.45 MB移动端均衡 (推荐)。
ASTC 8x820.250.25 MB (1/16)移动端低配/特效/背景。

4. 网格数据 (Mesh Data)

详细数据请参阅 图形预算 > 模型与骨骼动画性能

5. 音频内存 (Audio Memory)

格式压缩比 (近似)1 分钟立体声大小 (44.1kHz)建议
PCM (WAV)1:1 (无压缩)~10 MB仅用于极短、极低延迟的音效 (UI 点击)。
ADPCM~3.5:1~3 MB频繁播放的短音效 (脚步、枪声)。CPU 开销极低。
Vorbis / MP3~10:1 (可变)~1 MB背景音乐 (BGM)、长语音。CPU 开销较高。

3. 程序预算 (Program/CPU Budget)

CPU 预算 (CPU Budget)

Roguelike + 塔防意味着海量实体,CPU 是最大瓶颈。
  • 同屏单位数: 最大 500 (怪物 + 塔 + 投射物)。
  • AI 更新频率:
    • 近处怪物 (<20m): 每帧更新。
    • 远处怪物 (>20m): 每 3-5 帧更新一次逻辑 (Time Slicing)。
    • 不可见怪物: 仅更新位置,暂停动画和物理。
  • 物理 (Physics):
    • 使用 Physics.Simulate 或 DOTS Physics。
    • 禁止使用 MeshCollider 对动态物体。全部使用 Sphere/Capsule/Box。
  • 垃圾回收 (GC):
    • 战斗中 禁止 new 操作。
    • 所有投射物、特效、伤害飘字必须使用 Object Pool

优化技术栈 (Tech Stack)

1. DOTS (Data-Oriented Technology Stack)

对于海量怪物的移动和简单逻辑,考虑使用 ECS (Entities) + Burst Compiler。这是解决千人同屏的终极方案。

🧠 DOTS 性能提升原理详解

DOTS 的核心不是”新技术”,而是让代码适配现代 CPU 的物理特性
1. 内存布局:AoS vs SoA
传统 OOP (Array of Structs):
[Entity1: Position, Rotation, Health, AI...]
[Entity2: Position, Rotation, Health, AI...]  ← 内存中交错排列
[Entity3: Position, Rotation, Health, AI...]
ECS (Struct of Arrays):
Positions: [Pos1, Pos2, Pos3, ...]   ← 同类型数据连续存储
Rotations: [Rot1, Rot2, Rot3, ...]
Healths:   [HP1,  HP2,  HP3,  ...]
为什么 SoA 更快? 参考 CPU 下的 Cache Miss
场景OOP (AoS)ECS (SoA)原因
遍历 10000 个 Position加载整个 Entity (~100 bytes)只加载 Position (12 bytes)减少 8x 内存读取
Cache Line 利用率每条 Cache Line (64B) 只有 ~12B 有用整条 Cache Line 全部是 Position5x 利用率提升
Prefetch 效率随机跳转,Prefetcher 失效顺序访问,Prefetcher 全中100x 速度差距
2. Burst Compiler:SIMD 向量化
Burst 将 C# 代码编译为原生机器码,并自动应用 SIMD (Single Instruction, Multiple Data):
操作普通 C#Burst + SIMD加速比
4 个 float 加法4 条指令1 条 SSE/AVX 指令4x
8 个 float 乘法8 条指令1 条 AVX 指令8x
循环 + 条件判断逐个处理自动展开 + 无分支10-50x
3. Job System:多核并行
Unity 传统 MonoBehaviour 只能跑在主线程。Job System 让逻辑分发到所有 CPU 核心:
CPU 核心数MonoBehaviourJobs (理论)实际加速
4 核1x4x~3x (调度开销)
8 核1x8x~5-6x
16 核1x16x~8-10x
4. 综合性能对比 (实测参考)
场景:移动 10000 个 Entity (每帧更新 Position)
方案耗时 (每帧)对比基准
MonoBehaviour + Transform~15-25 ms100% (基准)
纯 C# 脚本 (无 Burst)~5-10 ms~50%
ECS (无 Burst)~2-4 ms~20%
ECS + Burst~0.3-0.8 ms~3%
ECS + Burst + Jobs (8 核)~0.05-0.15 ms~0.5% 🚀
🚀 结论: DOTS 全栈可以带来 50-200x 的性能提升,核心原因:
  • Cache 友好: 连续内存,Prefetch 全中
  • SIMD: 一条指令处理多个数据
  • 多核: 充分利用现代 CPU 所有核心
  • 无 GC: 使用 NativeArray,战斗中零分配

2. GPU Skinning

将骨骼动画计算从 CPU 转移到 GPU Shader,解放 CPU 算力。

3. Addressables

资源按需加载,避免启动时加载所有资源导致内存溢出。

CPU 微观基准 (CPU Micro-Benchmarks)

以下数据为近似值(基于现代 PC/Console 架构),用于指导代码编写。

CPU 下的 Cache Miss:隐形杀手

现代 CPU 极快,瓶颈通常在内存墙 (Memory Wall)。 假设 CPU 主频 3GHz (1 cycle ≈ 0.33ns)。执行 100 万次 操作的理论时间差异:
存储层级访问延迟 (Cycles)访问时间 (ns)100 万次访问总耗时 (理想估算)类比
L1 Cache3 - 41 ns0.5 - 1 ms从桌子上拿一张纸
L2 Cache10 - 123 - 4 ns3 - 4 ms从书架上拿一本书
L3 Cache30 - 7010 - 20 ns10 - 20 ms从隔壁房间拿一本书
Main RAM200 - 300+60 - 100 ns60 - 100 ms (掉帧!)下楼去图书馆拿一本书
⚠️ 结论:
  • 顺序数组遍历 (Data Oriented): CPU 预取器 (Prefetcher) 极其高效,几乎全中 L1/L2。100 万次遍历 = 1-2ms。
  • 随机指针跳转 (OOP/Linked List): 也就是传统 class 引用满天飞。每次跳转都可能是 Cache Miss。100 万次跳转 = 100ms (直接卡死由 60FPS 跌至 10FPS)。
  • 这就是为什么我们要用 Struct 数组和 Object Pool (保持内存连续)。

Unity 常见 API 热点估算

基于 PC 平台 (i7 级别单核) 的粗略估算。移动端请将时间 x5 - x10
操作近似耗时 (每次)1000 次耗时危险等级建议
transform.position (get/set)~20 ns0.02 ms🟢 安全稍微有点开销 (C++到 C# marshalling),但在热循环中还是尽量缓存。
GetComponent<T>()~100 - 300 ns0.1 - 0.3 ms🟡 留意不要在 Update 里调。在 Awake 缓存。
GameObject.Instantiate0.1 ms - 5.0 ms+100ms+ (卡顿)🔴 致命必须用对象池。包含复杂组件/子物体时极慢。
Destroy()~0.05 ms+50ms+🟠 严重触发 GC,导致后续卡顿。
FindObjectOfType线性遍历全场景N/A🔴 禁止随着场景物体增多呈线性增长。运行时绝不要用。
Camera.main~2 ms (老版本)N/A🟠 慢内部是 FindByTag。新版 Unity 有优化,但仍建议手动缓存 Singleton
Debug.Log0.1 ms+100ms+🔴 卡顿涉及字符串拼接、堆栈抓取、IO。正式包必须剔除。
Physics.Raycast~1 - 5 us1 - 5 ms🟡 适中取决于场景碰撞体数量。尽量用 LayerMask 过滤。

GC (垃圾回收) 开销

.NET/Mono 的 GC 是**“Stop The World”**模式,一旦触发,主线程暂停。
GC 类型近似耗时触发条件危险等级
Gen0 (快速回收)0.5 - 2 ms临时小对象 (如 lambda 捕获、临时字符串)🟡 频繁则累积
Gen1 (中等回收)2 - 10 ms存活过一次 Gen0 的对象🟠 明显卡顿
Gen2 (完整回收)10 - 100+ ms长期生存的大对象、大数组🔴 灾难性帧卡顿
⚠️ 重要结论:
  • 每帧分配 1KB 内存:约每秒触发 1 次 Gen0 GC (~1-2ms 卡顿)。
  • 战斗中禁止 new:所有对象必须预分配或使用对象池。
  • String 拼接是 GC 大户:每次 "a" + "b" 都产生新对象。

IO 操作开销

IO 是毫秒级操作,绝不能在主线程执行。
操作类型近似耗时备注
SSD 随机读 (4KB)0.05 - 0.15 msNVMe SSD,极快但仍远超 CPU 运算。
HDD 随机读 (4KB)5 - 15 ms机械寻道,一次读取 = 掉 1 帧。
文件打开 (fopen)0.1 - 1 ms系统调用开销。
小文件完整读取 (1KB)0.1 - 0.5 ms (SSD)文件越大越慢。
大文件读取 (10MB)50 - 200+ ms必须异步 + 流式加载。
PlayerPrefs.Save()5 - 50 ms同步写磁盘。只在关键点调用。
JSON 反序列化 (1KB)0.1 - 0.5 ms取决于解析器复杂度。
JSON 反序列化 (100KB)10 - 50 ms考虑换用 MessagePack/Protobuf。
🔴 核心原则: 所有 IO 必须在后台线程 + 异步回调中执行。

字符串操作开销

字符串在 C# 中是不可变的,每次修改都创建新对象。
操作近似耗时GC 分配建议
短字符串拼接 "a" + "b"~50 - 100 ns是 (新对象)少量可接受,循环中禁止。
循环拼接 1000 次1 - 5 ms + GC1000 个临时对象🔴 必须用 StringBuilder
StringBuilder.Append x1000~0.1 - 0.3 ms预分配则无✅ 正确做法。
string.Format~200 - 500 ns是 (boxing 可能)$"" 插值或 StringBuilder
int.ToString()~100 - 200 ns缓存常用数字字符串 (如 “0”-“99”)。
string.Contains/IndexOfO(n) 线性长字符串慎用热循环。

反射 (Reflection) 开销

反射是运行时元数据查询,极其昂贵。
操作近似耗时对比直接调用建议
GetType()~5 - 20 ns~1x相对廉价。
typeof(T)~1 ns编译期确定✅ 尽量用这个。
MethodInfo.Invoke1 - 10 us100x - 1000x 慢🔴 热路径禁止。
GetField/GetProperty~100 - 500 ns10x - 50x 慢缓存 FieldInfo/PropertyInfo。
Activator.CreateInstance1 - 5 us50x - 200x 慢用泛型工厂 new T() 或缓存。
替代方案: Expression Trees 编译、Source Generators、或预生成代码。

数学运算开销 (CPU)

在 CPU 上,浮点运算已非常快,但除法和超越函数仍有显著开销。
操作近似耗时 (Cycles)备注
加/减/乘 +, -, *1 - 3极快,流水线优化。
除法 /10 - 20比乘法慢 5-10 倍。用乘法替代 (如 x * 0.5f 代替 x / 2)。
平方根 sqrt10 - 20硬件指令,尚可。rsqrt (倒数平方根) 更快。
三角函数 sin, cos50 - 100查表或泰勒展开近似可提速。
指数/对数 exp, log50 - 100同上。
Mathf.Lerp~5 - 10内部是 a + (b-a) * t
Vector3.Normalize~20 - 50包含 sqrt。如只需方向比较,用 sqrMagnitude

网络操作延迟

网络是变化最大的不确定因素。
操作典型延迟备注
本地回环 (localhost)< 0.1 ms测试用。
局域网 (LAN)0.1 - 1 ms理想情况。
国内跨省 (同运营商)20 - 50 ms正常延迟。
国内跨运营商50 - 150 ms可能需要加速器。
跨国 (中美)150 - 300+ ms物理限制 (光速)。
DNS 查询50 - 200 ms首次连接。缓存 IP。
TCP 握手 (建连)RTT x 1.5约 1.5 倍往返时间。
TLS 握手 (HTTPS)RTT x 2-3额外 1-2 次往返。复用连接!

线程与同步开销

多线程不是免费的午餐。
操作近似耗时备注
创建新线程0.1 - 1+ ms极其昂贵!必须用线程池。
线程池任务调度1 - 10 us比创建线程快 100 倍。
lock (无竞争)10 - 50 ns几乎免费。
lock (有竞争)1 us - 数 ms线程阻塞等待。减少锁粒度。
Interlocked 原子操作10 - 50 ns无锁首选,但仍有 Cache Line 同步开销。
上下文切换 (Context Switch)1 - 10 us线程过多时 CPU 疲于切换。
Task.Run (调度)~100 - 500 ns加入线程池队列。
async/await (无阻塞)~50 - 100 ns状态机开销。相比同步代码略慢但可接受。

4. 图形预算 (Graphics/GPU Budget)

GPU 预算 (GPU Budget)

  • Draw Calls (Batches): < 2000。
    • 必须启用 GPU Instancing (大量同屏怪物)。
    • UI 图集必须合并,减少 Draw Call。
  • Triangle Count: < 1.5M (全场景)。
    • 主角: 15k - 20k。
    • 杂兵: 1.5k - 3k (使用 LOD)。
    • Boss: 10k - 15k。
  • Overdraw:
    • 特效粒子限制透明层数。
    • 避免全屏后处理叠加过多。

GPU 微观基准 (Graphics Micro-Benchmarks)

以下数据为近似值(基于现代 PC/Console 架构),用于指导 Shader 编写。

Shader 指令开销参考 (GPU)

GPU 是大规模并行架构,吞吐量 (Throughput) 比延迟更重要。但当指令产生依赖或特定复杂运算时,开销会指数上升。
操作类型指令示例近似开销 (Cycles)备注
基础运算+, -, *, madd1现代 GPU 通常一个周期能处理 float4 的乘加。
插值/透视varying 插值1-2硬件光栅化阶段处理,通常免费。
倒数/平方根rcp, rsqrt2-4特殊功能单元 (SFU) 处理。
三角函数sin, cos4-8SFU 处理。精度要求高时更慢。
复杂函数pow, log, exp, atan8-16+昂贵。在像素 Shader 中慎用,尽量用拟合公式近似。
纹理采样tex2D, SampleLatency: 400-800延迟极高,但 GPU 会在等待时切换线程。依赖纹理读取(用一次采样的结果去采样下一次)会吃满延迟,导致 GPU 停顿。
分支判断if, loop1 - ???如果同个 Warp/Wavefront 内所有像素走向相同分支,开销很小;如果分歧 (Divergence),则两边都要执行(开销 double)。
Discardclip, discardVariable会破坏 Early-Z 优化,可能导致 Overdraw 暴增。
Normal Mapping1x tex2D + TBN 变换+1 采样 + ~10 ALU额外一次采样 + 切线空间转换。性价比极高的细节提升。
Triplanar Mapping3x tex2D + 混合权重+3 采样 + ~20 ALU三个轴向各采样一次并混合。开销是普通 UV 的 3 倍,用于无 UV 展开的地形/程序化模型。可优化为 2-sample 近似。
Parallax Mapping多次 tex2D (步进)+4-16 采样视差效果需多次深度查询。移动端慎用。Steep Parallax 更贵。
PBR (标准)Albedo + Normal + MRAO+3-4 采样 + ~50 ALU金属度/粗糙度/AO 贴图 + BRDF 计算。现代游戏标配,但开销不低。
屏幕空间反射 (SSR)Ray Marching极高 (数百 ALU)逐像素射线步进。仅用于高端画质。
光照模型
光照类型计算内容近似开销备注
Unlit (无光)纯颜色/纹理~5 ALU最便宜,用于 UI、特效、卡通描边。
Lambert (漫反射)N·L~10 ALU最简单的光照模型。
Blinn-PhongLambert + (N·H)^n~20-30 ALU经典高光模型。
GGX/Cook-Torrance (PBR)D + F + G 项~50-100 ALU正确的物理反射。金属/粗糙度工作流。
各向异性高光额外切线计算~30-50 ALU头发、拉丝金属。
SSS (次表面散射)多次采样/预积分 LUT~50-200 ALU皮肤、蜡烛、树叶。实时版通常用 LUT 近似。
卡通着色 (Cel)离散化光照 + 描边~20-40 ALUstep/smoothstep 分段。
阴影技术
阴影类型采样次数近似开销备注
硬阴影 (1x PCF)1+1 采样锯齿明显。
软阴影 (4x PCF)4+4 采样 + ~20 ALU常用质量档。
软阴影 (16x PCF)16+16 采样 + ~40 ALUPoisson Disk 采样。
CSM (级联阴影)取决于级数+1-4 采样/级 + 级联判断开放世界必备。远景 LOD 阴影。
Contact Shadow射线步进 (4-16 步)+4-16 采样物体接触处的细节阴影。
PCSS (软阴影)查找 + 采样极高真实半影效果,仅高端。
环境与间接光
技术采样/计算近似开销备注
Cubemap 反射1x texCUBE+1 采样简单环境映射。
Cubemap + Mip 模糊1x texCUBE (LOD)+1 采样粗糙度驱动模糊,PBR 标配。
平面反射额外 RT 渲染Draw Call x2复制场景渲染开销!谨慎使用。
Lightmap 采样1-2x tex2D+1-2 采样静态光照,极高性价比。
Light Probe (SH)球谐计算~20-30 ALU动态物体间接光。无采样。
Reflection Probe1x texCUBE+1 采样局部反射探针。
常用特效技术
特效实现方式近似开销备注
Fresnel (边缘光)1 - N·V~5 ALU几乎免费的轮廓效果。
Rim Light (边缘高光)Fresnel + pow~10 ALU增强轮廓感。
Dissolve (溶解)噪声采样 + clip+1 采样 + ~10 ALU消融/出现效果。
UV 动画时间偏移 UV~5 ALU流动效果。
UV 扭曲噪声采样偏移 UV+1 采样 + ~10 ALU热浪、水面扭曲。
顶点动画VS 中偏移顶点~10-30 ALU (VS)旗帜、草、水面波动。便宜因为在 VS。
GPU 粒子Compute/VS 模拟取决于系统比 CPU 粒子快 10-100x。
Outline (描边)背面挤出 / 后处理+1 Pass 或 ~20 ALU卡通渲染常用。
高级渲染技术
技术开销备注
Tessellation极高 (硬件依赖)动态细分。移动端不支持/极慢。
Displacement MappingTessellation + 采样同上 + 纹理开销。
Decal (投影贴花)+1 Pass 或延迟读取弹孔、血迹。Deferred 友好。
Volumetric Fog极高 (射线步进)3D 体积雾。需 8-64 步,降分辨率渲染。
Bent Normal / AO+1 采样预烘焙数据,增强间接光遮蔽感。
透明与混合
技术开销备注
Alpha Test (Cutout)~5 ALUclip/discard,Early-Z 破坏风险。树叶、铁丝网。
Alpha Blend带宽开销读+写 Color Buffer。Overdraw 累积!
Premultiplied Alpha同 Blend避免边缘黑边。
Additive Blend同 Blend发光、火焰。叠加更亮。
OIT (顺序无关透明)极高多 Pass/链表。正确排序透明层。研发中技术。
Dithered Transparency~10 ALU图案化 discard,伪透明,保留 Z-buffer。

Overdraw 与 Fill Rate:像素级性能

Overdraw 指同一像素被多次绘制。每多画一次,就多执行一遍 Fragment Shader。
分辨率与像素数量
分辨率像素数量备注
720p (1280x720)0.92M约 100 万像素
1080p (1920x1080)2.07M约 200 万像素
1440p (2560x1440)3.69M约 370 万像素
4K (3840x2160)8.29M约 830 万像素
Overdraw 开销计算
假设 1080p (约 200 万像素),Shader 每像素 50 ALU 指令:
Overdraw 倍率实际渲染像素数Shader 执行次数相对基准
1x (理想)2M100M ALU ops100%
2x (轻度)4M200M ALU ops200%
3x (中度)6M300M ALU ops300%
5x (严重,粒子/UI)10M500M ALU ops500% ⚠️
10x+ (灾难)20M+1B+ ALU ops爆炸 🔴
🔴 实战案例:
  • 全屏粒子特效 (火焰、烟雾): 每层粒子都是一次 Overdraw。10 层粒子 = 10x Overdraw。
  • 半透明 UI 叠加: 血条 + 技能栏 + 弹窗,每层都要混合。
  • 后处理链: Bloom + DOF + 色调映射,每个 Pass 都是一次全屏绘制。
Fill Rate (填充率) 预算
Fill Rate = GPU 每秒能填充的像素数 (包含 Shader 计算)。
GPU 档次典型 Fill Rate1080p @ 60FPS 裕量
GTX 1060 / RX 580~50 GPixel/s2M × 60 = 120M/s → 裕量 ~400x
RTX 3060 / RX 6600~100 GPixel/s裕量 ~800x
移动端 (Mali-G78)~5-10 GPixel/s裕量 ~40-80x (极紧张!)
⚠️ 注意: 上面是理论峰值。复杂 Shader (PBR + 多贴图) 会显著降低实际 Fill Rate。移动端尤其脆弱!
带宽开销
每个像素的显存带宽消耗:
操作每像素带宽1080p 全屏 (2M 像素)
读取 Color Buffer (RGBA8)4 bytes8 MB
写入 Color Buffer4 bytes8 MB
读取 Depth Buffer (24-bit)3-4 bytes6-8 MB
1 张 1024x1024 纹理采样依赖 CacheMiss 时吃带宽
HDR Buffer (RGBA16F)8 bytes16 MB
一次全屏后处理 Pass (读+写): 约 16-32 MB 带宽。 GTX 1060 带宽 ~192 GB/s → 一帧 16.6ms 内可传输 ~3.2 GB。 理论上能支持 ~100 次全屏 Pass,但加上其他开销,实际 10-20 次就是极限
常见后处理效果开销
基于 1080p @ GTX 1060 级别的近似 GPU 时间:
后处理效果Pass 数量GPU 耗时 (近似)危险等级备注
Blit (简单拷贝)10.1 - 0.2 ms🟢 廉价纯带宽开销。
Gamma/Tonemapping10.1 - 0.3 ms🟢 廉价每像素几条 ALU。
FXAA10.3 - 0.5 ms🟢 廉价快速边缘检测 + 混合。
SMAA (1x)2-30.5 - 1.0 ms🟡 适中多 Pass,效果更好。
TAA1-20.5 - 1.5 ms🟡 适中需要 Motion Vector + History Buffer。
Vignette/Film Grain10.1 - 0.2 ms🟢 廉价几乎免费的风格化。
Color Grading (LUT)10.2 - 0.4 ms🟢 廉价3D LUT 查表,一次采样。
Bloom (基础)4-61.0 - 2.0 ms🟡 适中降采样 + 多级模糊 + 合成。
Bloom (高质量)8-122.0 - 4.0 ms🟠 较重更多 Mip 级别和迭代。
景深 DOF (简单)2-31.0 - 2.0 ms🟡 适中CoC 计算 + 模糊。
景深 DOF (散景)4-83.0 - 6.0 ms🔴 昂贵真实光圈形状需要更多采样。
运动模糊1-20.5 - 1.5 ms🟡 适中依赖 Motion Vector 质量。
SSAO (简单)2-41.5 - 3.0 ms🟠 较重多次深度采样。
SSAO (HBAO+/GTAO)4-63.0 - 5.0 ms🔴 昂贵高质量环境光遮蔽。
SSR (屏幕空间反射)4-84.0 - 10.0 ms🔴 极贵Ray Marching + 多级模糊。移动端禁用。
体积光/God Rays4-82.0 - 5.0 ms🔴 昂贵射线步进或径向模糊。
全屏模糊 (Gaussian)20.5 - 1.0 ms🟡 适中分离式卷积 (H+V)。
Kawase Blur4-60.8 - 1.5 ms🟡 适中比高斯更高效的迭代模糊。
📊 典型后处理栈开销:
配置效果组合总 GPU 耗时
极简 (移动端)Tonemapping + FXAA + Vignette0.5 - 1.0 ms
标准 (PC)Bloom + TAA + Color Grading + Vignette2.0 - 4.0 ms
高端 (PC)Bloom + SSAO + SSR + TAA + DOF8.0 - 15.0 ms ⚠️
16.6ms 帧预算下,高端后处理可能吃掉 50-90% 的 GPU 时间!

GPU Instancing 性能对比

GPU Instancing 让相同 Mesh + Material 的物体一次 Draw Call 批量渲染,而非逐个提交。
极端场景测试 (渲染 10,000 个简单立方体)
方案Draw CallsCPU 提交时间GPU 渲染时间总帧时间
无 Instancing (逐个渲染)10,000~15-25 ms~2-5 ms20-30 ms (33 FPS)
GPU Instancing1~0.1-0.3 ms~2-5 ms2-6 ms (166+ FPS)
性能差异10000x 减少50-100x 提升相同5-10x 总提升
不同物体数量的 Draw Call 对比
同类物体数量无 InstancingGPU InstancingSRP Batcher
100100 DC1 DC1-10 DC
1,0001,000 DC1 DC10-50 DC
10,00010,000 DC ⚠️1 DC50-200 DC
100,000卡死 🔴1-10 DC500+ DC
为什么 Draw Call 这么贵?
每个 Draw Call 涉及:
  1. CPU→GPU 通信:状态切换、缓冲区绑定 (~5-50 us/次)
  2. 驱动验证:参数校验、着色器编译检查
  3. 命令队列:提交渲染命令到 GPU
经验法则:
  • Draw Call 安全上限: PC ~2000-3000,移动端 ~200-500
  • 超过上限: CPU 成为瓶颈,GPU 反而在等待命令
Instancing 使用条件
条件是否支持 Instancing
相同 Mesh + 相同 Material✅ 完美支持
相同 Mesh + 不同颜色 (MaterialPropertyBlock)✅ 支持
不同 Mesh❌ 无法合批
不同 Material❌ 无法合批
Skinned Mesh (骨骼动画)❌ 需 GPU Skinning 特殊处理
透明物体 (需排序)⚠️ 部分支持,排序可能破坏批次
实战参考 (塔防游戏场景)
场景内容无 InstancingGPU Instancing优化效果
200 个相同小兵200 DC1 DC✅ 极佳
50 种不同怪物各 10 只500 DC50 DC✅ 良好 (每种 1 DC)
1000 颗相同子弹1000 DC1 DC✅ 极佳
500 个相同草丛500 DC1 DC✅ 极佳
100 个不同道具100 DC100 DC❌ 无法优化
🐢 100 万次运算对比 (GPU):
  • 1M 次乘加 (x * y + z): 几乎瞬间完成 (受限于显存带宽或 ALU 峰值)。
  • 1M 次 \text{pow}(x, y): 比乘加慢 10-20 倍。
  • 1M 次依赖纹理采样: 如果发生 Cache Miss,将导致 GPU 核心大量闲置等待 DRAM。

模型与骨骼动画性能

顶点/三角形数量开销
模型类型推荐顶点数推荐面数备注
UI 图标/2D< 100< 50精灵已足够。
粒子/子弹4-502-20Billboard 或简单形状。
杂兵 (大量同屏)500 - 1.5K300 - 1K对 Instancing 友好。LOD 降至 100-300。
精英怪2K - 5K1K - 3K中等细节。
Boss5K - 15K3K - 10K可添加更多细节。
主角 (玩家角色)10K - 25K5K - 15K最近距离观看,需要细节。
环境物体 (LOD0)500 - 5K300 - 3K根据屏幕占比调整。
地形 Tile视复杂度动态 LOD使用 Unity Terrain LOD 或自定义。
全场景三角形预算
平台目标总三角形备注
PC (GTX 1060)< 1.5M60FPS 目标。
PC (高端)< 5M可更激进。
Steam Deck< 1M功耗敏感。
移动端 (高端)< 500K严格控制。
移动端 (中低端)< 200K非常严格!
骨骼数量开销 (CPU Skinning)
每个骨骼需要矩阵运算 + 顶点变换,CPU Skinning 开销与骨骼数成正比。
骨骼数量CPU 开销估算 (每角色)建议用途
1-10 骨骼~0.01 ms简单道具、武器。
20-30 骨骼~0.02-0.05 ms基础人形怪物。
50-60 骨骼~0.05-0.1 ms标准人形 + 手指/面部。
100+ 骨骼~0.1-0.3 ms复杂角色。主角专用
200+ 骨骼~0.3-1.0+ ms极端情况。避免!
同屏骨骼角色数量上限
假设目标:每帧 Skinning 总开销 < 3ms (留给其他 CPU 工作)
每角色骨骼数CPU Skinning 上限GPU Skinning 上限
30 骨骼~60-100 角色500+ 角色
60 骨骼~30-50 角色300+ 角色
100 骨骼~15-30 角色150+ 角色
🚀 GPU Skinning 的优势:
  • 骨骼矩阵计算移至 GPU Shader
  • CPU 只需上传矩阵数据 (每角色 ~几 KB)
  • 同屏角色数可提升 5-10x
骨骼权重 (Bones per Vertex)
每个顶点受多少骨骼影响:
Quality 设置权重数开销效果
1 Bone1最快刚性变形,关节处有裂缝。
2 Bones2+50%基本平滑。移动端推荐。
4 Bones (默认)4+100%良好平滑。PC 标准。
Unlimited无限极高电影级品质。实时游戏避免。
Mesh 数据各分量开销
每个顶点的内存占用:
顶点属性大小 (bytes)备注
Position12 (float3)必须。
Normal12 (float3)光照必须。可压缩为 4 bytes (packed)。
Tangent16 (float4)Normal Map 必须。
UV08 (float2)主纹理。
UV18 (float2)Lightmap。
Color4 (RGBA8)顶点色。可选。
BoneWeights16-324 骨骼 = 16 bytes 索引 + 16 bytes 权重。
总计 (典型)50-80 bytes/顶点
模型数据量示例
模型顶点数每顶点大小内存占用
杂兵 (1K 顶点)1,00060 bytes60 KB
主角 (20K 顶点)20,00080 bytes1.6 MB
Boss (15K 顶点)15,00070 bytes1 MB
100 个杂兵 (Instanced)1,00060 bytes60 KB (共享)
100 个杂兵 (非 Instanced)100,00060 bytes6 MB ⚠️