Unity程序员如何做移动端性能优化:原理与商业项目实战

引言:移动端性能优化的特殊挑战

移动设备与PC平台有着本质的性能差异:有限的CPU/GPU性能、严格的功耗限制、不稳定的网络环境、多样化的硬件配置和操作系统版本。在移动端,性能优化不仅影响游戏体验,更直接影响电池寿命、设备发热和用户留存率。

商业项目关键指标

  • 帧率稳定性(60FPS/30FPS目标)
  • 内存使用(iOS 1.8GB警告线,Android因设备而异)
  • 耗电量(每小时的电池消耗百分比)
  • 安装包大小(App Store 200MB蜂窝下载限制)
  • 发热控制(设备表面温度不超过45℃)

第一部分:移动端性能分析工具链

1.1 Unity Profiler深度使用

关键Profiler模块

// 自定义性能监控系统
public class MobilePerformanceMonitor : MonoBehaviour
{
    private class FrameMetrics
    {
        public float FrameTime;
        public float CPUTime;
        public float GPUTime;
        public int DrawCalls;
        public int SetPassCalls;
        public int Triangles;
        public int Vertices;
        public long MemoryAllocated;
        public long MemoryReserved;
        public int GCCollectCount;
    }
    
    private Queue<FrameMetrics> m_frameHistory = new Queue<FrameMetrics>();
    private const int HISTORY_SIZE = 300; // 5秒数据(假设60FPS)
    
    private float m_lastGCCollectTime = 0;
    private int m_gcCollectCount = 0;
    
    void Update()
    {
        CollectFrameMetrics();
        AnalyzePerformance();
        CheckCriticalIssues();
    }
    
    void CollectFrameMetrics()
    {
        var metrics = new FrameMetrics
        {
            FrameTime = Time.unscaledDeltaTime * 1000f, // 毫秒
            MemoryAllocated = Profiler.GetTotalAllocatedMemoryLong() / 1024 / 1024, // MB
            MemoryReserved = Profiler.GetTotalReservedMemoryLong() / 1024 / 1024,
            DrawCalls = GetDrawCallCount(),
            Triangles = GetTriangleCount(),
            Vertices = GetVertexCount()
        };
        
        m_frameHistory.Enqueue(metrics);
        if (m_frameHistory.Count > HISTORY_SIZE)
            m_frameHistory.Dequeue();
    }
    
    void AnalyzePerformance()
    {
        if (m_frameHistory.Count < 10) return;
        
        // 计算平均帧时间
        float avgFrameTime = m_frameHistory.Average(m => m.FrameTime);
        float fps = 1000f / avgFrameTime;
        
        // 检测掉帧(帧时间超过阈值)
        int droppedFrames = m_frameHistory.Count(m => m.FrameTime > 33.3f); // 低于30FPS
        
        // 检测内存泄漏趋势
        var oldest = m_frameHistory.First();
        var newest = m_frameHistory.Last();
        float memoryGrowth = newest.MemoryAllocated - oldest.MemoryAllocated;
        
        // 生成报告
        if (Time.frameCount % 60 == 0) // 每60帧报告一次
        {
            Debug.Log($"性能报告 - FPS: {fps:F1}, 掉帧: {droppedFrames}, " +
                     $"内存增长: {memoryGrowth:F1}MB");
        }
    }
    
    void CheckCriticalIssues()
    {
        var current = m_frameHistory.LastOrDefault();
        if (current == null) return;
        
        // 关键问题检测
        if (current.FrameTime > 50f) // 低于20FPS
        {
            Debug.LogWarning($"严重掉帧: {current.FrameTime:F1}ms");
            LogDetailedAnalysis();
        }
        
        if (current.MemoryAllocated > GetMemoryWarningThreshold())
        {
            Debug.LogError($"内存过高: {current.MemoryAllocated}MB");
            TriggerMemoryCleanup();
        }
    }
    
    // 获取DrawCall等渲染数据(需要自定义实现)
    int GetDrawCallCount()
    {
        #if DEVELOPMENT_BUILD || UNITY_EDITOR
        return UnityEditor.UnityStats.drawCalls;
        #else
        // 发布版本需要其他方式获取
        return -1;
        #endif
    }
    
    // 自定义性能采样标记
    public class ScopedProfilerSample : IDisposable
    {
        private string m_name;
        private System.Diagnostics.Stopwatch m_stopwatch;
        
        public ScopedProfilerSample(string name)
        {
            m_name = name;
            m_stopwatch = System.Diagnostics.Stopwatch.StartNew();
            Profiler.BeginSample(name);
        }
        
        public void Dispose()
        {
            m_stopwatch.Stop();
            Profiler.EndSample();
            
            // 记录耗时(仅开发版本)
            #if DEVELOPMENT_BUILD
            if (m_stopwatch.ElapsedMilliseconds > 5) // 超过5ms警告
            {
                Debug.LogWarning($"性能警告 - {m_name}: {m_stopwatch.ElapsedMilliseconds}ms");
            }
            #endif
        }
    }
    
    // 使用示例
    void ProcessComplexLogic()
    {
        using (new ScopedProfilerSample("ProcessComplexLogic"))
        {
            // 复杂的逻辑处理
            // ...
        }
    }
}

1.2 平台专属分析工具

iOS专用工具链

// iOS性能监控集成
public class iOSPerformanceMonitor
{
    #if UNITY_IOS && !UNITY_EDITOR
    [System.Runtime.InteropServices.DllImport("__Internal")]
    private static extern void StartPerfMonitoring();
    
    [System.Runtime.InteropServices.DllImport("__Internal")]
    private static extern double GetThermalState(); // 0-1,1表示过热
    
    [System.Runtime.InteropServices.DllImport("__Internal")]
    private static extern double GetBatteryLevel();
    
    [System.Runtime.InteropServices.DllImport("__Internal")]
    private static extern void LogMetalPerformance(string jsonData);
    #endif
    
    public void Initialize()
    {
        #if UNITY_IOS && !UNITY_EDITOR
        StartPerfMonitoring();
        #endif
    }
    
    public float GetThermalStatus()
    {
        #if UNITY_IOS && !UNITY_EDITOR
        return (float)GetThermalState();
        #else
        return 0f;
        #endif
    }
    
    // 热限制自适应
    public void ApplyThermalThrottling()
    {
        float thermalState = GetThermalStatus();
        
        if (thermalState > 0.7f) // 设备过热
        {
            // 降低渲染质量
            QualitySettings.SetQualityLevel(0, true); // 最低画质
            
            // 降低帧率
            Application.targetFrameRate = 30;
            
            // 减少粒子效果
            ParticleSystem[] allParticles = GameObject.FindObjectsOfType<ParticleSystem>();
            foreach (var ps in allParticles)
            {
                var emission = ps.emission;
                emission.rateOverTimeMultiplier *= 0.5f;
            }
            
            Debug.Log("热限制触发:已降低渲染质量");
        }
        else if (thermalState > 0.3f) // 设备温热
        {
            // 适度降低质量
            Application.targetFrameRate = 45;
        }
    }
}

Android专用工具链

// Android性能监控
public class AndroidPerformanceMonitor
{
    #if UNITY_ANDROID && !UNITY_EDITOR
    private static AndroidJavaClass m_unityPlayer;
    private static AndroidJavaObject m_currentActivity;
    private static AndroidJavaObject m_powerManager;
    
    static AndroidPerformanceMonitor()
    {
        m_unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        m_currentActivity = m_unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
        
        AndroidJavaClass powerManagerClass = new AndroidJavaClass("android.os.PowerManager");
        m_powerManager = m_currentActivity.Call<AndroidJavaObject>("getSystemService", "power");
    }
    #endif
    
    // 检查是否处于省电模式
    public static bool IsPowerSaveMode()
    {
        #if UNITY_ANDROID && !UNITY_EDITOR
        return m_powerManager.Call<bool>("isPowerSaveMode");
        #else
        return false;
        #endif
    }
    
    // 获取可用内存
    public static long GetAvailableMemory()
    {
        #if UNITY_ANDROID && !UNITY_EDITOR
        AndroidJavaClass activityManagerClass = new AndroidJavaClass("android.app.ActivityManager");
        AndroidJavaObject activityManager = m_currentActivity.Call<AndroidJavaObject>("getSystemService", "activity");
        
        AndroidJavaObject memoryInfo = new AndroidJavaObject("android.app.ActivityManager$MemoryInfo");
        activityManager.Call("getMemoryInfo", memoryInfo);
        
        long availMem = memoryInfo.Get<long>("availMem");
        return availMem / 1024 / 1024; // MB
        #else
        return 0;
        #endif
    }
    
    // 设置CPU核心使用(大核/小核调度)
    public static void SetCPUAffinity(bool useBigCoresOnly)
    {
        #if UNITY_ANDROID && !UNITY_EDITOR
        try
        {
            AndroidJavaClass processClass = new AndroidJavaClass("android.os.Process");
            int pid = processClass.CallStatic<int>("myPid");
            
            // 获取CPU核心信息
            string cpuInfo = ReadFile("/proc/cpuinfo");
            // 解析核心信息并设置亲和性...
            
            Debug.Log($"设置CPU亲和性,PID: {pid}");
        }
        catch (System.Exception e)
        {
            Debug.LogWarning($"设置CPU亲和性失败: {e.Message}");
        }
        #endif
    }
    
    #if UNITY_ANDROID && !UNITY_EDITOR
    private static string ReadFile(string path)
    {
        using (AndroidJavaObject file = new AndroidJavaObject("java.io.File", path))
        using (AndroidJavaObject fis = new AndroidJavaObject("java.io.FileInputStream", file))
        using (AndroidJavaObject bis = new AndroidJavaObject("java.io.BufferedInputStream", fis))
        {
            byte[] buffer = new byte[1024];
            System.Text.StringBuilder content = new System.Text.StringBuilder();
            
            while (bis.Call<int>("read", buffer) != -1)
            {
                content.Append(System.Text.Encoding.UTF8.GetString(buffer));
            }
            
            return content.ToString();
        }
    }
    #endif
}

