专家级/架构级知识体系架构介绍
1. 内存管理与GC优化 - 深度剖析
托管堆与非托管内存
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
public class MemoryManagement {
// 托管内存 - 会产生GC
List<Vector3> managedList = new List<Vector3>();
// 非托管内存 - 无GC,但需手动释放
NativeArray<Vector3> nativeArray;
void Start() {
// 分配非托管内存
nativeArray = new NativeArray<Vector3>(1000, Allocator.Persistent);
}
void OnDestroy() {
if (nativeArray.IsCreated) {
nativeArray.Dispose(); // 必须手动释放!
}
}
// 使用unsafe代码直接操作内存
unsafe void UnsafeMemoryAccess() {
void* ptr = NativeArrayUnsafeUtility.GetUnsafePtr(nativeArray);
Vector3* vectorPtr = (Vector3*)ptr;
for (int i = 0; i < nativeArray.Length; i++) {
vectorPtr[i] = new Vector3(i, i, i);
}
}
}
// 零GC的字符串操作
public static class StringOptimization {
private static readonly StringBuilder sb = new StringBuilder(256);
public static string FormatScore(int score) {
sb.Clear();
sb.Append("Score: ");
sb.Append(score);
return sb.ToString(); // 只有这里产生GC
}
// 使用Span<T>避免字符串分配 (C# 7.2+)
public static void ProcessString(ReadOnlySpan<char> text) {
// 直接在栈上操作,无GC
}
}
// struct vs class 的深度理解
public struct LargeStruct { // 大struct会导致栈复制开销
public float a, b, c, d, e, f, g, h;
}
public readonly struct ReadOnlyStruct { // 只读struct,编译器优化
public readonly float Value;
}
public ref struct RefStruct { // 只能在栈上分配
public Span<byte> Data;
}
GC.Alloc热点分析
public class GCOptimization {
// 每帧分配 - 产生大量GC
void Update_Bad() {
foreach (var item in GetEnemies()) { // GetEnemies()返回新List
// ...
}
var position = new Vector3(1, 2, 3); // 装箱
SendMessage("OnHit", position); // SendMessage产生GC
}
// 缓存和重用
private List<Enemy> cachedEnemies = new List<Enemy>(100);
private Vector3 cachedPosition;
void Update_Good() {
GetEnemiesNonAlloc(cachedEnemies); // 重用List
foreach (var enemy in cachedEnemies) {
// ...
}
}
// 避免闭包捕获产生的分配
private Action cachedAction;
void Start() {
cachedAction = OnComplete; // 缓存委托
}
void RegisterCallback() {
EventManager.Register(cachedAction); // 不产生新分配
// EventManager.Register(() => OnComplete()); // 每次都分配
}
void OnComplete() { }
}
2. Assembly Definition - 模块化架构
// MyGame.Core.asmdef
{
"name": "MyGame.Core",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": []
}
// MyGame.Gameplay.asmdef
{
"name": "MyGame.Gameplay",
"references": ["MyGame.Core"],
"includePlatforms": [],
"allowUnsafeCode": false
}
// 好处:
// 1. 加速编译(只重新编译修改的模块)
// 2. 强制依赖管理(循环依赖会报错)
// 3. 代码隔离(减少耦合)
3. IL2CPP 与代码生成
// link.xml - 防止代码被剥离
<linker>
<assembly fullname="Assembly-CSharp">
<type fullname="MyNamespace.MyClass" preserve="all"/>
</assembly>
</linker>
// 使用[Preserve]特性
using UnityEngine.Scripting;
[Preserve]
public class ImportantClass {
[Preserve]
public void ImportantMethod() { }
}
// AOT编译限制 - 不能使用的特性
public class AOTLimitations {
// IL2CPP不支持动态代码生成
void NotSupported() {
// Reflection.Emit
// System.Linq.Expressions (部分)
// 动态类型创建
}
// 泛型需要提前实例化
void GenericAOT() {
// 需要在某处显式使用这些泛型组合
var _ = new List<MyCustomType>();
var __ = new Dictionary<int, MyCustomType>();
}
}
4. 自定义渲染管线 (SRP)
using UnityEngine.Rendering;
public class CustomRenderPipeline : RenderPipeline {
protected override void Render(ScriptableRenderContext context, Camera[] cameras) {
foreach (Camera camera in cameras) {
RenderCamera(context, camera);
}
}
void RenderCamera(ScriptableRenderContext context, Camera camera) {
// 设置相机参数
context.SetupCameraProperties(camera);
// 清除
CommandBuffer cmd = CommandBufferPool.Get("Clear");
cmd.ClearRenderTarget(true, true, Color.black);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
// 剔除
camera.TryGetCullingParameters(out var cullingParameters);
var cullingResults = context.Cull(ref cullingParameters);
// 渲染不透明物体
var sortingSettings = new SortingSettings(camera) {
criteria = SortingCriteria.CommonOpaque
};
var drawingSettings = new DrawingSettings(
new ShaderTagId("SRPDefaultUnlit"), sortingSettings
);
var filteringSettings = new FilteringSettings(RenderQueueRange.opaque);
context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings);
// 渲染天空盒
context.DrawSkybox(camera);
// 渲染透明物体
sortingSettings.criteria = SortingCriteria.CommonTransparent;
drawingSettings.sortingSettings = sortingSettings;
filteringSettings.renderQueueRange = RenderQueueRange.transparent;
context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings);
// 提交
context.Submit();
}
}
// CommandBuffer深度使用
public class CustomRenderFeature {
private CommandBuffer commandBuffer;
public void Execute(ScriptableRenderContext context, Camera camera) {
commandBuffer = CommandBufferPool.Get("Custom Pass");
// 创建临时RT
int tempRT = Shader.PropertyToID("_TempRT");
commandBuffer.GetTemporaryRT(tempRT, camera.pixelWidth, camera.pixelHeight, 0, FilterMode.Bilinear);
// Blit操作
commandBuffer.Blit(BuiltinRenderTextureType.CameraTarget, tempRT);
// 自定义渲染
commandBuffer.DrawMesh(mesh, Matrix4x4.identity, material);
// 清理
commandBuffer.ReleaseTemporaryRT(tempRT);
context.ExecuteCommandBuffer(commandBuffer);
CommandBufferPool.Release(commandBuffer);
}
}
5. 网络同步 - 预测回滚与状态同步
// 客户端预测 + 服务器和解
public class NetworkController {
private Queue<InputFrame> inputHistory = new Queue<InputFrame>();
private Queue<StateFrame> stateHistory = new Queue<StateFrame>();
private const int MAX_HISTORY = 60; // 1秒历史(60fps)
public struct InputFrame {
public int frameNumber;
public Vector3 input;
public float timestamp;
}
public struct StateFrame {
public int frameNumber;
public Vector3 position;
public Vector3 velocity;
}
void Update() {
// 1. 客户端预测
InputFrame input = new InputFrame {
frameNumber = Time.frameCount,
input = GetPlayerInput(),
timestamp = Time.time
};
// 保存输入历史
inputHistory.Enqueue(input);
if (inputHistory.Count > MAX_HISTORY) {
inputHistory.Dequeue();
}
// 本地模拟
SimulateMovement(input.input);
// 保存状态
stateHistory.Enqueue(new StateFrame {
frameNumber = Time.frameCount,
position = transform.position,
velocity = GetComponent<Rigidbody>().velocity
});
if (stateHistory.Count > MAX_HISTORY) {
stateHistory.Dequeue();
}
// 发送给服务器
SendInputToServer(input);
}
// 2. 服务器状态回调 - 和解
void OnServerStateReceived(StateFrame serverState) {
// 找到对应的客户端历史状态
StateFrame clientState = FindState(serverState.frameNumber);
// 检查是否需要回滚
float positionError = Vector3.Distance(serverState.position, clientState.position);
if (positionError > 0.1f) { // 误差阈值
Debug.Log($"预测错误,回滚并重新模拟。误差: {positionError}");
// 回滚到服务器状态
transform.position = serverState.position;
GetComponent<Rigidbody>().velocity = serverState.velocity;
// 重新应用之后的所有输入
foreach (var input in inputHistory) {
if (input.frameNumber > serverState.frameNumber) {
SimulateMovement(input.input);
}
}
}
}
StateFrame FindState(int frameNumber) {
foreach (var state in stateHistory) {
if (state.frameNumber == frameNumber) return state;
}
return default;
}
void SimulateMovement(Vector3 input) {
// 确定性物理模拟
GetComponent<Rigidbody>().AddForce(input * 10f);
}
Vector3 GetPlayerInput() {
return new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
}
void SendInputToServer(InputFrame input) {
// 网络发送逻辑
}
}
// 插值和外推
public class NetworkTransform {
private struct Snapshot {
public float timestamp;
public Vector3 position;
public Quaternion rotation;
}
private Queue<Snapshot> snapshots = new Queue<Snapshot>();
private const float INTERPOLATION_DELAY = 0.1f; // 100ms延迟
public void OnSnapshotReceived(Vector3 position, Quaternion rotation) {
snapshots.Enqueue(new Snapshot {
timestamp = Time.time,
position = position,
rotation = rotation
});
// 保留最近500ms的快照
while (snapshots.Count > 0 && Time.time - snapshots.Peek().timestamp > 0.5f) {
snapshots.Dequeue();
}
}
void Update() {
if (snapshots.Count < 2) return;
float targetTime = Time.time - INTERPOLATION_DELAY;
// 找到插值的两个快照
Snapshot from = default, to = default;
bool foundPair = false;
var snapshotArray = snapshots.ToArray();
for (int i = 0; i < snapshotArray.Length - 1; i++) {
if (snapshotArray[i].timestamp <= targetTime && snapshotArray[i + 1].timestamp >= targetTime) {
from = snapshotArray[i];
to = snapshotArray[i + 1];
foundPair = true;
break;
}
}
if (foundPair) {
float t = (targetTime - from.timestamp) / (to.timestamp - from.timestamp);
transform.position = Vector3.Lerp(from.position, to.position, t);
transform.rotation = Quaternion.Slerp(from.rotation, to.rotation, t);
}
}
}
6. 热更新方案
// HybridCLR (原huatuo) 或 ILRuntime
// 使用反射热加载DLL
public class HotfixManager {
private Assembly hotfixAssembly;
public async Task LoadHotfixAsync() {
// 从服务器下载DLL
byte[] dllBytes = await DownloadDLL("https://example.com/hotfix.dll");
byte[] pdbBytes = await DownloadDLL("https://example.com/hotfix.pdb");
// 加载程序集
hotfixAssembly = Assembly.Load(dllBytes, pdbBytes);
// 调用热更新代码
Type type = hotfixAssembly.GetType("HotfixNamespace.HotfixClass");
MethodInfo method = type.GetMethod("Initialize");
method?.Invoke(null, null);
}
async Task<byte[]> DownloadDLL(string url) {
using (UnityWebRequest request = UnityWebRequest.Get(url)) {
await request.SendWebRequest();
return request.downloadHandler.data;
}
}
}
// Lua热更新 (xLua/toLua)
/*
-- Lua代码
function OnButtonClick()
print("从Lua调用")
CS.UnityEngine.GameObject.Find("Player"):SetActive(false)
end
*/
// C# 调用Lua
using XLua;
[LuaCallCSharp]
public class LuaManager : MonoBehaviour {
private LuaEnv luaEnv;
void Start() {
luaEnv = new LuaEnv();
luaEnv.DoString("require 'main'");
// 调用Lua函数
LuaFunction func = luaEnv.Global.Get<LuaFunction>("OnButtonClick");
func.Call();
}
void OnDestroy() {
luaEnv.Dispose();
}
}
7. 确定性物理与定点数
// 使用定点数避免浮点误差(网络同步/帧同步必备)
public struct FixedPoint {
private long rawValue;
private const int FRACTIONAL_BITS = 16;
private const long ONE = 1L << FRACTIONAL_BITS;
public static FixedPoint FromRaw(long raw) {
return new FixedPoint { rawValue = raw };
}
public static FixedPoint FromInt(int value) {
return new FixedPoint { rawValue = (long)value << FRACTIONAL_BITS };
}
public static FixedPoint FromFloat(float value) {
return new FixedPoint { rawValue = (long)(value * ONE) };
}
public float ToFloat() {
return (float)rawValue / ONE;
}
public static FixedPoint operator +(FixedPoint a, FixedPoint b) {
return FromRaw(a.rawValue + b.rawValue);
}
public static FixedPoint operator *(FixedPoint a, FixedPoint b) {
return FromRaw((a.rawValue * b.rawValue) >> FRACTIONAL_BITS);
}
// 确定性sin/cos查找表
private static readonly FixedPoint[] sinTable = new FixedPoint[360];
static FixedPoint() {
for (int i = 0; i < 360; i++) {
sinTable[i] = FromFloat(Mathf.Sin(i * Mathf.Deg2Rad));
}
}
public static FixedPoint Sin(FixedPoint degrees) {
int index = ((int)degrees.ToFloat()) % 360;
if (index < 0) index += 360;
return sinTable[index];
}
}
// 确定性物理模拟
public class DeterministicPhysics {
public struct RigidBody {
public FixedPoint x, y, z;
public FixedPoint vx, vy, vz;
public FixedPoint mass;
}
public static void Step(ref RigidBody body, FixedPoint deltaTime) {
// 确定性更新(所有客户端结果完全一致)
body.x = body.x + body.vx * deltaTime;
body.y = body.y + body.vy * deltaTime;
body.z = body.z + body.vz * deltaTime;
// 应用重力
FixedPoint gravity = FixedPoint.FromFloat(-9.81f);
body.vy = body.vy + gravity * deltaTime;
}
}
8. Profiler深度分析与优化
using Unity.Profiling;
public class CustomProfiler {
// 自定义Profiler标记
private static readonly ProfilerMarker s_PrepareMarker = new ProfilerMarker("MyGame.Prepare");
private static readonly ProfilerMarker s_SimulateMarker = new ProfilerMarker("MyGame.Simulate");
void Update() {
s_PrepareMarker.Begin();
PrepareData();
s_PrepareMarker.End();
using (s_SimulateMarker.Auto()) { // 自动Begin/End
SimulatePhysics();
}
}
// 深度采样
private static readonly ProfilerRecorder systemMemoryRecorder;
private static readonly ProfilerRecorder gcMemoryRecorder;
private static readonly ProfilerRecorder mainThreadTimeRecorder;
static CustomProfiler() {
systemMemoryRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Memory, "System Used Memory");
gcMemoryRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Memory, "GC Reserved Memory");
mainThreadTimeRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Internal, "Main Thread", 15);
}
void OnGUI() {
GUI.Label(new Rect(10, 10, 300, 20), $"System Memory: {systemMemoryRecorder.LastValue / (1024 * 1024)} MB");
GUI.Label(new Rect(10, 30, 300, 20), $"GC Memory: {gcMemoryRecorder.LastValue / (1024 * 1024)} MB");
if (mainThreadTimeRecorder.Valid) {
var samplesCount = mainThreadTimeRecorder.Capacity;
var samples = new List<ProfilerRecorderSample>(samplesCount);
mainThreadTimeRecorder.CopyTo(samples);
double avgTime = 0;
foreach (var sample in samples) {
avgTime += sample.Value;
}
avgTime /= samplesCount;
GUI.Label(new Rect(10, 50, 300, 20), $"Main Thread: {avgTime / 1000000.0:F2} ms");
}
}
void PrepareData() { }
void SimulatePhysics() { }
}
9. 源生成器 (Source Generators) - C# 9.0+
// 编译时代码生成,避免反射开销
[Generator]
public class AutoPropertyGenerator : ISourceGenerator {
public void Initialize(GeneratorInitializationContext context) { }
public void Execute(GeneratorExecutionContext context) {
// 生成代码
string source = @"
namespace Generated {
public partial class AutoGenerated {
public void GeneratedMethod() {
UnityEngine.Debug.Log(""This method was generated!"");
}
}
}";
context.AddSource("AutoGenerated.g.cs", source);
}
}
// 使用生成的代码
public partial class AutoGenerated {
// GeneratedMethod() 会自动添加
}
10. 高级数学 - 四元数与矩阵
public class AdvancedMath {
// 四元数插值 - Slerp vs Lerp
public static Quaternion CustomSlerp(Quaternion a, Quaternion b, float t) {
// 计算夹角
float dot = Quaternion.Dot(a, b);
// 如果点积为负,取最短路径
if (dot < 0) {
b = new Quaternion(-b.x, -b.y, -b.z, -b.w);
dot = -dot;
}
// 如果非常接近,使用线性插值
if (dot > 0.9995f) {
return Quaternion.Lerp(a, b, t);
}
// 球面插值
float theta = Mathf.Acos(dot);
float sinTheta = Mathf.Sin(theta);
float wa = Mathf.Sin((1 - t) * theta) / sinTheta;
float wb = Mathf.Sin(t * theta) / sinTheta;
return new Quaternion(
wa * a.x + wb * b.x,
wa * a.y + wb * b.y,
wa * a.z + wb * b.z,
wa * a.w + wb * b.w
);
}
// 矩阵分解 - TRS
public static void DecomposeMatrix(Matrix4x4 matrix, out Vector3 position, out Quaternion rotation, out Vector3 scale) {
// 提取位置
position = matrix.GetColumn(3);
// 提取缩放
Vector3 scaleX = new Vector3(matrix.m00, matrix.m10, matrix.m20);
Vector3 scaleY = new Vector3(matrix.m01, matrix.m11, matrix.m21);
Vector3 scaleZ = new Vector3(matrix.m02, matrix.m12, matrix.m22);
scale = new Vector3(scaleX.magnitude, scaleY.magnitude, scaleZ.magnitude);
// 移除缩放,提取旋转
if (scale.x != 0) scaleX /= scale.x;
if (scale.y != 0) scaleY /= scale.y;
if (scale.z != 0) scaleZ /= scale.z;
Matrix4x4 rotationMatrix = Matrix4x4.identity;
rotationMatrix.SetColumn(0, scaleX);
rotationMatrix.SetColumn(1, scaleY);
rotationMatrix.SetColumn(2, scaleZ);
rotation = rotationMatrix.rotation;
}
// 贝塞尔曲线
public static Vector3 CubicBezier(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) {
float u = 1 - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;
Vector3 p = uuu * p0;
p += 3 * uu * t * p1;
p += 3 * u * tt * p2;
p += ttt * p3;
return p;
}
}
专家级/架构级知识树
🏆 专家级知识
│
├─ 🧠 内存与性能
│ ├─ GC优化与零分配
│ ├─ Native容器与unsafe代码
│ ├─ Stack vs Heap深度理解
│ ├─ Profiler深度分析
│ └─ 内存对齐与缓存友好
│
├─ 🏗️ 架构与工程
│ ├─ Assembly Definition模块化
│ ├─ 依赖注入(DI)框架
│ ├─ 事件驱动架构
│ ├─ ECS架构模式
│ └─ 插件化系统
│
├─ 🌐 网络编程
│ ├─ 客户端预测
│ ├─ 服务器和解
│ ├─ 帧同步vs状态同步
│ ├─ 确定性物理
│ └─ 网络插值与外推
│
├─ 🔥 热更新
│ ├─ HybridCLR
│ ├─ ILRuntime
│ ├─ Lua集成(xLua)
│ ├─ AssetBundle管理
│ └─ 资源热更新流程
│
├─ 🎨 图形编程
│ ├─ 自定义渲染管线(SRP)
│ ├─ CommandBuffer深度使用
│ ├─ Compute Shader高级
│ ├─ GPU Instancing
│ └─ 自定义后处理
│
├─ ⚙️ 编译与构建
│ ├─ IL2CPP深度理解
│ ├─ 代码裁剪与优化
│ ├─ Source Generators
│ ├─ 自定义构建管线
│ └─ 多平台适配
│
├─ 🔬 底层技术
│ ├─ Native Plugin开发
│ ├─ 平台特定代码
│ ├─ 定点数运算
│ ├─ SIMD优化
│ └─ 协程底层实现
│
└─ 🧮 高级算法
├─ 空间分割(Octree/BSP)
├─ A*寻路优化
├─ 行为树/状态机
├─ 程序化生成
└─ 物理约束求解器

被折叠的 条评论
为什么被折叠?



