【Unity知识扫盲】专家级/架构级概念

专家级/架构级知识体系架构介绍

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*寻路优化
├─ 行为树/状态机
├─ 程序化生成
└─ 物理约束求解器

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值