第二部分:渲染性能优化

2.1 DrawCall优化策略

// 动态DrawCall合并系统
public class DynamicBatchingOptimizer : MonoBehaviour
{
    [System.Serializable]
    public class BatchableMaterial
    {
        public Material Material;
        public List<MeshRenderer> Renderers = new List<MeshRenderer>();
        public bool IsStatic = true;
    }
    
    private Dictionary<Material, BatchableMaterial> m_materialGroups = new Dictionary<Material, BatchableMaterial>();
    private List<GameObject> m_dynamicBatchedObjects = new List<GameObject>();
    
    void Start()
    {
        // 自动检测并合并静态物体
        StartCoroutine(AutoBatchStaticObjects());
        
        // 监控DrawCall
        StartCoroutine(MonitorDrawCalls());
    }
    
    IEnumerator AutoBatchStaticObjects()
    {
        // 分批处理避免卡顿
        MeshRenderer[] allRenderers = FindObjectsOfType<MeshRenderer>();
        int batchSize = 50;
        
        for (int i = 0; i < allRenderers.Length; i += batchSize)
        {
            int end = Mathf.Min(i + batchSize, allRenderers.Length);
            
            for (int j = i; j < end; j++)
            {
                MeshRenderer renderer = allRenderers[j];
                
                // 只处理静态物体
                if (renderer.gameObject.isStatic)
                {
                    AddToBatchGroup(renderer);
                }
            }
            
            yield return null; // 下一帧继续
        }
        
        // 执行合并
        ExecuteBatching();
    }
    
    void AddToBatchGroup(MeshRenderer renderer)
    {
        Material mat = renderer.sharedMaterial;
        if (mat == null) return;
        
        if (!m_materialGroups.TryGetValue(mat, out var group))
        {
            group = new BatchableMaterial { Material = mat };
            m_materialGroups[mat] = group;
        }
        
        group.Renderers.Add(renderer);
    }
    
    void ExecuteBatching()
    {
        foreach (var kvp in m_materialGroups)
        {
            var group = kvp.Value;
            if (group.Renderers.Count < 2) continue; // 需要至少2个渲染器
            
            // 合并网格
            CombineMeshes(group);
        }
    }
    
    void CombineMeshes(BatchableMaterial group)
    {
        List<MeshFilter> meshFilters = new List<MeshFilter>();
        List<CombineInstance> combineInstances = new List<CombineInstance>();
        
        foreach (var renderer in group.Renderers)
        {
            MeshFilter filter = renderer.GetComponent<MeshFilter>();
            if (filter != null && filter.sharedMesh != null)
            {
                meshFilters.Add(filter);
                
                CombineInstance ci = new CombineInstance
                {
                    mesh = filter.sharedMesh,
                    transform = filter.transform.localToWorldMatrix
                };
                combineInstances.Add(ci);
            }
        }
        
        if (combineInstances.Count == 0) return;
        
        // 创建合并后的游戏对象
        GameObject combinedObject = new GameObject("CombinedMesh_" + group.Material.name);
        MeshFilter combinedFilter = combinedObject.AddComponent<MeshFilter>();
        MeshRenderer combinedRenderer = combinedObject.AddComponent<MeshRenderer>();
        
        // 合并网格
        Mesh combinedMesh = new Mesh();
        combinedMesh.CombineMeshes(combineInstances.ToArray(), true, true);
        combinedFilter.mesh = combinedMesh;
        combinedRenderer.material = group.Material;
        
        // 禁用原始渲染器
        foreach (var renderer in group.Renderers)
        {
            renderer.enabled = false;
        }
        
        m_dynamicBatchedObjects.Add(combinedObject);
        
        Debug.Log($"合并了 {combineInstances.Count} 个网格,材质: {group.Material.name}");
    }
    
    IEnumerator MonitorDrawCalls()
    {
        while (true)
        {
            yield return new WaitForSeconds(1f);
            
            #if UNITY_EDITOR
            int drawCalls = UnityEditor.UnityStats.drawCalls;
            int setPassCalls = UnityEditor.UnityStats.setPassCalls;
            
            Debug.Log($"渲染统计 - DrawCalls: {drawCalls}, SetPassCalls: {setPassCalls}");
            
            // 预警机制
            if (drawCalls > GetDrawCallThreshold())
            {
                Debug.LogWarning($"DrawCall过高: {drawCalls}");
                OnDrawCallExceeded(drawCalls);
            }
            #endif
        }
    }
    
    int GetDrawCallThreshold()
    {
        // 根据平台设定阈值
        #if UNITY_IOS
        return 40; // iOS建议低于40
        #elif UNITY_ANDROID
        return 50; // Android可稍高
        #else
        return 100; // 其他平台
        #endif
    }
    
    void OnDrawCallExceeded(int currentDrawCalls)
    {
        // 自动降低渲染质量
        if (!QualitySettings.lodBias.Equals(0.5f))
        {
            QualitySettings.lodBias = 0.5f; // 降低LOD距离
            Debug.Log("自动降低LOD偏置以减少DrawCall");
        }
    }
}

// GPU Instancing优化(大量相同物体)
public class GPUInstancingOptimizer : MonoBehaviour
{
    [System.Serializable]
    public class InstancingData
    {
        public Mesh Mesh;
        public Material Material;
        public int InstanceCount = 1000;
        public Vector3 AreaSize = new Vector3(50, 0, 50);
        
        [NonSerialized]
        public Matrix4x4[] Matrices;
        [NonSerialized]
        public MaterialPropertyBlock PropertyBlock;
    }
    
    public List<InstancingData> InstancingGroups = new List<InstancingData>();
    
    void Start()
    {
        InitializeInstancing();
    }
    
    void InitializeInstancing()
    {
        foreach (var group in InstancingGroups)
        {
            group.Matrices = new Matrix4x4[group.InstanceCount];
            group.PropertyBlock = new MaterialPropertyBlock();
            
            // 设置随机颜色
            Vector4[] colors = new Vector4[group.InstanceCount];
            for (int i = 0; i < group.InstanceCount; i++)
            {
                colors[i] = new Color(Random.value, Random.value, Random.value, 1f);
            }
            group.PropertyBlock.SetVectorArray("_Color", colors);
            
            // 初始化位置
            UpdateInstancingPositions(group);
        }
    }
    
    void UpdateInstancingPositions(InstancingData group)
    {
        for (int i = 0; i < group.InstanceCount; i++)
        {
            Vector3 position = new Vector3(
                Random.Range(-group.AreaSize.x, group.AreaSize.x),
                Random.Range(-group.AreaSize.y, group.AreaSize.y),
                Random.Range(-group.AreaSize.z, group.AreaSize.z)
            );
            
            Quaternion rotation = Quaternion.Euler(
                Random.Range(0, 360),
                Random.Range(0, 360),
                Random.Range(0, 360)
            );
            
            Vector3 scale = Vector3.one * Random.Range(0.5f, 2f);
            
            group.Matrices[i] = Matrix4x4.TRS(position, rotation, scale);
        }
    }
    
    void Update()
    {
        RenderInstances();
    }
    
    void RenderInstances()
    {
        foreach (var group in InstancingGroups)
        {
            if (group.Mesh != null && group.Material != null)
            {
                // 使用GPU Instancing渲染大量实例
                // 注意:移动端一次最多渲染1023个实例
                int batchSize = 1023;
                int instanceCount = group.InstanceCount;
                
                for (int i = 0; i < instanceCount; i += batchSize)
                {
                    int count = Mathf.Min(batchSize, instanceCount - i);
                    Graphics.DrawMeshInstanced(
                        group.Mesh,
                        0,
                        group.Material,
                        new ArraySegment<Matrix4x4>(group.Matrices, i, count).ToArray(),
                        count,
                        group.PropertyBlock
                    );
                }
            }
        }
    }
    
    // 动态更新实例位置(优化版本)
    public void UpdateInstancePosition(int groupIndex, int instanceIndex, Vector3 newPosition)
    {
        if (groupIndex >= 0 && groupIndex < InstancingGroups.Count)
        {
            var group = InstancingGroups[groupIndex];
            if (instanceIndex >= 0 && instanceIndex < group.InstanceCount)
            {
                // 只更新变换矩阵的位置部分(避免重新分配)
                var matrix = group.Matrices[instanceIndex];
                matrix.m03 = newPosition.x;
                matrix.m13 = newPosition.y;
                matrix.m23 = newPosition.z;
                group.Matrices[instanceIndex] = matrix;
            }
        }
    }
}

2.2 移动端Shader优化

// 移动端优化Shader示例(使用Shader Graph或代码)
public class MobileShaderOptimizer
{
    // 通用移动端Shader优化规则
    public class OptimizationRules
    {
        public static string ApplyMobileOptimizations(string shaderCode)
        {
            // 1. 移除不必要的光照计算
            shaderCode = shaderCode.Replace("#pragma multi_compile_fwdbase", "");
            shaderCode = shaderCode.Replace("#pragma multi_compile_fwdadd", "");
            
            // 2. 简化变体
            shaderCode = shaderCode.Replace(
                "multi_compile_fog", 
                "shader_feature _FOG_ON"
            );
            
            // 3. 减少纹理采样
            // 检测并合并多个纹理采样
            
            // 4. 使用半精度浮点数
            shaderCode = shaderCode.Replace(
                "float ", 
                "half "
            ).Replace(
                "float2 ",
                "half2 "
            ).Replace(
                "float3 ",
                "half3 "
            ).Replace(
                "float4 ",
                "half4 "
            );
            
            return shaderCode;
        }
    }
    
    // 运行时Shader LOD系统
    public class ShaderLODSystem : MonoBehaviour
    {
        [System.Serializable]
        public class ShaderLODLevel
        {
            public string ShaderName;
            public int LOD = 100;
            public Shader ReplacementShader;
        }
        
        public List<ShaderLODLevel> LODLevels = new List<ShaderLODLevel>();
        public float UpdateInterval = 2f;
        
        private Dictionary<string, Shader> m_originalShaders = new Dictionary<string, Shader>();
        private Dictionary<Renderer, Material[]> m_originalMaterials = new Dictionary<Renderer, Material[]>();
        
        void Start()
        {
            StartCoroutine(MonitorAndAdjustShaderLOD());
        }
        
        IEnumerator MonitorAndAdjustShaderLOD()
        {
            while (true)
            {
                yield return new WaitForSeconds(UpdateInterval);
                
                float fps = 1f / Time.unscaledDeltaTime;
                float thermalState = GetThermalState();
                
                // 根据性能指标决定Shader LOD
                int targetLOD = CalculateTargetLOD(fps, thermalState);
                
                ApplyShaderLOD(targetLOD);
            }
        }
        
        int CalculateTargetLOD(float fps, float thermalState)
        {
            if (fps < 25 || thermalState > 0.7f)
                return 100; // 最低质量
            else if (fps < 45 || thermalState > 0.4f)
                return 200; // 中等质量
            else
                return 300; // 高质量
        }
        
        void ApplyShaderLOD(int targetLOD)
        {
            foreach (var lodLevel in LODLevels)
            {
                if (targetLOD <= lodLevel.LOD && lodLevel.ReplacementShader != null)
                {
                    ReplaceShader(lodLevel.ShaderName, lodLevel.ReplacementShader);
                }
                else
                {
                    RestoreShader(lodLevel.ShaderName);
                }
            }
        }
        
        void ReplaceShader(string shaderName, Shader replacementShader)
        {
            Renderer[] allRenderers = FindObjectsOfType<Renderer>();
            
            foreach (var renderer in allRenderers)
            {
                if (!m_originalMaterials.ContainsKey(renderer))
                {
                    m_originalMaterials[renderer] = renderer.sharedMaterials;
                }
                
                Material[] newMaterials = new Material[renderer.sharedMaterials.Length];
                for (int i = 0; i < renderer.sharedMaterials.Length; i++)
                {
                    Material mat = renderer.sharedMaterials[i];
                    if (mat != null && mat.shader != null && mat.shader.name.Contains(shaderName))
                    {
                        if (!m_originalShaders.ContainsKey(mat.name))
                        {
                            m_originalShaders[mat.name] = mat.shader;
                        }
                        
                        Material newMat = new Material(mat);
                        newMat.shader = replacementShader;
                        newMaterials[i] = newMat;
                    }
                    else
                    {
                        newMaterials[i] = mat;
                    }
                }
                
                renderer.sharedMaterials = newMaterials;
            }
        }
    }
    
    // 移动端友好的简化Shader(代码方式)
    public class SimpleMobileShader
    {
        /*
        Shader "Mobile/OptimizedDiffuse" {
            Properties {
                _MainTex ("Base (RGB)", 2D) = "white" {}
                _Color ("Color", Color) = (1,1,1,1)
            }
            
            SubShader {
                Tags { "RenderType"="Opaque" }
                LOD 150
                
                CGPROGRAM
                #pragma surface surf Lambert noforwardadd noshadow
                #pragma skip_variants FOG_EXP FOG_EXP2
                
                sampler2D _MainTex;
                fixed4 _Color;
                
                struct Input {
                    float2 uv_MainTex;
                };
                
                void surf (Input IN, inout SurfaceOutput o) {
                    fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
                    o.Albedo = c.rgb;
                    o.Alpha = c.a;
                }
                ENDCG
            }
            
            FallBack "Mobile/VertexLit"
        }
        */
    }
}

第三部分:内存优化策略

3.1 纹理内存优化

// 纹理动态加载与卸载系统
public class TextureMemoryManager : MonoBehaviour
{
    [System.Serializable]
    public class TextureInfo
    {
        public string TextureName;
        public Texture2D Texture;
        public long MemorySize; // 字节
        public float LastAccessTime;
        public bool IsPermanent; // 是否常驻内存
        public int ReferenceCount;
    }
    
    private Dictionary<string, TextureInfo> m_textureCache = new Dictionary<string, TextureInfo>();
    private long m_maxMemoryBytes = 100 * 1024 * 1024; // 100MB
    private long m_currentMemoryBytes = 0;
    
    // 纹理加载策略
    public enum LoadStrategy
    {
        Immediate,      // 立即加载
        Async,          // 异步加载
        Streaming,      // 流式加载
        OnDemand        // 按需加载
    }
    
    public Texture2D LoadTexture(string path, LoadStrategy strategy = LoadStrategy.OnDemand)
    {
        // 检查缓存
        if (m_textureCache.TryGetValue(path, out var info))
        {
            info.LastAccessTime = Time.time;
            info.ReferenceCount++;
            return info.Texture;
        }
        
        Texture2D texture = null;
        
        switch (strategy)
        {
            case LoadStrategy.Immediate:
                texture = Resources.Load<Texture2D>(path);
                break;
                
            case LoadStrategy.Async:
                StartCoroutine(LoadTextureAsync(path, tex => texture = tex));
                break;
                
            case LoadStrategy.OnDemand:
                // 检查内存是否足够
                if (CanLoadTexture(path))
                {
                    texture = Resources.Load<Texture2D>(path);
                }
                else
                {
                    // 需要先卸载一些纹理
                    UnloadLeastUsedTextures(GetTextureSize(path));
                    texture = Resources.Load<Texture2D>(path);
                }
                break;
        }
        
        if (texture != null)
        {
            long size = CalculateTextureSize(texture);
            AddToCache(path, texture, size);
        }
        
        return texture;
    }
    
    IEnumerator LoadTextureAsync(string path, Action<Texture2D> callback)
    {
        ResourceRequest request = Resources.LoadAsync<Texture2D>(path);
        yield return request;
        
        Texture2D texture = request.asset as Texture2D;
        callback?.Invoke(texture);
    }
    
    long CalculateTextureSize(Texture2D texture)
    {
        // 计算纹理内存占用
        // 公式: 宽度 × 高度 × 每个像素的字节数
        int bytesPerPixel = GetBytesPerPixel(texture.format);
        return texture.width * texture.height * bytesPerPixel;
    }
    
    int GetBytesPerPixel(TextureFormat format)
    {
        switch (format)
        {
            case TextureFormat.RGBA32: return 4;
            case TextureFormat.RGB24: return 3;
            case TextureFormat.RGBAFloat: return 16;
            case TextureFormat.RGBAHalf: return 8;
            case TextureFormat.ETC2_RGBA8: return 1; // 压缩格式
            case TextureFormat.PVRTC_RGBA4: return 0.5f; // 4bpp
            default: return 4;
        }
    }
    
    void AddToCache(string path, Texture2D texture, long size)
    {
        var info = new TextureInfo
        {
            TextureName = path,
            Texture = texture,
            MemorySize = size,
            LastAccessTime = Time.time,
            ReferenceCount = 1
        };
        
        m_textureCache[path] = info;
        m_currentMemoryBytes += size;
        
        // 检查内存限制
        if (m_currentMemoryBytes > m_maxMemoryBytes)
        {
            UnloadLeastUsedTextures(m_currentMemoryBytes - m_maxMemoryBytes);
        }
    }
    
    void UnloadLeastUsedTextures(long bytesToFree)
    {
        // 按最后访问时间和引用计数排序
        var texturesToUnload = m_textureCache.Values
            .Where(t => !t.IsPermanent && t.ReferenceCount == 0)
            .OrderBy(t => t.LastAccessTime)
            .ToList();
        
        long freedBytes = 0;
        
        foreach (var textureInfo in texturesToUnload)
        {
            if (freedBytes >= bytesToFree) break;
            
            Resources.UnloadAsset(textureInfo.Texture);
            m_textureCache.Remove(textureInfo.TextureName);
            m_currentMemoryBytes -= textureInfo.MemorySize;
            freedBytes += textureInfo.MemorySize;
            
            Debug.Log($"卸载纹理: {textureInfo.TextureName}, 释放: {textureInfo.MemorySize / 1024}KB");
        }
    }
    
    // 纹理压缩优化
    public void OptimizeTextureCompression()
    {
        #if UNITY_EDITOR
        // 批量设置纹理压缩格式
        string[] texturePaths = UnityEditor.AssetDatabase.FindAssets("t:Texture2D");
        
        foreach (string guid in texturePaths)
        {
            string path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid);
            UnityEditor.TextureImporter importer = UnityEditor.AssetImporter.GetAtPath(path) as UnityEditor.TextureImporter;
            
            if (importer != null)
            {
                // 根据平台设置压缩格式
                UnityEditor.TextureImporterPlatformSettings androidSettings = importer.GetPlatformTextureSettings("Android");
                androidSettings.overridden = true;
                androidSettings.format = UnityEditor.TextureImporterFormat.ETC2_RGBA8;
                androidSettings.maxTextureSize = 2048; // 限制最大尺寸
                importer.SetPlatformTextureSettings(androidSettings);
                
                UnityEditor.TextureImporterPlatformSettings iosSettings = importer.GetPlatformTextureSettings("iPhone");
                iosSettings.overridden = true;
                iosSettings.format = UnityEditor.TextureImporterFormat.PVRTC_RGBA4;
                iosSettings.maxTextureSize = 2048;
                importer.SetPlatformTextureSettings(iosSettings);
                
                // 启用Mipmap(根据需求)
                importer.mipmapEnabled = !importer.textureType == UnityEditor.TextureImporterType.Sprite;
                
                UnityEditor.AssetDatabase.ImportAsset(path);
            }
        }
        #endif
    }
    
    // 纹理动态降级
    public class TextureQualityScaler : MonoBehaviour
    {
        private Dictionary<Texture2D, Texture2D> m_lowResVersions = new Dictionary<Texture2D, Texture2D>();
        
        public void ScaleTexturesBasedOnMemory(float scaleFactor)
        {
            // 根据可用内存调整纹理质量
            long availableMemory = SystemInfo.systemMemorySize * 1024 * 1024;
            long usedMemory = Profiler.GetTotalAllocatedMemoryLong();
            
            float memoryUsageRatio = (float)usedMemory / availableMemory;
            
            if (memoryUsageRatio > 0.7f) // 内存使用超过70%
            {
                // 降低所有纹理的分辨率
                foreach (var kvp in m_textureCache)
                {
                    ScaleTexture(kvp.Value.Texture, scaleFactor);
                }
            }
        }
        
        void ScaleTexture(Texture2D original, float scale)
        {
            if (m_lowResVersions.ContainsKey(original)) return;
            
            // 创建低分辨率版本
            int newWidth = Mathf.Max(32, (int)(original.width * scale));
            int newHeight = Mathf.Max(32, (int)(original.height * scale));
            
            Texture2D lowResTexture = new Texture2D(newWidth, newHeight, original.format, false);
            
            // 使用双线性滤波缩放
            Color[] pixels = original.GetPixels();
            Color[] scaledPixels = ScalePixels(pixels, original.width, original.height, newWidth, newHeight);
            
            lowResTexture.SetPixels(scaledPixels);
            lowResTexture.Apply();
            
            m_lowResVersions[original] = lowResTexture;
            
            // 替换材质中的纹理
            ReplaceTextureInMaterials(original, lowResTexture);
        }
    }
}

3.2 对象池与内存复用

// 智能对象池系统
public class SmartObjectPool : MonoBehaviour
{
    [System.Serializable]
    public class PoolConfig
    {
        public GameObject Prefab;
        public int InitialSize = 10;
        public int MaxSize = 100;
        public bool CanGrow = true;
        public float AutoCleanupTime = 60f; // 60秒后清理未使用的对象
    }
    
    private class PooledObject
    {
        public GameObject GameObject;
        public float LastUseTime;
        public bool IsInUse;
    }
    
    private Dictionary<string, Queue<PooledObject>> m_pools = new Dictionary<string, Queue<PooledObject>>();
    private Dictionary<string, PoolConfig> m_poolConfigs = new Dictionary<string, PoolConfig>();
    private Dictionary<GameObject, PooledObject> m_activeObjects = new Dictionary<GameObject, PooledObject>();
    
    void Start()
    {
        // 启动自动清理
        StartCoroutine(AutoCleanupRoutine());
    }
    
    public void RegisterPool(string poolName, PoolConfig config)
    {
        m_poolConfigs[poolName] = config;
        m_pools[poolName] = new Queue<PooledObject>();
        
        // 预热对象池
        PrewarmPool(poolName, config.InitialSize);
    }
    
    void PrewarmPool(string poolName, int count)
    {
        var config = m_poolConfigs[poolName];
        var pool = m_pools[poolName];
        
        for (int i = 0; i < count; i++)
        {
            GameObject obj = Instantiate(config.Prefab);
            obj.SetActive(false);
            obj.transform.SetParent(transform);
            
            pool.Enqueue(new PooledObject
            {
                GameObject = obj,
                LastUseTime = Time.time,
                IsInUse = false
            });
        }
    }
    
    public GameObject GetFromPool(string poolName, Vector3 position, Quaternion rotation)
    {
        if (!m_pools.ContainsKey(poolName))
        {
            Debug.LogError($"对象池未注册: {poolName}");
            return null;
        }
        
        var pool = m_pools[poolName];
        var config = m_poolConfigs[poolName];
        
        PooledObject pooledObj = null;
        
        // 尝试从池中获取
        if (pool.Count > 0)
        {
            pooledObj = pool.Dequeue();
        }
        // 如果池为空且允许增长
        else if (config.CanGrow && GetTotalPoolSize(poolName) < config.MaxSize)
        {
            GameObject newObj = Instantiate(config.Prefab);
            newObj.transform.SetParent(transform);
            
            pooledObj = new PooledObject
            {
                GameObject = newObj,
                LastUseTime = Time.time,
                IsInUse = false
            };
        }
        
        if (pooledObj != null)
        {
            pooledObj.GameObject.SetActive(true);
            pooledObj.GameObject.transform.position = position;
            pooledObj.GameObject.transform.rotation = rotation;
            pooledObj.LastUseTime = Time.time;
            pooledObj.IsInUse = true;
            
            m_activeObjects[pooledObj.GameObject] = pooledObj;
            
            return pooledObj.GameObject;
        }
        
        return null;
    }
    
    public void ReturnToPool(GameObject obj)
    {
        if (!m_activeObjects.TryGetValue(obj, out var pooledObj))
        {
            Debug.LogWarning($"对象不属于任何对象池: {obj.name}");
            Destroy(obj);
            return;
        }
        
        // 重置对象状态
        ResetPooledObject(pooledObj);
        
        // 检查应该回到哪个池
        string poolName = FindPoolNameForPrefab(obj);
        if (!string.IsNullOrEmpty(poolName))
        {
            var pool = m_pools[poolName];
            var config = m_poolConfigs[poolName];
            
            // 检查池是否已满
            if (pool.Count < config.MaxSize)
            {
                pool.Enqueue(pooledObj);
            }
            else
            {
                // 池已满,销毁对象
                Destroy(obj);
            }
        }
        
        m_activeObjects.Remove(obj);
    }
    
    void ResetPooledObject(PooledObject pooledObj)
    {
        GameObject obj = pooledObj.GameObject;
        
        obj.SetActive(false);
        obj.transform.SetParent(transform);
        pooledObj.IsInUse = false;
        pooledObj.LastUseTime = Time.time;
        
        // 重置所有组件状态
        var rigidbody = obj.GetComponent<Rigidbody>();
        if (rigidbody != null)
        {
            rigidbody.velocity = Vector3.zero;
            rigidbody.angularVelocity = Vector3.zero;
        }
        
        // 重置粒子系统
        var particleSystem = obj.GetComponent<ParticleSystem>();
        if (particleSystem != null)
        {
            particleSystem.Clear();
        }
        
        // 重置动画状态
        var animator = obj.GetComponent<Animator>();
        if (animator != null)
        {
            animator.Rebind();
        }
    }
    
    IEnumerator AutoCleanupRoutine()
    {
        while (true)
        {
            yield return new WaitForSeconds(30f); // 每30秒检查一次
            
            CleanupUnusedObjects();
        }
    }
    
    void CleanupUnusedObjects()
    {
        float currentTime = Time.time;
        
        foreach (var kvp in m_pools)
        {
            string poolName = kvp.Key;
            var pool = kvp.Value;
            var config = m_poolConfigs[poolName];
            
            if (config.AutoCleanupTime <= 0) continue;
            
            // 检查并清理长时间未使用的对象
            List<PooledObject> objectsToRemove = new List<PooledObject>();
            
            foreach (var pooledObj in pool)
            {
                if (!pooledObj.IsInUse && 
                    (currentTime - pooledObj.LastUseTime) > config.AutoCleanupTime)
                {
                    objectsToRemove.Add(pooledObj);
                }
            }
            
            foreach (var obj in objectsToRemove)
            {
                pool = new Queue<PooledObject>(pool.Where(o => o != obj));
                Destroy(obj.GameObject);
                
                Debug.Log($"清理长时间未使用的对象: {poolName}");
            }
            
            m_pools[poolName] = pool;
        }
    }
    
    // 内存压力响应
    public void OnMemoryWarning()
    {
        Debug.Log("收到内存警告,清理对象池");
        
        // 强制清理所有未使用的对象
        foreach (var kvp in m_pools)
        {
            var pool = kvp.Value;
            var config = m_poolConfigs[kvp.Key];
            
            // 保留最小数量的对象
            int objectsToKeep = Mathf.Min(5, config.InitialSize / 2);
            
            while (pool.Count > objectsToKeep)
            {
                var obj = pool.Dequeue();
                if (!obj.IsInUse)
                {
                    Destroy(obj.GameObject);
                }
                else
                {
                    // 如果正在使用,放回队列
                    pool.Enqueue(obj);
                }
            }
        }
        
        // 触发GC
        System.GC.Collect();
        Resources.UnloadUnusedAssets();
    }
}

第四部分:CPU性能优化

4.1 脚本执行优化

// 分层更新系统
public class HierarchicalUpdateSystem : MonoBehaviour
{
    [System.Serializable]
    public class UpdateLayer
    {
        public string Name;
        public float UpdateInterval = 0.1f; // 更新间隔(秒)
        public List<MonoBehaviour> Components = new List<MonoBehaviour>();
        
        [NonSerialized]
        public float Timer;
        [NonSerialized]
        public int CurrentIndex;
    }
    
    public List<UpdateLayer> Layers = new List<UpdateLayer>();
    
    private Dictionary<MonoBehaviour, UpdateLayer> m_componentLayers = new Dictionary<MonoBehaviour, UpdateLayer>();
    
    void Update()
    {
        float deltaTime = Time.deltaTime;
        
        foreach (var layer in Layers)
        {
            layer.Timer += deltaTime;
            
            if (layer.Timer >= layer.UpdateInterval)
            {
                layer.Timer = 0f;
                
                // 分帧更新:每帧只更新一部分组件
                UpdateLayerComponents(layer);
            }
        }
    }
    
    void UpdateLayerComponents(UpdateLayer layer)
    {
        if (layer.Components.Count == 0) return;
        
        // 每帧更新固定数量的组件
        int componentsPerFrame = Mathf.CeilToInt(layer.Components.Count / (layer.UpdateInterval / Time.deltaTime));
        componentsPerFrame = Mathf.Max(1, componentsPerFrame);
        
        for (int i = 0; i < componentsPerFrame; i++)
        {
            int index = (layer.CurrentIndex + i) % layer.Components.Count;
            var component = layer.Components[index];
            
            if (component != null && component.isActiveAndEnabled)
            {
                UpdateComponent(component);
            }
        }
        
        layer.CurrentIndex = (layer.CurrentIndex + componentsPerFrame) % layer.Components.Count;
    }
    
    void UpdateComponent(MonoBehaviour component)
    {
        // 使用接口或基类来调用更新方法
        if (component is IUpdateable updateable)
        {
            updateable.OnUpdate();
        }
        // 或者使用反射(性能较差,仅作示例)
        // var method = component.GetType().GetMethod("CustomUpdate");
        // method?.Invoke(component, null);
    }
    
    public void RegisterComponent(MonoBehaviour component, float updateInterval)
    {
        // 查找或创建合适的层
        UpdateLayer layer = Layers.Find(l => Mathf.Approximately(l.UpdateInterval, updateInterval));
        
        if (layer == null)
        {
            layer = new UpdateLayer
            {
                Name = $"Layer_{updateInterval}s",
                UpdateInterval = updateInterval
            };
            Layers.Add(layer);
        }
        
        layer.Components.Add(component);
        m_componentLayers[component] = layer;
    }
    
    public void UnregisterComponent(MonoBehaviour component)
    {
        if (m_componentLayers.TryGetValue(component, out var layer))
        {
            layer.Components.Remove(component);
            m_componentLayers.Remove(component);
        }
    }
    
    // 动态调整更新频率
    public void AdjustUpdateRateBasedOnPerformance()
    {
        float fps = 1f / Time.unscaledDeltaTime;
        
        if (fps < 30)
        {
            // 性能不佳,降低更新频率
            foreach (var layer in Layers)
            {
                layer.UpdateInterval *= 1.5f; // 增加50%间隔
            }
        }
        else if (fps > 50)
        {
            // 性能良好,可提高更新频率
            foreach (var layer in Layers)
            {
                layer.UpdateInterval = Mathf.Max(0.016f, layer.UpdateInterval * 0.8f); // 减少20%间隔
            }
        }
    }
}

// 接口定义
public interface IUpdateable
{
    void OnUpdate();
}

// 使用示例
public class OptimizedEnemyAI : MonoBehaviour, IUpdateable
{
    private HierarchicalUpdateSystem m_updateSystem;
    
    void Start()
    {
        m_updateSystem = FindObjectOfType<HierarchicalUpdateSystem>();
        if (m_updateSystem != null)
        {
            // 注册为每0.5秒更新一次(而不是每帧)
            m_updateSystem.RegisterComponent(this, 0.5f);
        }
    }
    
    public void OnUpdate()
    {
        // AI逻辑,每0.5秒执行一次
        UpdateAI();
    }
    
    void UpdateAI()
    {
        // 简化的AI逻辑
        // ...
    }
    
    void OnDestroy()
    {
        if (m_updateSystem != null)
        {
            m_updateSystem.UnregisterComponent(this);
        }
    }
}

// 批量处理系统(减少每帧调用)
public class BatchProcessor : MonoBehaviour
{
    private class BatchOperation
    {
        public Action Action;
        public float Priority;
    }
    
    private List<BatchOperation> m_operations = new List<BatchOperation>();
    private List<BatchOperation> m_pendingOperations = new List<BatchOperation>();
    private object m_lock = new object();
    
    public int MaxOperationsPerFrame = 10;
    
    void Update()
    {
        // 处理批次操作
        ProcessBatch();
    }
    
    public void AddOperation(Action action, float priority = 0)
    {
        lock (m_lock)
        {
            m_pendingOperations.Add(new BatchOperation
            {
                Action = action,
                Priority = priority
            });
        }
    }
    
    void ProcessBatch()
    {
        // 将待处理操作添加到主列表
        lock (m_lock)
        {
            if (m_pendingOperations.Count > 0)
            {
                m_operations.AddRange(m_pendingOperations);
                m_pendingOperations.Clear();
            }
        }
        
        // 按优先级排序
        m_operations.Sort((a, b) => b.Priority.CompareTo(a.Priority));
        
        // 每帧处理有限数量的操作
        int processedCount = 0;
        for (int i = m_operations.Count - 1; i >= 0 && processedCount < MaxOperationsPerFrame; i--)
        {
            try
            {
                m_operations[i].Action?.Invoke();
            }
            catch (Exception e)
            {
                Debug.LogError($"批处理操作失败: {e.Message}");
            }
            
            m_operations.RemoveAt(i);
            processedCount++;
        }
    }
    
    // 使用示例:批量更新UI
    public class BatchUIUpdater : MonoBehaviour
    {
        private BatchProcessor m_batchProcessor;
        private Dictionary<string, string> m_uiUpdates = new Dictionary<string, string>();
        
        void Start()
        {
            m_batchProcessor = FindObjectOfType<BatchProcessor>();
        }
        
        public void QueueUIUpdate(string elementId, string newValue)
        {
            m_uiUpdates[elementId] = newValue;
            
            // 添加到批处理器(低优先级)
            m_batchProcessor.AddOperation(() =>
            {
                UpdateAllUIElements();
            }, 0.5f);
        }
        
        void UpdateAllUIElements()
        {
            // 一次性更新所有UI元素
            foreach (var kvp in m_uiUpdates)
            {
                // 更新UI逻辑
                // ...
            }
            
            m_uiUpdates.Clear();
        }
    }
}

4.2 物理优化

// 移动端物理优化系统
public class MobilePhysicsOptimizer : MonoBehaviour
{
    [System.Serializable]
    public class PhysicsLayerConfig
    {
        public string LayerName;
        public int LayerIndex;
        public float UpdateFrequency = 0.1f; // 更新频率(秒)
        public bool UseSimplifiedCollision = true;
        public bool EnableOnlyWhenVisible = true;
    }
    
    public List<PhysicsLayerConfig> LayerConfigs = new List<PhysicsLayerConfig>();
    
    private Dictionary<int, PhysicsLayer> m_physicsLayers = new Dictionary<int, PhysicsLayer>();
    
    private class PhysicsLayer
    {
        public PhysicsLayerConfig Config;
        public List<Rigidbody> Rigidbodies = new List<Rigidbody>();
        public float Timer;
        public bool IsVisible;
    }
    
    void Start()
    {
        InitializePhysicsLayers();
        ApplyMobilePhysicsSettings();
    }
    
    void InitializePhysicsLayers()
    {
        // 初始化所有物理层
        foreach (var config in LayerConfigs)
        {
            var layer = new PhysicsLayer
            {
                Config = config,
                Timer = 0f
            };
            
            m_physicsLayers[config.LayerIndex] = layer;
        }
        
        // 收集所有刚体并分配到对应层
        Rigidbody[] allRigidbodies = FindObjectsOfType<Rigidbody>();
        foreach (var rb in allRigidbodies)
        {
            int layer = rb.gameObject.layer;
            if (m_physicsLayers.TryGetValue(layer, out var physicsLayer))
            {
                physicsLayer.Rigidbodies.Add(rb);
                
                // 应用层特定设置
                ApplyLayerSettings(rb, physicsLayer.Config);
            }
        }
    }
    
    void ApplyLayerSettings(Rigidbody rb, PhysicsLayerConfig config)
    {
        if (config.UseSimplifiedCollision)
        {
            // 使用简化碰撞体
            ReplaceWithSimplifiedCollider(rb.gameObject);
        }
        
        // 禁用不需要的物理特性
        rb.sleepThreshold = 0.5f; // 提高睡眠阈值
        rb.solverIterations = 4;  // 减少求解器迭代次数
        rb.solverVelocityIterations = 1;
    }
    
    void ReplaceWithSimplifiedCollider(GameObject obj)
    {
        Collider[] colliders = obj.GetComponents<Collider>();
        
        foreach (var collider in colliders)
        {
            // 根据需求替换为简化碰撞体
            if (collider is MeshCollider meshCollider)
            {
                // MeshCollider性能较差,替换为BoxCollider或CapsuleCollider
                ReplaceMeshCollider(meshCollider);
            }
        }
    }
    
    void ReplaceMeshCollider(MeshCollider meshCollider)
    {
        GameObject obj = meshCollider.gameObject;
        Bounds bounds = meshCollider.bounds;
        
        // 根据形状选择最合适的简化碰撞体
        Vector3 size = bounds.size;
        
        Destroy(meshCollider);
        
        // 根据长宽高比例选择碰撞体类型
        float maxDimension = Mathf.Max(size.x, size.y, size.z);
        float minDimension = Mathf.Min(size.x, size.y, size.z);
        float ratio = maxDimension / (minDimension + 0.001f);
        
        if (ratio > 3f)
        {
            // 长条形,使用胶囊碰撞体
            CapsuleCollider capsule = obj.AddComponent<CapsuleCollider>();
            capsule.center = bounds.center - obj.transform.position;
            capsule.height = size.y;
            capsule.radius = Mathf.Min(size.x, size.z) * 0.5f;
        }
        else
        {
            // 使用盒形碰撞体
            BoxCollider box = obj.AddComponent<BoxCollider>();
            box.center = bounds.center - obj.transform.position;
            box.size = size;
        }
    }
    
    void Update()
    {
        float deltaTime = Time.deltaTime;
        
        // 更新各物理层
        foreach (var kvp in m_physicsLayers)
        {
            var layer = kvp.Value;
            layer.Timer += deltaTime;
            
            // 检查可见性(如果启用)
            if (layer.Config.EnableOnlyWhenVisible)
            {
                layer.IsVisible = CheckLayerVisibility(layer);
            }
            else
            {
                layer.IsVisible = true;
            }
            
            // 按频率更新物理
            if (layer.IsVisible && layer.Timer >= layer.Config.UpdateFrequency)
            {
                layer.Timer = 0f;
                UpdatePhysicsLayer(layer);
            }
        }
    }
    
    bool CheckLayerVisibility(PhysicsLayer layer)
    {
        // 检查该层是否有任何刚体在相机视野内
        Camera mainCamera = Camera.main;
        if (mainCamera == null) return true;
        
        foreach (var rb in layer.Rigidbodies)
        {
            if (rb == null) continue;
            
            Vector3 viewportPos = mainCamera.WorldToViewportPoint(rb.position);
            if (viewportPos.x >= 0 && viewportPos.x <= 1 && 
                viewportPos.y >= 0 && viewportPos.y <= 1 &&
                viewportPos.z > 0)
            {
                return true;
            }
        }
        
        return false;
    }
    
    void UpdatePhysicsLayer(PhysicsLayer layer)
    {
        // 更新该层的所有刚体
        foreach (var rb in layer.Rigidbodies)
        {
            if (rb == null || !rb.gameObject.activeInHierarchy) continue;
            
            // 手动更新物理(简化的模拟)
            if (!rb.isKinematic)
            {
                // 应用重力
                rb.velocity += Physics.gravity * layer.Config.UpdateFrequency;
                
                // 应用阻力
                rb.velocity *= Mathf.Clamp01(1f - layer.Config.UpdateFrequency * rb.drag);
                
                // 更新位置
                rb.position += rb.velocity * layer.Config.UpdateFrequency;
            }
        }
    }
    
    void ApplyMobilePhysicsSettings()
    {
        // 应用移动端优化的物理设置
        Physics.defaultSolverIterations = 4;
        Physics.defaultSolverVelocityIterations = 1;
        Physics.sleepThreshold = 0.5f;
        Physics.defaultContactOffset = 0.01f;
        Physics.queriesHitBackfaces = false;
        Physics.queriesHitTriggers = false; // 如果不需要触发检测
        
        // 根据设备性能调整
        if (SystemInfo.processorFrequency < 1500) // 低频CPU
        {
            Time.fixedDeltaTime = 0.05f; // 20 FPS物理更新
            Physics.defaultSolverIterations = 2;
        }
        else
        {
            Time.fixedDeltaTime = 0.033f; // 30 FPS物理更新
        }
    }
    
    // 动态调整物理质量
    public class DynamicPhysicsQuality : MonoBehaviour
    {
        private float m_lastCheckTime;
        private float m_checkInterval = 2f;
        
        void Update()
        {
            if (Time.time - m_lastCheckTime > m_checkInterval)
            {
                m_lastCheckTime = Time.time;
                AdjustPhysicsQuality();
            }
        }
        
        void AdjustPhysicsQuality()
        {
            float frameTime = Time.unscaledDeltaTime * 1000f; // 毫秒
            
            if (frameTime > 33.3f) // 低于30FPS
            {
                // 降低物理质量
                Physics.defaultSolverIterations = Mathf.Max(2, Physics.defaultSolverIterations - 1);
                Time.fixedDeltaTime = Mathf.Min(0.1f, Time.fixedDeltaTime * 1.5f);
                
                Debug.Log($"降低物理质量: SolverIterations={Physics.defaultSolverIterations}, FixedDelta={Time.fixedDeltaTime}");
            }
            else if (frameTime < 16.7f) // 高于60FPS
            {
                // 可提高物理质量(如果有余量)
                Physics.defaultSolverIterations = Mathf.Min(8, Physics.defaultSolverIterations + 1);
                Time.fixedDeltaTime = Mathf.Max(0.016f, Time.fixedDeltaTime * 0.8f);
            }
        }
    }
}

第五部分:功耗与发热控制

// 移动端功耗管理系统
public class PowerManagementSystem : MonoBehaviour
{
    [System.Serializable]
    public class PowerProfile
    {
        public string ProfileName;
        public int TargetFrameRate = 30;
        public float ScreenBrightness = 0.7f;
        public bool EnableVSync = false;
        public int ShadowQuality = 0;
        public int TextureQuality = 1;
        public bool ReduceParticles = true;
        public bool SimplifyShaders = false;
    }
    
    public PowerProfile[] PowerProfiles = new PowerProfile[]
    {
        new PowerProfile { ProfileName = "HighPerformance", TargetFrameRate = 60 },
        new PowerProfile { ProfileName = "Balanced", TargetFrameRate = 45 },
        new PowerProfile { ProfileName = "PowerSaving", TargetFrameRate = 30 },
        new PowerProfile { ProfileName = "UltraSaving", TargetFrameRate = 20 }
    };
    
    private PowerProfile m_currentProfile;
    private float m_lastProfileChangeTime;
    private const float PROFILE_CHANGE_COOLDOWN = 10f; // 10秒冷却
    
    // 监控指标
    private float m_batteryDrainRate; // 电池消耗率(%/分钟)
    private float m_lastBatteryLevel;
    private float m_lastCheckTime;
    private float m_deviceTemperature; // 设备温度(模拟值)
    
    void Start()
    {
        // 初始化为平衡模式
        ApplyPowerProfile("Balanced");
        
        // 初始化监控
        m_lastBatteryLevel = GetBatteryLevel();
        m_lastCheckTime = Time.time;
        
        // 启动监控协程
        StartCoroutine(PowerMonitoringRoutine());
    }
    
    IEnumerator PowerMonitoringRoutine()
    {
        while (true)
        {
            yield return new WaitForSeconds(60f); // 每分钟检查一次
            
            UpdatePowerMetrics();
            AdjustProfileBasedOnConditions();
        }
    }
    
    void UpdatePowerMetrics()
    {
        float currentBatteryLevel = GetBatteryLevel();
        float currentTime = Time.time;
        float timeDelta = currentTime - m_lastCheckTime;
        
        if (timeDelta > 0)
        {
            m_batteryDrainRate = (m_lastBatteryLevel - currentBatteryLevel) / (timeDelta / 60f);
        }
        
        m_lastBatteryLevel = currentBatteryLevel;
        m_lastCheckTime = currentTime;
        
        // 模拟设备温度(实际项目需要平台特定API)
        m_deviceTemperature = EstimateDeviceTemperature();
        
        Debug.Log($"功耗监控 - 电池消耗: {m_batteryDrainRate:F2}%/分钟, 温度: {m_deviceTemperature:F1}°C");
    }
    
    void AdjustProfileBasedOnConditions()
    {
        // 检查电池电量
        float batteryLevel = GetBatteryLevel();
        
        // 检查是否在充电
        bool isCharging = IsCharging();
        
        // 检查设备温度
        bool isOverheating = m_deviceTemperature > 40f;
        
        // 决定使用哪个功耗配置文件
        string targetProfile = "Balanced";
        
        if (isOverheating)
        {
            targetProfile = "UltraSaving";
            Debug.LogWarning("设备过热,切换至超省电模式");
        }
        else if (!isCharging && batteryLevel < 20)
        {
            targetProfile = "PowerSaving";
            Debug.Log("电量低于20%,切换至省电模式");
        }
        else if (!isCharging && batteryLevel < 50)
        {
            targetProfile = "Balanced";
        }
        else if (isCharging || batteryLevel > 80)
        {
            targetProfile = "HighPerformance";
        }
        
        // 应用配置文件(如果有冷却时间)
        if (Time.time - m_lastProfileChangeTime > PROFILE_CHANGE_COOLDOWN)
        {
            ApplyPowerProfile(targetProfile);
            m_lastProfileChangeTime = Time.time;
        }
    }
    
    void ApplyPowerProfile(string profileName)
    {
        var profile = PowerProfiles.FirstOrDefault(p => p.ProfileName == profileName);
        if (profile == null) return;
        
        m_currentProfile = profile;
        
        // 应用设置
        Application.targetFrameRate = profile.TargetFrameRate;
        QualitySettings.vSyncCount = profile.EnableVSync ? 1 : 0;
        QualitySettings.shadowDistance = profile.ShadowQuality * 20f;
        QualitySettings.masterTextureLimit = profile.TextureQuality;
        
        if (profile.ReduceParticles)
        {
            ReduceParticleEffects();
        }
        
        if (profile.SimplifyShaders)
        {
            SimplifyShaderQuality();
        }
        
        Debug.Log($"应用功耗配置文件: {profileName}, 目标帧率: {profile.TargetFrameRate}");
    }
    
    void ReduceParticleEffects()
    {
        ParticleSystem[] allParticles = FindObjectsOfType<ParticleSystem>();
        foreach (var ps in allParticles)
        {
            var main = ps.main;
            main.maxParticles = Mathf.Min(main.maxParticles, 100);
            
            var emission = ps.emission;
            emission.rateOverTimeMultiplier *= 0.5f;
        }
    }
    
    void SimplifyShaderQuality()
    {
        // 切换到简化Shader
        // 实现参考前面的ShaderLODSystem
    }
    
    // 平台特定API封装
    float GetBatteryLevel()
    {
        #if UNITY_ANDROID && !UNITY_EDITOR
        try
        {
            using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
            using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
            using (AndroidJavaObject intentFilter = new AndroidJavaObject("android.content.IntentFilter", "android.intent.action.BATTERY_CHANGED"))
            using (AndroidJavaObject batteryIntent = currentActivity.Call<AndroidJavaObject>("registerReceiver", null, intentFilter))
            {
                int level = batteryIntent.Call<int>("getIntExtra", "level", -1);
                int scale = batteryIntent.Call<int>("getIntExtra", "scale", -1);
                
                if (level >= 0 && scale > 0)
                {
                    return (float)level / (float)scale * 100f;
                }
            }
        }
        catch (Exception e)
        {
            Debug.LogWarning($"获取电池电量失败: {e.Message}");
        }
        #elif UNITY_IOS && !UNITY_EDITOR
        // iOS使用UIDevice API
        #endif
        
        return 100f; // 默认值
    }
    
    bool IsCharging()
    {
        #if UNITY_ANDROID && !UNITY_EDITOR
        try
        {
            using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
            using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
            using (AndroidJavaObject intentFilter = new AndroidJavaObject("android.content.IntentFilter", "android.intent.action.BATTERY_CHANGED"))
            using (AndroidJavaObject batteryIntent = currentActivity.Call<AndroidJavaObject>("registerReceiver", null, intentFilter))
            {
                int status = batteryIntent.Call<int>("getIntExtra", "status", -1);
                return status == 2 || status == 5; // 2=充电中, 5=满电
            }
        }
        catch (Exception e)
        {
            Debug.LogWarning($"检查充电状态失败: {e.Message}");
        }
        #endif
        
        return false;
    }
    
    float EstimateDeviceTemperature()
    {
        // 实际项目需要平台特定API
        // 这里使用性能指标估算
        float frameTime = Time.unscaledDeltaTime * 1000f;
        float cpuUsage = (frameTime > 16.7f) ? (frameTime / 33.3f) : 0.5f;
        
        // 模拟温度:基础温度 + CPU使用率影响
        return 30f + cpuUsage * 15f;
    }
    
    // 后台运行优化
    void OnApplicationPause(bool pauseStatus)
    {
        if (pauseStatus)
        {
            // 应用进入后台
            OnEnterBackground();
        }
        else
        {
            // 应用回到前台
            OnEnterForeground();
        }
    }
    
    void OnEnterBackground()
    {
        Debug.Log("应用进入后台,降低资源消耗");
        
        // 大幅降低帧率
        Application.targetFrameRate = 10;
        
        // 暂停非必要的协程和更新
        PauseNonCriticalSystems();
        
        // 减少内存占用
        Resources.UnloadUnusedAssets();
        System.GC.Collect();
    }
    
    void OnEnterForeground()
    {
        Debug.Log("应用回到前台,恢复性能");
        
        // 恢复帧率
        ApplyPowerProfile(m_currentProfile.ProfileName);
        
        // 恢复系统
        ResumeCriticalSystems();
    }
    
    // 场景加载优化
    public class OptimizedSceneLoader : MonoBehaviour
    {
        public float MaxLoadingFrameTime = 16.7f; // 确保加载时不低于60FPS
        
        public IEnumerator LoadSceneAsyncWithLimit(string sceneName)
        {
            AsyncOperation asyncLoad = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(sceneName);
            asyncLoad.allowSceneActivation = false;
            
            while (asyncLoad.progress < 0.9f)
            {
                // 每帧限制加载时间
                float startTime = Time.realtimeSinceStartup;
                
                // 执行一部分加载
                // ...
                
                float elapsed = (Time.realtimeSinceStartup - startTime) * 1000f;
                if (elapsed < MaxLoadingFrameTime)
                {
                    // 如果还有时间,让出控制权
                    yield return null;
                }
                else
                {
                    // 已经用完了帧时间,等待下一帧
                    yield return new WaitForEndOfFrame();
                }
            }
            
            // 加载完成,激活场景
            asyncLoad.allowSceneActivation = true;
        }
    }
}

第六部分:网络与IO优化

// 移动端网络优化
public class MobileNetworkOptimizer : MonoBehaviour
{
    public enum NetworkType
    {
        Unknown,
        WiFi,
        Cellular4G,
        Cellular3G,
        Cellular2G
    }
    
    private NetworkType m_currentNetworkType = NetworkType.Unknown;
    private float m_networkSpeed; // KB/s
    private float m_lastNetworkCheckTime;
    
    void Start()
    {
        StartCoroutine(NetworkMonitoringRoutine());
    }
    
    IEnumerator NetworkMonitoringRoutine()
    {
        while (true)
        {
            yield return new WaitForSeconds(5f); // 每5秒检查一次
            
            DetectNetworkType();
            AdjustNetworkSettings();
        }
    }
    
    void DetectNetworkType()
    {
        #if UNITY_ANDROID && !UNITY_EDITOR
        try
        {
            using (AndroidJavaClass connectivityManagerClass = new AndroidJavaClass("android.net.ConnectivityManager"))
            using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
            using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
            using (AndroidJavaObject connectivityManager = currentActivity.Call<AndroidJavaObject>("getSystemService", "connectivity"))
            {
                AndroidJavaObject networkInfo = connectivityManager.Call<AndroidJavaObject>("getActiveNetworkInfo");
                
                if (networkInfo != null && networkInfo.Call<bool>("isConnected"))
                {
                    int type = networkInfo.Call<int>("getType");
                    
                    if (type == 1) // TYPE_WIFI
                    {
                        m_currentNetworkType = NetworkType.WiFi;
                    }
                    else if (type == 0) // TYPE_MOBILE
                    {
                        int subtype = networkInfo.Call<int>("getSubtype");
                        
                        switch (subtype)
                        {
                            case 13: // LTE
                            case 19: // LTE_CA
                                m_currentNetworkType = NetworkType.Cellular4G;
                                break;
                            case 3: // UMTS
                            case 8: // HSDPA
                            case 9: // HSUPA
                            case 10: // HSPA
                            case 15: // HSPAP
                                m_currentNetworkType = NetworkType.Cellular3G;
                                break;
                            default:
                                m_currentNetworkType = NetworkType.Cellular2G;
                                break;
                        }
                    }
                }
            }
        }
        catch (Exception e)
        {
            Debug.LogWarning($"检测网络类型失败: {e.Message}");
        }
        #endif
    }
    
    void AdjustNetworkSettings()
    {
        switch (m_currentNetworkType)
        {
            case NetworkType.WiFi:
                // 高质量设置
                SetNetworkQuality(1.0f);
                break;
                
            case NetworkType.Cellular4G:
                // 中等质量
                SetNetworkQuality(0.7f);
                break;
                
            case NetworkType.Cellular3G:
                // 低质量
                SetNetworkQuality(0.4f);
                break;
                
            case NetworkType.Cellular2G:
                // 最低质量
                SetNetworkQuality(0.2f);
                break;
                
            default:
                SetNetworkQuality(0.5f);
                break;
        }
        
        Debug.Log($"网络类型: {m_currentNetworkType}, 应用相应优化");
    }
    
    void SetNetworkQuality(float quality)
    {
        // 调整网络相关设置
        // 例如:纹理下载质量、同步频率等
        
        // 调整AssetBundle下载质量
        AdjustAssetBundleQuality(quality);
        
        // 调整网络同步频率
        AdjustSyncFrequency(quality);
    }
    
    void AdjustAssetBundleQuality(float quality)
    {
        // 根据网络质量决定下载的AssetBundle质量
        if (quality < 0.3f)
        {
            // 使用低质量资源
            PlayerPrefs.SetString("AssetBundleQuality", "Low");
        }
        else if (quality < 0.6f)
        {
            // 使用中等质量资源
            PlayerPrefs.SetString("AssetBundleQuality", "Medium");
        }
        else
        {
            // 使用高质量资源
            PlayerPrefs.SetString("AssetBundleQuality", "High");
        }
    }
    
    // 智能资源下载
    public class SmartAssetDownloader : MonoBehaviour
    {
        private class DownloadTask
        {
            public string AssetUrl;
            public Action<byte[]> OnComplete;
            public int Priority; // 0=最高,越大优先级越低
            public float Timeout = 30f;
        }
        
        private Queue<DownloadTask> m_downloadQueue = new Queue<DownloadTask>();
        private bool m_isDownloading = false;
        private float m_maxDownloadSizePerFrame = 50 * 1024; // 50KB每帧
        
        public void DownloadAsset(string url, Action<byte[]> callback, int priority = 10)
        {
            var task = new DownloadTask
            {
                AssetUrl = url,
                OnComplete = callback,
                Priority = priority
            };
            
            m_downloadQueue.Enqueue(task);
            
            // 按优先级排序
            m_downloadQueue = new Queue<DownloadTask>(
                m_downloadQueue.OrderBy(t => t.Priority)
            );
            
            if (!m_isDownloading)
            {
                StartCoroutine(DownloadQueueProcessor());
            }
        }
        
        IEnumerator DownloadQueueProcessor()
        {
            m_isDownloading = true;
            
            while (m_downloadQueue.Count > 0)
            {
                var task = m_downloadQueue.Dequeue();
                yield return StartCoroutine(DownloadWithLimit(task));
                
                // 每下载一个任务后等待一帧,避免卡顿
                yield return null;
            }
            
            m_isDownloading = false;
        }
        
        IEnumerator DownloadWithLimit(DownloadTask task)
        {
            using (UnityEngine.Networking.UnityWebRequest request = 
                   UnityEngine.Networking.UnityWebRequest.Get(task.AssetUrl))
            {
                request.timeout = (int)task.Timeout;
                request.SendWebRequest();
                
                float startTime = Time.time;
                long downloadedSize = 0;
                
                while (!request.isDone)
                {
                    // 限制每帧下载量
                    if (downloadedSize < request.downloadedBytes)
                    {
                        long newData = request.downloadedBytes - downloadedSize;
                        
                        if (newData > m_maxDownloadSizePerFrame)
                        {
                            // 暂停下载直到下一帧
                            yield return null;
                        }
                        
                        downloadedSize = request.downloadedBytes;
                    }
                    
                    // 检查超时
                    if (Time.time - startTime > task.Timeout)
                    {
                        request.Abort();
                        Debug.LogWarning($"下载超时: {task.AssetUrl}");
                        task.OnComplete?.Invoke(null);
                        yield break;
                    }
                    
                    yield return null;
                }
                
                if (request.result == UnityEngine.Networking.UnityWebRequest.Result.Success)
                {
                    task.OnComplete?.Invoke(request.downloadHandler.data);
                }
                else
                {
                    Debug.LogError($"下载失败: {request.error}");
                    task.OnComplete?.Invoke(null);
                }
            }
        }
    }
    
    // 本地缓存优化
    public class LocalCacheOptimizer
    {
        private string m_cachePath;
        private Dictionary<string, DateTime> m_cacheIndex = new Dictionary<string, DateTime>();
        private long m_maxCacheSize = 100 * 1024 * 1024; // 100MB
        
        public LocalCacheOptimizer()
        {
            m_cachePath = Application.persistentDataPath + "/Cache/";
            
            if (!Directory.Exists(m_cachePath))
            {
                Directory.CreateDirectory(m_cachePath);
            }
            
            LoadCacheIndex();
        }
        
        public void SaveToCache(string key, byte[] data)
        {
            string filePath = m_cachePath + key;
            
            File.WriteAllBytes(filePath, data);
            m_cacheIndex[key] = DateTime.Now;
            
            SaveCacheIndex();
            
            // 检查缓存大小
            CheckAndCleanCache();
        }
        
        public byte[] LoadFromCache(string key, float maxAgeHours = 24)
        {
            if (!m_cacheIndex.TryGetValue(key, out var lastAccess))
                return null;
            
            // 检查缓存是否过期
            if ((DateTime.Now - lastAccess).TotalHours > maxAgeHours)
            {
                RemoveFromCache(key);
                return null;
            }
            
            string filePath = m_cachePath + key;
            if (File.Exists(filePath))
            {
                // 更新访问时间
                m_cacheIndex[key] = DateTime.Now;
                SaveCacheIndex();
                
                return File.ReadAllBytes(filePath);
            }
            
            return null;
        }
        
        void CheckAndCleanCache()
        {
            long currentSize = CalculateCacheSize();
            
            if (currentSize > m_maxCacheSize)
            {
                // 清理最旧的文件
                var filesToDelete = m_cacheIndex
                    .OrderBy(kvp => kvp.Value)
                    .Take(10) // 每次清理10个最旧的文件
                    .ToList();
                
                foreach (var kvp in filesToDelete)
                {
                    RemoveFromCache(kvp.Key);
                }
                
                Debug.Log($"缓存清理完成,删除了{filesToDelete.Count}个文件");
            }
        }
        
        long CalculateCacheSize()
        {
            long totalSize = 0;
            
            foreach (var kvp in m_cacheIndex)
            {
                string filePath = m_cachePath + kvp.Key;
                if (File.Exists(filePath))
                {
                    totalSize += new FileInfo(filePath).Length;
                }
            }
            
            return totalSize;
        }
        
        void LoadCacheIndex()
        {
            string indexFile = m_cachePath + "index.dat";
            if (File.Exists(indexFile))
            {
                string[] lines = File.ReadAllLines(indexFile);
                foreach (string line in lines)
                {
                    string[] parts = line.Split('|');
                    if (parts.Length == 2)
                    {
                        if (DateTime.TryParse(parts[1], out DateTime date))
                        {
                            m_cacheIndex[parts[0]] = date;
                        }
                    }
                }
            }
        }
        
        void SaveCacheIndex()
        {
            string indexFile = m_cachePath + "index.dat";
            using (StreamWriter writer = new StreamWriter(indexFile))
            {
                foreach (var kvp in m_cacheIndex)
                {
                    writer.WriteLine($"{kvp.Key}|{kvp.Value:yyyy-MM-dd HH:mm:ss}");
                }
            }
        }
    }
}

总结:移动端性能优化最佳实践

7.1 性能优化检查清单

// 移动端性能检查系统
public class MobilePerformanceChecklist : MonoBehaviour
{
    [System.Serializable]
    public class ChecklistItem
    {
        public string Category;
        public string Description;
        public bool IsChecked;
        public string HowToFix;
        public Severity Severity;
    }
    
    public enum Severity
    {
        Critical,   // 必须修复
        High,       // 应该修复
        Medium,     // 建议修复
        Low         // 可选修复
    }
    
    public List<ChecklistItem> Items = new List<ChecklistItem>();
    
    void Start()
    {
        LoadDefaultChecklist();
        StartCoroutine(RunPerformanceAudit());
    }
    
    void LoadDefaultChecklist()
    {
        Items = new List<ChecklistItem>
        {
            // 渲染优化
            new ChecklistItem
            {
                Category = "渲染",
                Description = "DrawCall是否超过平台限制?",
                Severity = Severity.Critical,
                HowToFix = "使用合批、GPU Instancing、减少材质数量"
            },
            
            new ChecklistItem
            {
                Category = "渲染",
                Description = "是否有过多的透明物体?",
                Severity = Severity.High,
                HowToFix = "合并透明物体,使用Alpha Test代替Alpha Blend"
            },
            
            // 内存优化
            new ChecklistItem
            {
                Category = "内存",
                Description = "纹理是否使用压缩格式?",
                Severity = Severity.Critical,
                HowToFix = "Android使用ETC2,iOS使用PVRTC,启用纹理压缩"
            },
            
            new ChecklistItem
            {
                Category = "内存",
                Description = "是否有内存泄漏?",
                Severity = Severity.Critical,
                HowToFix = "使用Profiler检查内存分配,实现对象池"
            },
            
            // CPU优化
            new ChecklistItem
            {
                Category = "CPU",
                Description = "是否每帧都有不必要的GC分配?",
                Severity = Severity.High,
                HowToFix = "避免在Update中分配内存,使用对象池和缓存"
            },
            
            new ChecklistItem
            {
                Category = "CPU",
                Description = "物理计算是否过多?",
                Severity = Severity.Medium,
                HowToFix = "减少刚体数量,使用简化的碰撞体,分层更新物理"
            },
            
            // 功耗优化
            new ChecklistItem
            {
                Category = "功耗",
                Description = "帧率是否稳定?",
                Severity = Severity.High,
                HowToFix = "确保帧率稳定在30或60FPS,避免波动"
            },
            
            new ChecklistItem
            {
                Category = "功耗",
                Description = "是否有过热问题?",
                Severity = Severity.Medium,
                HowToFix = "降低渲染质量,减少粒子效果,实现热限制自适应"
            }
        };
    }
    
    IEnumerator RunPerformanceAudit()
    {
        yield return new WaitForSeconds(5f); // 等待游戏稳定
        
        Debug.Log("=== 移动端性能审计开始 ===");
        
        foreach (var item in Items)
        {
            item.IsChecked = CheckItem(item);
            
            if (!item.IsChecked && item.Severity <= Severity.High)
            {
                Debug.LogWarning($"[{item.Category}] {item.Description}");
                Debug.Log($"建议修复: {item.HowToFix}");
            }
            
            yield return null; // 分帧检查避免卡顿
        }
        
        Debug.Log("=== 移动端性能审计完成 ===");
        
        GeneratePerformanceReport();
    }
    
    bool CheckItem(ChecklistItem item)
    {
        switch (item.Description)
        {
            case "DrawCall是否超过平台限制?":
                #if UNITY_EDITOR
                int drawCalls = UnityEditor.UnityStats.drawCalls;
                return drawCalls <= GetDrawCallLimit();
                #else
                return true; // 发布版本中需要其他检测方式
                #endif
                
            case "是否有内存泄漏?":
                return CheckMemoryLeak();
                
            case "是否每帧都有不必要的GC分配?":
                return CheckGCAllocation();
                
            default:
                return true;
        }
    }
    
    bool CheckMemoryLeak()
    {
        // 监控内存增长趋势
        // 实际实现需要更复杂的监控
        return true;
    }
    
    bool CheckGCAllocation()
    {
        // 检查GC分配频率
        // 实际实现需要Profiler数据
        return true;
    }
    
    void GeneratePerformanceReport()
    {
        StringBuilder report = new StringBuilder();
        report.AppendLine("=== 移动端性能报告 ===");
        report.AppendLine($"生成时间: {DateTime.Now}");
        report.AppendLine($"设备: {SystemInfo.deviceModel}");
        report.AppendLine($"平台: {Application.platform}");
        report.AppendLine();
        
        int criticalIssues = Items.Count(i => !i.IsChecked && i.Severity == Severity.Critical);
        int highIssues = Items.Count(i => !i.IsChecked && i.Severity == Severity.High);
        
        report.AppendLine($"关键问题: {criticalIssues}");
        report.AppendLine($"重要问题: {highIssues}");
        report.AppendLine();
        
        if (criticalIssues > 0)
        {
            report.AppendLine("必须修复的问题:");
            foreach (var item in Items.Where(i => !i.IsChecked && i.Severity == Severity.Critical))
            {
                report.AppendLine($"  • {item.Description}");
            }
        }
        
        Debug.Log(report.ToString());
    }
}

7.2 平台特定优化指南

iOS优化要点

  1. 使用Metal图形API(不要使用OpenGL ES)
  2. 纹理格式使用PVRTC(压缩比高)
  3. 注意iOS的内存警告(收到警告必须立即清理)
  4. 使用Asset Catalog管理资源
  5. 注意64位架构支持

Android优化要点

  1. 支持多种分辨率和DPI
  2. 使用ETC2纹理压缩(支持Alpha通道)
  3. 注意不同厂商的GPU差异(Mali、Adreno、PowerVR)
  4. 处理Android内存管理(LMK机制)
  5. 支持多种ABI架构(armeabi-v7a, arm64-v8a)

7.3 持续优化策略

  1. 性能基准测试:建立性能基准,每次提交代码前进行测试
  2. 自动化测试:编写性能回归测试,集成到CI/CD流程
  3. 用户数据分析:收集真实用户的性能数据,发现实际瓶颈
  4. 渐进式优化:先解决最影响性能的问题,逐步优化次要问题
  5. 团队培训:确保所有开发人员了解移动端性能最佳实践

7.4 关键性能指标(KPI)

  • 帧率稳定性:99%的帧在目标帧时间±30%内
  • 内存峰值:低于平台限制的80%
  • 启动时间:冷启动<3秒,热启动<1秒
  • 电池消耗:每小时<15%(正常游戏)
  • 安装包大小:iOS<200MB,Android<150MB(APK)

结论

移动端性能优化是一个系统工程,需要从架构设计、资源管理、代码实现到测试验证的全流程关注。成功的优化不是一次性工作,而是持续的过程。通过建立完善的性能监控体系、实施针对性的优化策略、并培养团队的优化意识,才能在移动平台上提供流畅、稳定的游戏体验。

记住:最好的优化是用户感受不到的优化——游戏既流畅又省电,安装包小却画质精美,这才是移动端性能优化的终极目标。

Logo

更多推荐