Unity3D游戏开发中的数学应用与商业实践

12.4.9 场景资源动态加载的数学优化

在商业级游戏开发中,场景加载的效率直接影响用户体验。我们通过数学模型来优化加载过程,采用概率统计方法预测资源加载顺序,减少用户等待时间。

12.4.9.1 加载优先级计算模型

资源加载优先级不应是固定的,而应基于玩家行为数据进行动态调整。我们使用马尔可夫链模型预测玩家接下来可能进入的场景,实现预加载。

using System;
using System.Collections.Generic;
using UnityEngine;

namespace SceneManagementOptimization
{
    // 场景转移概率矩阵
    public class SceneTransitionMatrix
    {
        private Dictionary<string, Dictionary<string, float>> transitionProbabilities;
        private Dictionary<string, int> sceneVisitCount;
        
        public SceneTransitionMatrix()
        {
            transitionProbabilities = new Dictionary<string, Dictionary<string, float>>();
            sceneVisitCount = new Dictionary<string, int>();
            InitializeDefaultProbabilities();
        }
        
        private void InitializeDefaultProbabilities()
        {
            // 初始化常见场景转移概率
            AddTransition("MainMenu", "Level1", 0.6f);
            AddTransition("MainMenu", "Settings", 0.3f);
            AddTransition("Level1", "Level2", 0.7f);
            AddTransition("Level1", "MainMenu", 0.3f);
        }
        
        public void AddTransition(string fromScene, string toScene, float probability)
        {
            if (!transitionProbabilities.ContainsKey(fromScene))
            {
                transitionProbabilities[fromScene] = new Dictionary<string, float>();
            }
            
            transitionProbabilities[fromScene][toScene] = probability;
        }
        
        public void RecordSceneVisit(string sceneName)
        {
            if (!sceneVisitCount.ContainsKey(sceneName))
            {
                sceneVisitCount[sceneName] = 0;
            }
            sceneVisitCount[sceneName]++;
            
            // 基于实际访问数据调整概率
            AdjustProbabilitiesBasedOnActualUsage();
        }
        
        private void AdjustProbabilitiesBasedOnActualUsage()
        {
            // 这里可以实现基于实际使用数据的概率调整算法
            // 例如使用贝叶斯更新或最大似然估计
        }
        
        public List<string> GetNextLikelyScenes(string currentScene, int count)
        {
            List<string> likelyScenes = new List<string>();
            
            if (transitionProbabilities.ContainsKey(currentScene))
            {
                // 按概率降序排序
                var sortedScenes = new List<KeyValuePair<string, float>>(
                    transitionProbabilities[currentScene]);
                
                sortedScenes.Sort((a, b) => b.Value.CompareTo(a.Value));
                
                for (int i = 0; i < Mathf.Min(count, sortedScenes.Count); i++)
                {
                    likelyScenes.Add(sortedScenes[i].Key);
                }
            }
            
            return likelyScenes;
        }
    }
    
    // 智能场景加载器
    public class IntelligentSceneLoader : MonoBehaviour
    {
        private SceneTransitionMatrix transitionMatrix;
        private Dictionary<string, AsyncOperation> loadingOperations;
        private Queue<string> preloadQueue;
        
        private void Start()
        {
            transitionMatrix = new SceneTransitionMatrix();
            loadingOperations = new Dictionary<string, AsyncOperation>();
            preloadQueue = new Queue<string>();
            
            // 开始智能预加载
            StartCoroutine(IntelligentPreloading());
        }
        
        private System.Collections.IEnumerator IntelligentPreloading()
        {
            while (true)
            {
                yield return new WaitForSeconds(5f); // 每5秒重新评估预加载需求
                
                string currentScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
                List<string> likelyScenes = transitionMatrix.GetNextLikelyScenes(currentScene, 2);
                
                foreach (string sceneName in likelyScenes)
                {
                    if (!IsSceneLoadedOrLoading(sceneName))
                    {
                        PreloadSceneAsync(sceneName, 0.3f); // 预加载30%的资源
                    }
                }
                
                // 清理不再需要的预加载
                CleanupUnnecessaryPreloads(likelyScenes);
            }
        }
        
        private void PreloadSceneAsync(string sceneName, float loadPercentage)
        {
            // 异步预加载场景的部分资源
            AsyncOperation operation = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(
                sceneName, UnityEngine.SceneManagement.LoadSceneMode.Additive);
            
            operation.allowSceneActivation = false;
            operation.priority = ThreadPriority.BelowNormal;
            
            // 设置最大加载百分比
            StartCoroutine(LoadWithLimit(operation, loadPercentage));
            
            loadingOperations[sceneName] = operation;
        }
        
        private System.Collections.IEnumerator LoadWithLimit(AsyncOperation operation, float limit)
        {
            while (operation.progress < limit)
            {
                yield return null;
            }
            
            // 暂停加载,但保持已加载的资源在内存中
            operation.allowSceneActivation = false;
        }
        
        private bool IsSceneLoadedOrLoading(string sceneName)
        {
            return loadingOperations.ContainsKey(sceneName);
        }
        
        private void CleanupUnnecessaryPreloads(List<string> currentLikelyScenes)
        {
            List<string> toRemove = new List<string>();
            
            foreach (var kvp in loadingOperations)
            {
                if (!currentLikelyScenes.Contains(kvp.Key))
                {
                    // 如果场景在最近2分钟内没有被预测为可能场景,则卸载
                    StartCoroutine(UnloadIfUnused(kvp.Key, kvp.Value));
                    toRemove.Add(kvp.Key);
                }
            }
            
            foreach (string sceneName in toRemove)
            {
                loadingOperations.Remove(sceneName);
            }
        }
        
        private System.Collections.IEnumerator UnloadIfUnused(string sceneName, AsyncOperation operation)
        {
            yield return new WaitForSeconds(120f); // 等待2分钟
            
            if (loadingOperations.ContainsKey(sceneName))
            {
                UnityEngine.SceneManagement.SceneManager.UnloadSceneAsync(sceneName);
                loadingOperations.Remove(sceneName);
            }
        }
        
        // 当玩家实际切换场景时调用
        public void OnSceneChanged(string newSceneName)
        {
            transitionMatrix.RecordSceneVisit(newSceneName);
            
            // 如果已经预加载了该场景,快速激活
            if (loadingOperations.ContainsKey(newSceneName))
            {
                StartCoroutine(QuickActivateScene(newSceneName));
            }
        }
        
        private System.Collections.IEnumerator QuickActivateScene(string sceneName)
        {
            AsyncOperation operation = loadingOperations[sceneName];
            operation.allowSceneActivation = true;
            
            while (!operation.isDone)
            {
                yield return null;
            }
            
            loadingOperations.Remove(sceneName);
        }
    }
}

12.4.9.2 内存压力自适应卸载策略

在移动设备上,内存管理至关重要。我们使用数学模型计算内存压力指数,动态调整AssetBundle的卸载策略。

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace MemoryOptimization
{
    // 内存压力评估器
    public class MemoryPressureEvaluator
    {
        private const float CriticalThreshold = 0.85f;
        private const float WarningThreshold = 0.7f;
        private const float SafeThreshold = 0.5f;
        
        private struct MemoryUsageHistory
        {
            public float Timestamp;
            public float UsagePercentage;
            public float ChangeRate;
        }
        
        private Queue<MemoryUsageHistory> historyQueue;
        private int maxHistorySize = 60; // 保留60秒的历史数据
        
        public MemoryPressureEvaluator()
        {
            historyQueue = new Queue<MemoryUsageHistory>(maxHistorySize);
        }
        
        public float CalculateMemoryPressure()
        {
            float totalMemory = SystemInfo.systemMemorySize;
            float usedMemory = GetCurrentUsedMemory();
            float usagePercentage = usedMemory / totalMemory;
            
            // 记录当前内存使用情况
            RecordMemoryUsage(usagePercentage);
            
            // 计算综合压力指数(当前使用率 + 趋势权重)
            float trendWeight = CalculateUsageTrend();
            float pressureIndex = usagePercentage * 0.7f + trendWeight * 0.3f;
            
            return Mathf.Clamp01(pressureIndex);
        }
        
        private float GetCurrentUsedMemory()
        {
            // 这里可以使用更精确的内存统计方法
            return UnityEngine.Profiling.Profiler.GetTotalAllocatedMemoryLong() / (1024f * 1024f);
        }
        
        private void RecordMemoryUsage(float usagePercentage)
        {
            MemoryUsageHistory currentHistory = new MemoryUsageHistory()
            {
                Timestamp = Time.time,
                UsagePercentage = usagePercentage,
                ChangeRate = 0f
            };
            
            if (historyQueue.Count > 0)
            {
                MemoryUsageHistory lastHistory = historyQueue.Last();
                float timeDelta = currentHistory.Timestamp - lastHistory.Timestamp;
                if (timeDelta > 0)
                {
                    currentHistory.ChangeRate = 
                        (currentHistory.UsagePercentage - lastHistory.UsagePercentage) / timeDelta;
                }
            }
            
            historyQueue.Enqueue(currentHistory);
            
            if (historyQueue.Count > maxHistorySize)
            {
                historyQueue.Dequeue();
            }
        }
        
        private float CalculateUsageTrend()
        {
            if (historyQueue.Count < 2)
            {
                return 0f;
            }
            
            // 计算加权平均变化率(近期的变化权重更高)
            float weightedSum = 0f;
            float weightSum = 0f;
            int index = 0;
            
            foreach (var history in historyQueue)
            {
                float weight = Mathf.Pow(0.9f, index); // 指数衰减权重
                weightedSum += history.ChangeRate * weight;
                weightSum += weight;
                index++;
            }
            
            float averageChangeRate = weightedSum / weightSum;
            
            // 将变化率映射到[0, 1]范围
            return Mathf.Clamp01((averageChangeRate + 0.1f) / 0.2f);
        }
        
        public MemoryPressureLevel GetPressureLevel()
        {
            float pressure = CalculateMemoryPressure();
            
            if (pressure >= CriticalThreshold)
            {
                return MemoryPressureLevel.Critical;
            }
            else if (pressure >= WarningThreshold)
            {
                return MemoryPressureLevel.Warning;
            }
            else if (pressure >= SafeThreshold)
            {
                return MemoryPressureLevel.Moderate;
            }
            else
            {
                return MemoryPressureLevel.Safe;
            }
        }
        
        public enum MemoryPressureLevel
        {
            Safe,       // < 50%
            Moderate,   // 50% - 70%
            Warning,    // 70% - 85%
            Critical    // > 85%
        }
    }
    
    // 自适应AssetBundle管理器
    public class AdaptiveAssetBundleManager : MonoBehaviour
    {
        private MemoryPressureEvaluator pressureEvaluator;
        private Dictionary<string, AssetBundleInfo> loadedBundles;
        private Dictionary<string, float> bundleLastAccessTime;
        
        private class AssetBundleInfo
        {
            public AssetBundle Bundle;
            public int ReferenceCount;
            public float LoadTime;
            public float LastAccessTime;
            public int MemorySize; // 预估内存大小(KB)
            public string BundleName;
            public BundlePriority Priority;
        }
        
        private enum BundlePriority
        {
            Critical,   // 必须常驻内存
            High,       // 高频使用
            Medium,     // 一般使用
            Low         // 低频使用
        }
        
        private void Start()
        {
            pressureEvaluator = new MemoryPressureEvaluator();
            loadedBundles = new Dictionary<string, AssetBundleInfo>();
            bundleLastAccessTime = new Dictionary<string, float>();
            
            // 定期检查内存压力
            StartCoroutine(MemoryPressureMonitor());
        }
        
        private System.Collections.IEnumerator MemoryPressureMonitor()
        {
            while (true)
            {
                yield return new WaitForSeconds(10f);
                
                MemoryPressureEvaluator.MemoryPressureLevel pressureLevel = 
                    pressureEvaluator.GetPressureLevel();
                
                switch (pressureLevel)
                {
                    case MemoryPressureEvaluator.MemoryPressureLevel.Critical:
                        PerformAggressiveCleanup();
                        break;
                        
                    case MemoryPressureEvaluator.MemoryPressureLevel.Warning:
                        PerformModerateCleanup();
                        break;
                        
                    case MemoryPressureEvaluator.MemoryPressureLevel.Moderate:
                        PerformMildCleanup();
                        break;
                }
            }
        }
        
        private void PerformAggressiveCleanup()
        {
            Debug.LogWarning("内存压力严重,执行激进清理");
            
            // 卸载所有低优先级且最近未使用的Bundle
            UnloadBundlesByPriority(BundlePriority.Low, 30f); // 30秒内未使用
            UnloadBundlesByPriority(BundlePriority.Medium, 60f); // 60秒内未使用
            
            // 强制GC
            System.GC.Collect();
            Resources.UnloadUnusedAssets();
        }
        
        private void PerformModerateCleanup()
        {
            Debug.Log("内存压力警告,执行适度清理");
            
            // 卸载低优先级且最近未使用的Bundle
            UnloadBundlesByPriority(BundlePriority.Low, 15f); // 15秒内未使用
        }
        
        private void PerformMildCleanup()
        {
            // 仅卸载长时间未使用的低优先级Bundle
            UnloadBundlesByPriority(BundlePriority.Low, 300f); // 5分钟内未使用
        }
        
        private void UnloadBundlesByPriority(BundlePriority priority, float unusedThreshold)
        {
            List<string> bundlesToUnload = new List<string>();
            float currentTime = Time.time;
            
            foreach (var kvp in loadedBundles)
            {
                AssetBundleInfo info = kvp.Value;
                
                if (info.Priority == priority && 
                    info.ReferenceCount == 0 && 
                    (currentTime - info.LastAccessTime) > unusedThreshold)
                {
                    bundlesToUnload.Add(kvp.Key);
                }
            }
            
            foreach (string bundleName in bundlesToUnload)
            {
                UnloadBundleInternal(bundleName, true);
            }
        }
        
        public void LoadBundle(string bundleName, BundlePriority priority)
        {
            if (!loadedBundles.ContainsKey(bundleName))
            {
                // 实际加载AssetBundle的代码
                string bundlePath = GetBundlePath(bundleName);
                AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(bundlePath);
                
                StartCoroutine(WaitForBundleLoad(request, bundleName, priority));
            }
            else
            {
                // 更新访问时间和引用计数
                AssetBundleInfo info = loadedBundles[bundleName];
                info.LastAccessTime = Time.time;
                info.ReferenceCount++;
            }
        }
        
        private System.Collections.IEnumerator WaitForBundleLoad(
            AssetBundleCreateRequest request, string bundleName, BundlePriority priority)
        {
            yield return request;
            
            AssetBundleInfo info = new AssetBundleInfo()
            {
                Bundle = request.assetBundle,
                ReferenceCount = 1,
                LoadTime = Time.time,
                LastAccessTime = Time.time,
                MemorySize = EstimateBundleSize(request.assetBundle),
                BundleName = bundleName,
                Priority = priority
            };
            
            loadedBundles[bundleName] = info;
        }
        
        private int EstimateBundleSize(AssetBundle bundle)
        {
            // 简化的预估方法,实际项目中需要更精确的计算
            return bundle.GetAllAssetNames().Length * 100; // 假设每个资源100KB
        }
        
        public void UnloadBundle(string bundleName, bool force = false)
        {
            UnloadBundleInternal(bundleName, force);
        }
        
        private void UnloadBundleInternal(string bundleName, bool force)
        {
            if (loadedBundles.ContainsKey(bundleName))
            {
                AssetBundleInfo info = loadedBundles[bundleName];
                
                if (force || info.ReferenceCount <= 0)
                {
                    if (info.Bundle != null)
                    {
                        info.Bundle.Unload(true);
                    }
                    
                    loadedBundles.Remove(bundleName);
                }
                else
                {
                    info.ReferenceCount--;
                }
            }
        }
        
        private string GetBundlePath(string bundleName)
        {
            // 返回AssetBundle的实际路径
            return Application.streamingAssetsPath + "/" + bundleName;
        }
    }
}

12.5.1 游戏对象创建的数学分布优化

在大型商业游戏中,同时创建大量游戏对象可能导致性能问题。我们使用空间分区算法和概率分布来控制对象创建。

12.5.1.1 空间网格分布系统

using System;
using System.Collections.Generic;
using UnityEngine;

namespace GameObjectDistribution
{
    // 空间网格管理器
    public class SpatialGridManager : MonoBehaviour
    {
        [System.Serializable]
        public class GridCell
        {
            public Vector3 Center;
            public List<GameObject> Objects;
            public int InstanceCount;
            public float Density;
            
            public GridCell(Vector3 center)
            {
                Center = center;
                Objects = new List<GameObject>();
                InstanceCount = 0;
                Density = 0f;
            }
        }
        
        [Header("Grid Settings")]
        public Vector3 GridSize = new Vector3(100f, 0f, 100f); // 忽略Y轴
        public float CellSize = 10f;
        public int MaxObjectsPerCell = 20;
        
        private Dictionary<Vector2Int, GridCell> gridCells;
        private Vector3 gridOrigin;
        
        private void Start()
        {
            InitializeGrid();
            StartCoroutine(DensityOptimization());
        }
        
        private void InitializeGrid()
        {
            gridCells = new Dictionary<Vector2Int, GridCell>();
            gridOrigin = transform.position - GridSize * 0.5f;
            
            int cellsX = Mathf.CeilToInt(GridSize.x / CellSize);
            int cellsZ = Mathf.CeilToInt(GridSize.z / CellSize);
            
            for (int x = 0; x < cellsX; x++)
            {
                for (int z = 0; z < cellsZ; z++)
                {
                    Vector2Int cellCoord = new Vector2Int(x, z);
                    Vector3 cellCenter = new Vector3(
                        gridOrigin.x + (x + 0.5f) * CellSize,
                        gridOrigin.y,
                        gridOrigin.z + (z + 0.5f) * CellSize
                    );
                    
                    gridCells[cellCoord] = new GridCell(cellCenter);
                }
            }
        }
        
        private Vector2Int WorldToGridCoord(Vector3 position)
        {
            Vector3 localPos = position - gridOrigin;
            int x = Mathf.FloorToInt(localPos.x / CellSize);
            int z = Mathf.FloorToInt(localPos.z / CellSize);
            
            return new Vector2Int(x, z);
        }
        
        public bool CanCreateObjectAt(Vector3 position, GameObject prefab)
        {
            Vector2Int cellCoord = WorldToGridCoord(position);
            
            if (gridCells.ContainsKey(cellCoord))
            {
                GridCell cell = gridCells[cellCoord];
                
                // 检查密度限制
                if (cell.Density > 0.8f) // 密度阈值
                {
                    return false;
                }
                
                // 检查实例数量限制
                if (cell.InstanceCount >= MaxObjectsPerCell)
                {
                    return false;
                }
                
                // 检查与现有对象的距离
                foreach (GameObject existingObj in cell.Objects)
                {
                    if (existingObj != null)
                    {
                        float distance = Vector3.Distance(position, existingObj.transform.position);
                        float minDistance = CalculateMinimumDistance(prefab, existingObj);
                        
                        if (distance < minDistance)
                        {
                            return false;
                        }
                    }
                }
                
                return true;
            }
            
            return false;
        }
        
        private float CalculateMinimumDistance(GameObject obj1, GameObject obj2)
        {
            // 基于对象边界框计算最小距离
            Renderer renderer1 = obj1.GetComponent<Renderer>();
            Renderer renderer2 = obj2.GetComponent<Renderer>();
            
            if (renderer1 != null && renderer2 != null)
            {
                float size1 = Mathf.Max(
                    renderer1.bounds.size.x,
                    renderer1.bounds.size.z
                );
                
                float size2 = Mathf.Max(
                    renderer2.bounds.size.x,
                    renderer2.bounds.size.z
                );
                
                return (size1 + size2) * 0.5f;
            }
            
            return 2.0f; // 默认最小距离
        }
        
        public void RegisterObject(GameObject obj, Vector3 position)
        {
            Vector2Int cellCoord = WorldToGridCoord(position);
            
            if (gridCells.ContainsKey(cellCoord))
            {
                GridCell cell = gridCells[cellCoord];
                cell.Objects.Add(obj);
                cell.InstanceCount++;
                
                // 更新密度
                UpdateCellDensity(cellCoord);
            }
        }
        
        public void UnregisterObject(GameObject obj)
        {
            // 查找并移除对象
            foreach (var kvp in gridCells)
            {
                if (kvp.Value.Objects.Remove(obj))
                {
                    kvp.Value.InstanceCount--;
                    UpdateCellDensity(kvp.Key);
                    break;
                }
            }
        }
        
        private void UpdateCellDensity(Vector2Int cellCoord)
        {
            GridCell cell = gridCells[cellCoord];
            
            // 基于实例数量和空间占用计算密度
            float area = CellSize * CellSize;
            float occupiedArea = cell.InstanceCount * Mathf.PI * 4f; // 假设每个对象占据4π面积
            
            cell.Density = Mathf.Clamp01(occupiedArea / area);
        }
        
        private System.Collections.IEnumerator DensityOptimization()
        {
            while (true)
            {
                yield return new WaitForSeconds(30f);
                
                OptimizeObjectDistribution();
            }
        }
        
        private void OptimizeObjectDistribution()
        {
            // 寻找高密度和低密度区域
            List<Vector2Int> highDensityCells = new List<Vector2Int>();
            List<Vector2Int> lowDensityCells = new List<Vector2Int>();
            
            foreach (var kvp in gridCells)
            {
                if (kvp.Value.Density > 0.7f)
                {
                    highDensityCells.Add(kvp.Key);
                }
                else if (kvp.Value.Density < 0.3f)
                {
                    lowDensityCells.Add(kvp.Key);
                }
            }
            
            // 从高密度区域移动对象到低密度区域
            RedistributeObjects(highDensityCells, lowDensityCells);
        }
        
        private void RedistributeObjects(List<Vector2Int> sourceCells, List<Vector2Int> targetCells)
        {
            foreach (Vector2Int sourceCoord in sourceCells)
            {
                GridCell sourceCell = gridCells[sourceCoord];
                
                if (sourceCell.Objects.Count == 0)
                {
                    continue;
                }
                
                // 尝试移动对象到目标区域
                foreach (Vector2Int targetCoord in targetCells)
                {
                    GridCell targetCell = gridCells[targetCoord];
                    
                    if (targetCell.Density < 0.5f && sourceCell.Objects.Count > 0)
                    {
                        // 移动一个对象
                        GameObject objToMove = sourceCell.Objects[0];
                        
                        // 计算目标位置(在目标单元格内随机位置)
                        Vector3 newPosition = CalculateRandomPositionInCell(targetCoord);
                        
                        if (CanCreateObjectAt(newPosition, objToMove))
                        {
                            // 实际移动对象
                            objToMove.transform.position = newPosition;
                            
                            // 更新注册信息
                            sourceCell.Objects.Remove(objToMove);
                            sourceCell.InstanceCount--;
                            
                            targetCell.Objects.Add(objToMove);
                            targetCell.InstanceCount++;
                            
                            UpdateCellDensity(sourceCoord);
                            UpdateCellDensity(targetCoord);
                            
                            break;
                        }
                    }
                }
            }
        }
        
        private Vector3 CalculateRandomPositionInCell(Vector2Int cellCoord)
        {
            float minX = gridOrigin.x + cellCoord.x * CellSize;
            float minZ = gridOrigin.z + cellCoord.y * CellSize;
            
            float x = minX + UnityEngine.Random.Range(0.2f, 0.8f) * CellSize;
            float z = minZ + UnityEngine.Random.Range(0.2f, 0.8f) * CellSize;
            
            // 使用射线投射找到地面高度
            Ray ray = new Ray(new Vector3(x, 100f, z), Vector3.down);
            RaycastHit hit;
            
            if (Physics.Raycast(ray, out hit, 200f))
            {
                return new Vector3(x, hit.point.y, z);
            }
            
            return new Vector3(x, gridOrigin.y, z);
        }
        
        private void OnDrawGizmosSelected()
        {
            // 绘制网格可视化
            Gizmos.color = Color.cyan;
            
            int cellsX = Mathf.CeilToInt(GridSize.x / CellSize);
            int cellsZ = Mathf.CeilToInt(GridSize.z / CellSize);
            
            for (int x = 0; x <= cellsX; x++)
            {
                Vector3 start = gridOrigin + new Vector3(x * CellSize, 0, 0);
                Vector3 end = start + new Vector3(0, 0, GridSize.z);
                Gizmos.DrawLine(start, end);
            }
            
            for (int z = 0; z <= cellsZ; z++)
            {
                Vector3 start = gridOrigin + new Vector3(0, 0, z * CellSize);
                Vector3 end = start + new Vector3(GridSize.x, 0, 0);
                Gizmos.DrawLine(start, end);
            }
            
            // 绘制密度信息
            if (gridCells != null)
            {
                foreach (var kvp in gridCells)
                {
                    float alpha = kvp.Value.Density;
                    Gizmos.color = new Color(1f, 0f, 0f, alpha * 0.3f);
                    Gizmos.DrawCube(kvp.Value.Center, new Vector3(CellSize, 0.1f, CellSize));
                }
            }
        }
    }
    
    // 智能对象生成器
    public class IntelligentObjectSpawner : MonoBehaviour
    {
        public GameObject[] Prefabs;
        public int MaxTotalObjects = 1000;
        public float SpawnRadius = 50f;
        public float SpawnInterval = 0.1f;
        
        private SpatialGridManager gridManager;
        private List<GameObject> spawnedObjects;
        private int totalSpawnedCount;
        
        private void Start()
        {
            gridManager = FindObjectOfType<SpatialGridManager>();
            if (gridManager == null)
            {
                GameObject gridObj = new GameObject("SpatialGridManager");
                gridManager = gridObj.AddComponent<SpatialGridManager>();
            }
            
            spawnedObjects = new List<GameObject>();
            
            // 开始智能生成
            StartCoroutine(SmartSpawning());
        }
        
        private System.Collections.IEnumerator SmartSpawning()
        {
            while (totalSpawnedCount < MaxTotalObjects)
            {
                yield return new WaitForSeconds(SpawnInterval);
                
                Vector3 spawnPosition = CalculateOptimalSpawnPosition();
                GameObject prefab = SelectPrefabBasedOnDistribution(spawnPosition);
                
                if (prefab != null && gridManager.CanCreateObjectAt(spawnPosition, prefab))
                {
                    GameObject newObj = Instantiate(prefab, spawnPosition, Quaternion.identity);
                    spawnedObjects.Add(newObj);
                    totalSpawnedCount++;
                    
                    gridManager.RegisterObject(newObj, spawnPosition);
                    
                    // 设置对象生命周期
                    SetupObjectLifecycle(newObj);
                }
            }
        }
        
        private Vector3 CalculateOptimalSpawnPosition()
        {
            // 使用多种策略计算生成位置
            Vector3 position;
            
            // 策略1:随机位置
            position = transform.position + UnityEngine.Random.insideUnitSphere * SpawnRadius;
            position.y = transform.position.y;
            
            // 策略2:基于现有对象分布的优化位置
            if (spawnedObjects.Count > 10)
            {
                position = FindLowDensityArea();
            }
            
            // 确保位置在地面之上
            Ray ray = new Ray(position + Vector3.up * 10f, Vector3.down);
            RaycastHit hit;
            
            if (Physics.Raycast(ray, out hit, 20f))
            {
                position.y = hit.point.y;
            }
            
            return position;
        }
        
        private Vector3 FindLowDensityArea()
        {
            // 采样多个位置,选择最优的
            Vector3 bestPosition = transform.position;
            float bestScore = float.MinValue;
            
            for (int i = 0; i < 10; i++)
            {
                Vector3 testPosition = transform.position + 
                    UnityEngine.Random.insideUnitSphere * SpawnRadius;
                testPosition.y = transform.position.y;
                
                float score = CalculatePositionScore(testPosition);
                
                if (score > bestScore)
                {
                    bestScore = score;
                    bestPosition = testPosition;
                }
            }
            
            return bestPosition;
        }
        
        private float CalculatePositionScore(Vector3 position)
        {
            float score = 0f;
            
            // 1. 距离其他对象的平均距离(越远越好)
            float totalDistance = 0f;
            int nearbyCount = 0;
            
            foreach (GameObject obj in spawnedObjects)
            {
                float distance = Vector3.Distance(position, obj.transform.position);
                if (distance < 20f)
                {
                    totalDistance += distance;
                    nearbyCount++;
                }
            }
            
            if (nearbyCount > 0)
            {
                float avgDistance = totalDistance / nearbyCount;
                score += avgDistance * 0.5f; // 权重
            }
            
            // 2. 距离生成器的距离(适中为好)
            float distanceToSpawner = Vector3.Distance(position, transform.position);
            float idealDistance = SpawnRadius * 0.7f;
            score -= Mathf.Abs(distanceToSpawner - idealDistance) * 0.3f;
            
            return score;
        }
        
        private GameObject SelectPrefabBasedOnDistribution(Vector3 position)
        {
            if (Prefabs.Length == 0)
            {
                return null;
            }
            
            // 根据位置和现有分布选择预制体
            Dictionary<GameObject, int> typeCount = new Dictionary<GameObject, int>();
            
            // 统计附近的对象类型
            foreach (GameObject obj in spawnedObjects)
            {
                if (Vector3.Distance(position, obj.transform.position) < 15f)
                {
                    // 这里需要知道预制体类型,简化处理
                    // 实际项目中需要更精确的类型识别
                }
            }
            
            // 简单随机选择,可以扩展为基于分布的智能选择
            return Prefabs[UnityEngine.Random.Range(0, Prefabs.Length)];
        }
        
        private void SetupObjectLifecycle(GameObject obj)
        {
            // 添加自动销毁组件
            AutoDestroy autoDestroy = obj.AddComponent<AutoDestroy>();
            autoDestroy.Lifetime = UnityEngine.Random.Range(30f, 120f);
            autoDestroy.OnDestroyCallback += () =>
            {
                spawnedObjects.Remove(obj);
                gridManager.UnregisterObject(obj);
                totalSpawnedCount--;
            };
        }
        
        private void OnDestroy()
        {
            // 清理所有生成的对象
            foreach (GameObject obj in spawnedObjects)
            {
                if (obj != null)
                {
                    Destroy(obj);
                }
            }
        }
    }
    
    // 自动销毁组件
    public class AutoDestroy : MonoBehaviour
    {
        public float Lifetime = 60f;
        public System.Action OnDestroyCallback;
        
        private float spawnTime;
        
        private void Start()
        {
            spawnTime = Time.time;
        }
        
        private void Update()
        {
            if (Time.time - spawnTime > Lifetime)
            {
                if (OnDestroyCallback != null)
                {
                    OnDestroyCallback.Invoke();
                }
                Destroy(gameObject);
            }
        }
    }
}

12.6.7 数学驱动的性能优化系统

12.6.7.1 基于统计学分析的性能监控

在商业项目中,我们需要实时监控性能指标,并使用统计方法识别性能问题。

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace PerformanceAnalytics
{
    // 性能数据点
    [System.Serializable]
    public struct PerformanceDataPoint
    {
        public float Timestamp;
        public float FrameTime;
        public float MemoryUsage;
        public float CPUTime;
        public float GPUTime;
        public int DrawCalls;
        public int TriangleCount;
        public int VertexCount;
        
        public static PerformanceDataPoint Lerp(PerformanceDataPoint a, PerformanceDataPoint b, float t)
        {
            return new PerformanceDataPoint()
            {
                Timestamp = Mathf.Lerp(a.Timestamp, b.Timestamp, t),
                FrameTime = Mathf.Lerp(a.FrameTime, b.FrameTime, t),
                MemoryUsage = Mathf.Lerp(a.MemoryUsage, b.MemoryUsage, t),
                CPUTime = Mathf.Lerp(a.CPUTime, b.CPUTime, t),
                GPUTime = Mathf.Lerp(a.GPUTime, b.GPUTime, t),
                DrawCalls = Mathf.RoundToInt(Mathf.Lerp(a.DrawCalls, b.DrawCalls, t)),
                TriangleCount = Mathf.RoundToInt(Mathf.Lerp(a.TriangleCount, b.TriangleCount, t)),
                VertexCount = Mathf.RoundToInt(Mathf.Lerp(a.VertexCount, b.VertexCount, t))
            };
        }
    }
    
    // 性能统计分析器
    public class PerformanceAnalyzer : MonoBehaviour
    {
        [Header("Sampling Settings")]
        public float SamplingInterval = 0.5f; // 每0.5秒采样一次
        public int MaxDataPoints = 3600; // 保留1小时的数据(每秒2个点)
        
        [Header("Thresholds")]
        public float CriticalFrameTime = 33.3f; // 30 FPS
        public float WarningFrameTime = 16.7f;  // 60 FPS
        public float CriticalMemoryMB = 2048f;  // 2GB
        
        private List<PerformanceDataPoint> dataPoints;
        private float lastSampleTime;
        
        // 统计摘要
        private class StatisticalSummary
        {
            public float Mean;
            public float Median;
            public float StandardDeviation;
            public float Min;
            public float Max;
            public float Percentile90;
            public float Percentile95;
            public float Percentile99;
            
            public override string ToString()
            {
                return $"Mean: {Mean:F2}, SD: {StandardDeviation:F2}, " +
                       $"Min: {Min:F2}, Max: {Max:F2}, " +
                       $"P90: {Percentile90:F2}, P95: {Percentile95:F2}, P99: {Percentile99:F2}";
            }
        }
        
        private void Start()
        {
            dataPoints = new List<PerformanceDataPoint>(MaxDataPoints);
            lastSampleTime = Time.time;
            
            // 开始性能监控
            StartCoroutine(PerformanceMonitoring());
        }
        
        private System.Collections.IEnumerator PerformanceMonitoring()
        {
            while (true)
            {
                yield return new WaitForSeconds(SamplingInterval);
                
                SamplePerformanceData();
                
                // 自动分析性能问题
                AnalyzePerformance();
            }
        }
        
        private void SamplePerformanceData()
        {
            PerformanceDataPoint dataPoint = new PerformanceDataPoint()
            {
                Timestamp = Time.time,
                FrameTime = Time.deltaTime * 1000f, // 转换为毫秒
                MemoryUsage = UnityEngine.Profiling.Profiler.GetTotalAllocatedMemoryLong() / (1024f * 1024f),
                CPUTime = UnityEngine.Profiling.Profiler.GetTotalReservedMemoryLong() / (1024f * 1024f),
                GPUTime = 0f, // 需要特定API获取
                DrawCalls = UnityEngine.Profiling.Profiler.GetDrawCallsCount(),
                TriangleCount = UnityEngine.Profiling.Profiler.GetTrianglesCount(),
                VertexCount = UnityEngine.Profiling.Profiler.GetVerticesCount()
            };
            
            dataPoints.Add(dataPoint);
            
            // 保持数据量在限制内
            if (dataPoints.Count > MaxDataPoints)
            {
                dataPoints.RemoveAt(0);
            }
            
            lastSampleTime = Time.time;
        }
        
        private void AnalyzePerformance()
        {
            if (dataPoints.Count < 10) // 至少需要10个数据点
            {
                return;
            }
            
            // 计算帧时间的统计摘要
            StatisticalSummary frameTimeSummary = CalculateStatisticalSummary(
                dataPoints.Select(p => p.FrameTime).ToList()
            );
            
            // 检测性能异常
            DetectPerformanceAnomalies(frameTimeSummary);
            
            // 生成性能报告
            if (Time.frameCount % 300 == 0) // 每300帧生成一次报告
            {
                GeneratePerformanceReport();
            }
        }
        
        private StatisticalSummary CalculateStatisticalSummary(List<float> values)
        {
            if (values == null || values.Count == 0)
            {
                return new StatisticalSummary();
            }
            
            // 排序用于计算百分位数
            List<float> sortedValues = new List<float>(values);
            sortedValues.Sort();
            
            StatisticalSummary summary = new StatisticalSummary()
            {
                Mean = values.Average(),
                Median = CalculateMedian(sortedValues),
                Min = sortedValues.First(),
                Max = sortedValues.Last(),
                StandardDeviation = CalculateStandardDeviation(values),
                Percentile90 = CalculatePercentile(sortedValues, 0.90f),
                Percentile95 = CalculatePercentile(sortedValues, 0.95f),
                Percentile99 = CalculatePercentile(sortedValues, 0.99f)
            };
            
            return summary;
        }
        
        private float CalculateMedian(List<float> sortedValues)
        {
            int count = sortedValues.Count;
            
            if (count % 2 == 0)
            {
                return (sortedValues[count / 2 - 1] + sortedValues[count / 2]) / 2f;
            }
            else
            {
                return sortedValues[count / 2];
            }
        }
        
        private float CalculateStandardDeviation(List<float> values)
        {
            float mean = values.Average();
            float sumOfSquares = 0f;
            
            foreach (float value in values)
            {
                sumOfSquares += (value - mean) * (value - mean);
            }
            
            return Mathf.Sqrt(sumOfSquares / values.Count);
        }
        
        private float CalculatePercentile(List<float> sortedValues, float percentile)
        {
            if (sortedValues.Count == 0)
            {
                return 0f;
            }
            
            float index = percentile * (sortedValues.Count - 1);
            int lowerIndex = Mathf.FloorToInt(index);
            int upperIndex = Mathf.CeilToInt(index);
            
            if (lowerIndex == upperIndex)
            {
                return sortedValues[lowerIndex];
            }
            
            float weight = index - lowerIndex;
            return sortedValues[lowerIndex] * (1 - weight) + sortedValues[upperIndex] * weight;
        }
        
        private void DetectPerformanceAnomalies(StatisticalSummary frameTimeSummary)
        {
            // 检测帧时间异常
            if (frameTimeSummary.Percentile95 > CriticalFrameTime)
            {
                Debug.LogError($"严重性能问题:95%的帧时间超过{CriticalFrameTime}ms");
                LogPerformanceIssue("CriticalFrameTime", frameTimeSummary.Percentile95);
            }
            else if (frameTimeSummary.Percentile90 > WarningFrameTime)
            {
                Debug.LogWarning($"性能警告:90%的帧时间超过{WarningFrameTime}ms");
                LogPerformanceIssue("WarningFrameTime", frameTimeSummary.Percentile90);
            }
            
            // 检测内存泄漏趋势
            if (dataPoints.Count > 100)
            {
                DetectMemoryLeak();
            }
        }
        
        private void DetectMemoryLeak()
        {
            // 使用线性回归检测内存增长趋势
            List<float> timestamps = new List<float>();
            List<float> memoryValues = new List<float>();
            
            for (int i = Mathf.Max(0, dataPoints.Count - 100); i < dataPoints.Count; i++)
            {
                timestamps.Add(dataPoints[i].Timestamp);
                memoryValues.Add(dataPoints[i].MemoryUsage);
            }
            
            // 计算线性回归
            LinearRegressionResult regression = CalculateLinearRegression(timestamps, memoryValues);
            
            // 如果内存持续增长且速率超过阈值,报告可能的内存泄漏
            if (regression.Slope > 0.1f) // 每秒增长超过0.1MB
            {
                Debug.LogWarning($"检测到可能的内存泄漏:内存增长速率{regression.Slope:F2}MB/s,R²={regression.RSquared:F3}");
            }
        }
        
        private struct LinearRegressionResult
        {
            public float Slope;
            public float Intercept;
            public float RSquared;
        }
        
        private LinearRegressionResult CalculateLinearRegression(List<float> xValues, List<float> yValues)
        {
            if (xValues.Count != yValues.Count || xValues.Count < 2)
            {
                return new LinearRegressionResult();
            }
            
            int n = xValues.Count;
            float sumX = 0f, sumY = 0f, sumXY = 0f, sumX2 = 0f, sumY2 = 0f;
            
            for (int i = 0; i < n; i++)
            {
                float x = xValues[i];
                float y = yValues[i];
                
                sumX += x;
                sumY += y;
                sumXY += x * y;
                sumX2 += x * x;
                sumY2 += y * y;
            }
            
            float slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
            float intercept = (sumY - slope * sumX) / n;
            
            // 计算R²
            float yMean = sumY / n;
            float ssTotal = 0f;
            float ssResidual = 0f;
            
            for (int i = 0; i < n; i++)
            {
                float y = yValues[i];
                float yPred = slope * xValues[i] + intercept;
                
                ssTotal += (y - yMean) * (y - yMean);
                ssResidual += (y - yPred) * (y - yPred);
            }
            
            float rSquared = 1f - (ssResidual / ssTotal);
            
            return new LinearRegressionResult()
            {
                Slope = slope,
                Intercept = intercept,
                RSquared = rSquared
            };
        }
        
        private void LogPerformanceIssue(string issueType, float value)
        {
            // 这里可以将性能问题记录到文件或发送到服务器
            string logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {issueType}: {value:F2}";
            System.IO.File.AppendAllText("PerformanceIssues.log", logMessage + Environment.NewLine);
        }
        
        private void GeneratePerformanceReport()
        {
            if (dataPoints.Count == 0)
            {
                return;
            }
            
            // 计算各项指标的统计摘要
            StatisticalSummary frameTimeStats = CalculateStatisticalSummary(
                dataPoints.Select(p => p.FrameTime).ToList()
            );
            
            StatisticalSummary memoryStats = CalculateStatisticalSummary(
                dataPoints.Select(p => p.MemoryUsage).ToList()
            );
            
            StatisticalSummary drawCallStats = CalculateStatisticalSummary(
                dataPoints.Select(p => (float)p.DrawCalls).ToList()
            );
            
            // 生成报告字符串
            string report = $@"
性能报告 - {DateTime.Now:yyyy-MM-dd HH:mm:ss}
====================
数据点数量:{dataPoints.Count}
时间范围:{dataPoints.Last().Timestamp - dataPoints.First().Timestamp:F1}秒

帧时间统计(ms):
{frameTimeStats}

内存使用统计(MB):
{memoryStats}

绘制调用统计:
{drawCallStats}

最近60秒的性能摘要:
- 平均FPS:{1000f / frameTimeStats.Mean:F1}
- 最低FPS:{1000f / frameTimeStats.Max:F1}
- 最高FPS:{1000f / frameTimeStats.Min:F1}
- 95%帧时间:{frameTimeStats.Percentile95:F2}ms ({1000f / frameTimeStats.Percentile95:F1} FPS)
";
            
            Debug.Log(report);
            
            // 保存报告到文件
            SavePerformanceReport(report);
        }
        
        private void SavePerformanceReport(string report)
        {
            string fileName = $"PerformanceReport_{DateTime.Now:yyyyMMdd_HHmmss}.txt";
            string filePath = System.IO.Path.Combine(Application.persistentDataPath, "PerformanceReports", fileName);
            
            // 确保目录存在
            System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(filePath));
            
            System.IO.File.WriteAllText(filePath, report);
        }
        
        // 公共API供其他系统查询性能数据
        public float GetCurrentFrameTime()
        {
            if (dataPoints.Count == 0)
            {
                return 0f;
            }
            
            return dataPoints.Last().FrameTime;
        }
        
        public float GetAverageFrameTime(int lastNSeconds = 10)
        {
            if (dataPoints.Count == 0)
            {
                return 0f;
            }
            
            float cutoffTime = Time.time - lastNSeconds;
            var recentPoints = dataPoints.Where(p => p.Timestamp >= cutoffTime).ToList();
            
            if (recentPoints.Count == 0)
            {
                return dataPoints.Average(p => p.FrameTime);
            }
            
            return recentPoints.Average(p => p.FrameTime);
        }
        
        public PerformanceDataPoint GetWorstPerformancePoint(int lastNSeconds = 30)
        {
            if (dataPoints.Count == 0)
            {
                return new PerformanceDataPoint();
            }
            
            float cutoffTime = Time.time - lastNSeconds;
            var recentPoints = dataPoints.Where(p => p.Timestamp >= cutoffTime).ToList();
            
            if (recentPoints.Count == 0)
            {
                recentPoints = dataPoints;
            }
            
            return recentPoints.OrderByDescending(p => p.FrameTime).First();
        }
    }
    
    // 性能优化建议系统
    public class PerformanceAdvisor : MonoBehaviour
    {
        private PerformanceAnalyzer analyzer;
        private Dictionary<string, float> issueScores;
        
        [System.Serializable]
        public class OptimizationRule
        {
            public string RuleName;
            public string Description;
            public Func<bool> Condition;
            public float Priority;
            public string Recommendation;
        }
        
        private List<OptimizationRule> rules;
        
        private void Start()
        {
            analyzer = FindObjectOfType<PerformanceAnalyzer>();
            if (analyzer == null)
            {
                analyzer = gameObject.AddComponent<PerformanceAnalyzer>();
            }
            
            issueScores = new Dictionary<string, float>();
            
            InitializeRules();
            StartCoroutine(AdviseOptimization());
        }
        
        private void InitializeRules()
        {
            rules = new List<OptimizationRule>()
            {
                new OptimizationRule()
                {
                    RuleName = "HighDrawCalls",
                    Description = "绘制调用过多",
                    Condition = () => analyzer.GetAverageFrameTime(10) > 20f,
                    Priority = 0.8f,
                    Recommendation = "考虑使用静态批处理、GPU Instancing或合并网格来减少绘制调用"
                },
                new OptimizationRule()
                {
                    RuleName = "HighMemoryUsage",
                    Description = "内存使用过高",
                    Condition = () => 
                    {
                        // 检查最近内存使用趋势
                        return false; // 简化实现
                    },
                    Priority = 0.9f,
                    Recommendation = "检查AssetBundle卸载策略,增加对象池大小,减少同时加载的资源"
                },
                new OptimizationRule()
                {
                    RuleName = "CPU Intensive",
                    Description = "CPU耗时过高",
                    Condition = () => analyzer.GetAverageFrameTime(10) > 30f,
                    Priority = 0.7f,
                    Recommendation = "优化Update循环,考虑使用Job System或ECS,减少每帧的GameObject数量"
                }
            };
        }
        
        private System.Collections.IEnumerator AdviseOptimization()
        {
            while (true)
            {
                yield return new WaitForSeconds(10f);
                
                List<OptimizationRule> activeRules = new List<OptimizationRule>();
                
                foreach (OptimizationRule rule in rules)
                {
                    if (rule.Condition != null && rule.Condition.Invoke())
                    {
                        activeRules.Add(rule);
                        
                        // 更新问题分数
                        if (!issueScores.ContainsKey(rule.RuleName))
                        {
                            issueScores[rule.RuleName] = 0f;
                        }
                        
                        issueScores[rule.RuleName] += rule.Priority * 0.1f;
                    }
                }
                
                // 按优先级排序
                activeRules.Sort((a, b) => b.Priority.CompareTo(a.Priority));
                
                // 提供建议
                if (activeRules.Count > 0)
                {
                    ProvideAdvice(activeRules);
                }
            }
        }
        
        private void ProvideAdvice(List<OptimizationRule> activeRules)
        {
            string advice = "性能优化建议:\n";
            
            foreach (OptimizationRule rule in activeRules.Take(3)) // 最多提供3条建议
            {
                advice += $"- [{rule.Priority:P0}] {rule.Description}: {rule.Recommendation}\n";
                
                // 记录建议
                Debug.Log($"性能建议:{rule.Description} - {rule.Recommendation}");
            }
            
            // 在开发版本中显示建议
            #if DEVELOPMENT_BUILD || UNITY_EDITOR
            ShowAdviceUI(advice);
            #endif
        }
        
        private void ShowAdviceUI(string advice)
        {
            // 这里可以实现UI显示逻辑
            // 例如:在屏幕角落显示建议,或添加到调试面板
        }
        
        public Dictionary<string, float> GetIssueScores()
        {
            return new Dictionary<string, float>(issueScores);
        }
        
        public void ResetIssueScore(string ruleName)
        {
            if (issueScores.ContainsKey(ruleName))
            {
                issueScores[ruleName] = 0f;
            }
        }
    }
}

12.6.7.2 基于机器学习的性能预测

在高级商业项目中,我们可以使用简单的机器学习模型预测性能问题。

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace PerformancePrediction
{
    // 性能特征向量
    [System.Serializable]
    public struct PerformanceFeatures
    {
        public float FrameTime;
        public float MemoryUsage;
        public int DrawCalls;
        public int GameObjectCount;
        public int ActiveParticles;
        public int ActiveAnimations;
        public float CameraDistance;
        public int VisibleLights;
        
        public float[] ToArray()
        {
            return new float[]
            {
                FrameTime,
                MemoryUsage,
                DrawCalls,
                GameObjectCount,
                ActiveParticles,
                ActiveAnimations,
                CameraDistance,
                VisibleLights
            };
        }
        
        public static PerformanceFeatures FromArray(float[] array)
        {
            if (array == null || array.Length < 8)
            {
                return new PerformanceFeatures();
            }
            
            return new PerformanceFeatures()
            {
                FrameTime = array[0],
                MemoryUsage = array[1],
                DrawCalls = array[2],
                GameObjectCount = (int)array[3],
                ActiveParticles = (int)array[4],
                ActiveAnimations = (int)array[5],
                CameraDistance = array[6],
                VisibleLights = (int)array[7]
            };
        }
    }
    
    // 简化的线性回归预测器
    public class PerformancePredictor : MonoBehaviour
    {
        [System.Serializable]
        public class TrainingData
        {
            public PerformanceFeatures Features;
            public float TargetFrameTime; // 下一帧的预测帧时间
        }
        
        private List<TrainingData> trainingDataSet;
        private float[] coefficients; // 回归系数
        
        [Header("Prediction Settings")]
        public int TrainingWindow = 300; // 使用最近300帧的数据训练
        public float PredictionHorizon = 1.0f; // 预测1秒后的性能
        public float RetrainInterval = 5.0f; // 每5秒重新训练
        
        private PerformanceAnalyzer analyzer;
        private float lastRetrainTime;
        
        private void Start()
        {
            trainingDataSet = new List<TrainingData>();
            coefficients = new float[9]; // 8个特征 + 偏置项
            
            analyzer = FindObjectOfType<PerformanceAnalyzer>();
            if (analyzer == null)
            {
                analyzer = gameObject.AddComponent<PerformanceAnalyzer>();
            }
            
            lastRetrainTime = Time.time;
            
            // 开始预测循环
            StartCoroutine(PredictionLoop());
        }
        
        private System.Collections.IEnumerator PredictionLoop()
        {
            while (true)
            {
                yield return new WaitForEndOfFrame();
                
                // 收集当前性能特征
                PerformanceFeatures currentFeatures = CollectCurrentFeatures();
                
                // 添加到训练数据
                AddTrainingData(currentFeatures);
                
                // 定期重新训练模型
                if (Time.time - lastRetrainTime > RetrainInterval)
                {
                    TrainModel();
                    lastRetrainTime = Time.time;
                }
                
                // 进行预测
                float predictedFrameTime = PredictNextFrameTime(currentFeatures);
                
                // 根据预测结果采取预防措施
                TakePreventiveMeasures(predictedFrameTime);
            }
        }
        
        private PerformanceFeatures CollectCurrentFeatures()
        {
            Camera mainCamera = Camera.main;
            float cameraDistance = 0f;
            int visibleLights = 0;
            
            if (mainCamera != null)
            {
                // 计算到最近物体的距离(简化实现)
                Ray ray = new Ray(mainCamera.transform.position, mainCamera.transform.forward);
                RaycastHit hit;
                if (Physics.Raycast(ray, out hit, 1000f))
                {
                    cameraDistance = hit.distance;
                }
                
                // 统计可见灯光(简化实现)
                visibleLights = UnityEngine.Object.FindObjectsOfType<Light>()
                    .Count(l => l.enabled && l.gameObject.activeInHierarchy);
            }
            
            return new PerformanceFeatures()
            {
                FrameTime = Time.deltaTime * 1000f,
                MemoryUsage = UnityEngine.Profiling.Profiler.GetTotalAllocatedMemoryLong() / (1024f * 1024f),
                DrawCalls = UnityEngine.Profiling.Profiler.GetDrawCallsCount(),
                GameObjectCount = UnityEngine.Object.FindObjectsOfType<GameObject>().Length,
                ActiveParticles = UnityEngine.Object.FindObjectsOfType<ParticleSystem>()
                    .Count(ps => ps.isPlaying),
                ActiveAnimations = UnityEngine.Object.FindObjectsOfType<Animation>()
                    .Count(a => a.isPlaying),
                CameraDistance = cameraDistance,
                VisibleLights = visibleLights
            };
        }
        
        private void AddTrainingData(PerformanceFeatures currentFeatures)
        {
            // 这里需要存储历史数据以便训练
            // 简化实现:直接使用当前分析器的数据
            
            if (trainingDataSet.Count >= TrainingWindow)
            {
                trainingDataSet.RemoveAt(0);
            }
            
            // 在实际实现中,需要正确设置目标值(下一帧的帧时间)
            // 这里使用简化方法
            TrainingData data = new TrainingData()
            {
                Features = currentFeatures,
                TargetFrameTime = currentFeatures.FrameTime * 1.05f // 假设增加5%
            };
            
            trainingDataSet.Add(data);
        }
        
        private void TrainModel()
        {
            if (trainingDataSet.Count < 10)
            {
                return;
            }
            
            // 使用梯度下降训练线性回归模型
            int featureCount = 8;
            float learningRate = 0.01f;
            int iterations = 100;
            
            // 初始化系数
            for (int i = 0; i < coefficients.Length; i++)
            {
                coefficients[i] = UnityEngine.Random.Range(-0.1f, 0.1f);
            }
            
            // 梯度下降
            for (int iter = 0; iter < iterations; iter++)
            {
                float[] gradients = new float[coefficients.Length];
                
                // 计算梯度
                foreach (TrainingData data in trainingDataSet)
                {
                    float prediction = Predict(data.Features, coefficients);
                    float error = prediction - data.TargetFrameTime;
                    
                    float[] features = data.Features.ToArray();
                    
                    // 偏置项的梯度
                    gradients[0] += error;
                    
                    // 特征系数的梯度
                    for (int i = 0; i < featureCount; i++)
                    {
                        gradients[i + 1] += error * features[i];
                    }
                }
                
                // 更新系数
                for (int i = 0; i < coefficients.Length; i++)
                {
                    coefficients[i] -= learningRate * gradients[i] / trainingDataSet.Count;
                }
            }
        }
        
        private float Predict(PerformanceFeatures features, float[] coeffs)
        {
            float[] featureArray = features.ToArray();
            float prediction = coeffs[0]; // 偏置项
            
            for (int i = 0; i < featureArray.Length; i++)
            {
                prediction += coeffs[i + 1] * featureArray[i];
            }
            
            return prediction;
        }
        
        public float PredictNextFrameTime(PerformanceFeatures currentFeatures)
        {
            return Predict(currentFeatures, coefficients);
        }
        
        private void TakePreventiveMeasures(float predictedFrameTime)
        {
            float threshold = 33.3f; // 30 FPS阈值
            
            if (predictedFrameTime > threshold)
            {
                float severity = (predictedFrameTime - threshold) / threshold;
                
                if (severity > 0.5f) // 严重预测
                {
                    Debug.LogWarning($"预测到性能下降:预测帧时间{predictedFrameTime:F2}ms,采取措施");
                    
                    // 采取激进措施
                    ReduceGraphicsQuality(2);
                    CullDistantObjects(50f);
                    DisableNonEssentialEffects();
                }
                else if (severity > 0.2f) // 中等预测
                {
                    Debug.Log($"预测到轻微性能下降:预测帧时间{predictedFrameTime:F2}ms,采取预防措施");
                    
                    // 采取温和措施
                    ReduceGraphicsQuality(1);
                    CullDistantObjects(100f);
                }
            }
        }
        
        private void ReduceGraphicsQuality(int levels)
        {
            // 降低图形质量设置
            QualitySettings.SetQualityLevel(
                Mathf.Max(0, QualitySettings.GetQualityLevel() - levels),
                true
            );
        }
        
        private void CullDistantObjects(float distance)
        {
            // 简化实现:通过调整相机的远裁剪面
            Camera mainCamera = Camera.main;
            if (mainCamera != null)
            {
                mainCamera.farClipPlane = Mathf.Min(mainCamera.farClipPlane, distance);
            }
        }
        
        private void DisableNonEssentialEffects()
        {
            // 禁用非必要的特效
            ParticleSystem[] particleSystems = UnityEngine.Object.FindObjectsOfType<ParticleSystem>();
            foreach (ParticleSystem ps in particleSystems)
            {
                if (!ps.main.playOnAwake || ps.particleCount < 10)
                {
                    ps.Stop(true, ParticleSystemStopBehavior.StopEmitting);
                }
            }
            
            // 禁用非必要的灯光
            Light[] lights = UnityEngine.Object.FindObjectsOfType<Light>();
            foreach (Light light in lights)
            {
                if (light.type != LightType.Directional && 
                    !light.gameObject.CompareTag("EssentialLight"))
                {
                    light.enabled = false;
                }
            }
        }
        
        // 获取模型信息供调试使用
        public string GetModelInfo()
        {
            if (coefficients == null || coefficients.Length == 0)
            {
                return "模型未训练";
            }
            
            string info = "线性回归模型系数:\n";
            info += $"偏置项: {coefficients[0]:F4}\n";
            
            string[] featureNames = new string[]
            {
                "帧时间", "内存使用", "绘制调用", "游戏对象数",
                "活跃粒子", "活跃动画", "相机距离", "可见灯光"
            };
            
            for (int i = 0; i < Mathf.Min(featureNames.Length, coefficients.Length - 1); i++)
            {
                info += $"{featureNames[i]}: {coefficients[i + 1]:F4}\n";
            }
            
            return info;
        }
        
        // 评估模型准确性
        public float EvaluateModelAccuracy()
        {
            if (trainingDataSet.Count < 20)
            {
                return 0f;
            }
            
            // 使用最近20%的数据作为测试集
            int testSize = Mathf.Max(5, trainingDataSet.Count / 5);
            var testSet = trainingDataSet.Skip(trainingDataSet.Count - testSize).ToList();
            
            float totalError = 0f;
            
            foreach (TrainingData data in testSet)
            {
                float prediction = Predict(data.Features, coefficients);
                float error = Mathf.Abs(prediction - data.TargetFrameTime);
                totalError += error;
            }
            
            float meanAbsoluteError = totalError / testSet.Count;
            float meanFrameTime = testSet.Average(d => d.TargetFrameTime);
            
            // 返回准确率(1 - 相对误差)
            return Mathf.Max(0f, 1f - (meanAbsoluteError / meanFrameTime));
        }
    }
}

12.7.10 数学在资源管理中的应用

12.7.10.1 基于图论的资源依赖分析

在复杂商业项目中,资源之间的依赖关系可以表示为图结构,我们可以使用图论算法优化资源加载和卸载。

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace ResourceDependencyGraph
{
    // 资源节点
    public class ResourceNode
    {
        public string ResourceId;
        public UnityEngine.Object Resource;
        public int MemorySize;
        public float LastAccessTime;
        public int AccessCount;
        public List<string> Dependencies;
        public List<string> Dependents;
        
        public ResourceNode(string id)
        {
            ResourceId = id;
            Dependencies = new List<string>();
            Dependents = new List<string>();
            LastAccessTime = Time.time;
            AccessCount = 0;
        }
        
        public float CalculateImportanceScore(float currentTime)
        {
            // 计算资源的重要性分数
            float timeSinceLastAccess = currentTime - LastAccessTime;
            float timeFactor = Mathf.Exp(-timeSinceLastAccess / 300f); // 5分钟衰减
            
            float accessFactor = Mathf.Log10(AccessCount + 1);
            float dependencyFactor = Dependents.Count * 0.1f;
            
            return timeFactor * (accessFactor + dependencyFactor);
        }
    }
    
    // 资源依赖图
    public class ResourceDependencyGraph
    {
        private Dictionary<string, ResourceNode> nodes;
        private Dictionary<string, List<string>> adjacencyList;
        
        public ResourceDependencyGraph()
        {
            nodes = new Dictionary<string, ResourceNode>();
            adjacencyList = new Dictionary<string, List<string>>();
        }
        
        public void AddResource(string resourceId, UnityEngine.Object resource, int memorySize)
        {
            if (!nodes.ContainsKey(resourceId))
            {
                ResourceNode node = new ResourceNode(resourceId)
                {
                    Resource = resource,
                    MemorySize = memorySize
                };
                
                nodes[resourceId] = node;
                adjacencyList[resourceId] = new List<string>();
            }
        }
        
        public void AddDependency(string fromResource, string toResource)
        {
            if (nodes.ContainsKey(fromResource) && nodes.ContainsKey(toResource))
            {
                // 添加边:fromResource 依赖 toResource
                if (!adjacencyList[fromResource].Contains(toResource))
                {
                    adjacencyList[fromResource].Add(toResource);
                    
                    // 更新节点的依赖关系
                    nodes[fromResource].Dependencies.Add(toResource);
                    nodes[toResource].Dependents.Add(fromResource);
                }
            }
        }
        
        public void RecordResourceAccess(string resourceId)
        {
            if (nodes.ContainsKey(resourceId))
            {
                ResourceNode node = nodes[resourceId];
                node.LastAccessTime = Time.time;
                node.AccessCount++;
            }
        }
        
        // 拓扑排序:确定资源加载顺序
        public List<string> GetTopologicalLoadOrder()
        {
            List<string> loadOrder = new List<string>();
            Dictionary<string, int> inDegree = new Dictionary<string, int>();
            Queue<string> queue = new Queue<string>();
            
            // 计算入度
            foreach (var kvp in nodes)
            {
                inDegree[kvp.Key] = 0;
            }
            
            foreach (var kvp in adjacencyList)
            {
                foreach (string dependent in kvp.Value)
                {
                    inDegree[dependent]++;
                }
            }
            
            // 入度为0的节点入队
            foreach (var kvp in inDegree)
            {
                if (kvp.Value == 0)
                {
                    queue.Enqueue(kvp.Key);
                }
            }
            
            // 拓扑排序
            while (queue.Count > 0)
            {
                string current = queue.Dequeue();
                loadOrder.Add(current);
                
                if (adjacencyList.ContainsKey(current))
                {
                    foreach (string neighbor in adjacencyList[current])
                    {
                        inDegree[neighbor]--;
                        if (inDegree[neighbor] == 0)
                        {
                            queue.Enqueue(neighbor);
                        }
                    }
                }
            }
            
            // 检查是否有环(不应发生,但需要处理)
            if (loadOrder.Count != nodes.Count)
            {
                Debug.LogError("资源依赖图中存在环!");
                // 添加剩余节点
                foreach (var kvp in nodes)
                {
                    if (!loadOrder.Contains(kvp.Key))
                    {
                        loadOrder.Add(kvp.Key);
                    }
                }
            }
            
            return loadOrder;
        }
        
        // 获取需要一起卸载的资源集合
        public List<string> GetResourcesToUnload(string resourceId)
        {
            List<string> toUnload = new List<string>();
            HashSet<string> visited = new HashSet<string>();
            
            // 深度优先搜索,找到所有依赖此资源的资源
            DFSFindDependents(resourceId, visited, toUnload);
            
            return toUnload;
        }
        
        private void DFSFindDependents(string resourceId, HashSet<string> visited, List<string> result)
        {
            if (visited.Contains(resourceId))
            {
                return;
            }
            
            visited.Add(resourceId);
            result.Add(resourceId);
            
            if (nodes.ContainsKey(resourceId))
            {
                foreach (string dependent in nodes[resourceId].Dependents)
                {
                    DFSFindDependents(dependent, visited, result);
                }
            }
        }
        
        // 寻找最佳资源卸载候选(基于重要性分数和内存占用)
        public List<string> FindBestUnloadCandidates(int targetMemoryReduction)
        {
            List<ResourceNode> candidateNodes = new List<ResourceNode>();
            float currentTime = Time.time;
            
            foreach (var kvp in nodes)
            {
                ResourceNode node = kvp.Value;
                
                // 只考虑可以被卸载的资源(没有依赖者或依赖者也可以被卸载)
                if (CanResourceBeUnloaded(node.ResourceId))
                {
                    node.CalculateImportanceScore(currentTime);
                    candidateNodes.Add(node);
                }
            }
            
            // 按重要性分数升序排序(最不重要的先卸载)
            candidateNodes.Sort((a, b) => 
                a.CalculateImportanceScore(currentTime).CompareTo(
                b.CalculateImportanceScore(currentTime)));
            
            // 使用0/1背包问题的变体选择要卸载的资源
            return SolveKnapsackProblem(candidateNodes, targetMemoryReduction);
        }
        
        private bool CanResourceBeUnloaded(string resourceId)
        {
            // 检查资源是否可以被卸载
            // 这里可以添加业务逻辑,如:关键资源不能卸载
            return true;
        }
        
        private List<string> SolveKnapsackProblem(List<ResourceNode> candidates, int targetMemory)
        {
            int n = candidates.Count;
            
            // 动态规划表:dp[i, w] = 前i个物品,容量为w时的最大价值(这里价值是重要性分数的倒数)
            float[,] dp = new float[n + 1, targetMemory + 1];
            
            for (int i = 1; i <= n; i++)
            {
                ResourceNode node = candidates[i - 1];
                int weight = node.MemorySize;
                float value = 1.0f / (node.CalculateImportanceScore(Time.time) + 0.001f); // 避免除零
                
                for (int w = 0; w <= targetMemory; w++)
                {
                    if (weight <= w)
                    {
                        dp[i, w] = Mathf.Max(dp[i - 1, w], dp[i - 1, w - weight] + value);
                    }
                    else
                    {
                        dp[i, w] = dp[i - 1, w];
                    }
                }
            }
            
            // 回溯找到选择的物品
            List<string> selectedResources = new List<string>();
            int remainingCapacity = targetMemory;
            
            for (int i = n; i > 0 && remainingCapacity > 0; i--)
            {
                if (dp[i, remainingCapacity] != dp[i - 1, remainingCapacity])
                {
                    ResourceNode node = candidates[i - 1];
                    selectedResources.Add(node.ResourceId);
                    remainingCapacity -= node.MemorySize;
                }
            }
            
            return selectedResources;
        }
        
        // 查找资源使用的最短路径(用于调试和优化)
        public List<string> FindShortestResourcePath(string startResource, string endResource)
        {
            if (!nodes.ContainsKey(startResource) || !nodes.ContainsKey(endResource))
            {
                return new List<string>();
            }
            
            // 使用BFS查找最短路径
            Dictionary<string, string> predecessor = new Dictionary<string, string>();
            Queue<string> queue = new Queue<string>();
            HashSet<string> visited = new HashSet<string>();
            
            queue.Enqueue(startResource);
            visited.Add(startResource);
            
            while (queue.Count > 0)
            {
                string current = queue.Dequeue();
                
                if (current == endResource)
                {
                    // 重建路径
                    return ReconstructPath(predecessor, startResource, endResource);
                }
                
                if (adjacencyList.ContainsKey(current))
                {
                    foreach (string neighbor in adjacencyList[current])
                    {
                        if (!visited.Contains(neighbor))
                        {
                            visited.Add(neighbor);
                            predecessor[neighbor] = current;
                            queue.Enqueue(neighbor);
                        }
                    }
                }
            }
            
            return new List<string>(); // 没有路径
        }
        
        private List<string> ReconstructPath(Dictionary<string, string> predecessor, 
            string start, string end)
        {
            List<string> path = new List<string>();
            string current = end;
            
            while (current != start)
            {
                path.Add(current);
                current = predecessor[current];
            }
            
            path.Add(start);
            path.Reverse();
            
            return path;
        }
        
        // 获取图形统计信息
        public string GetGraphStatistics()
        {
            int totalNodes = nodes.Count;
            int totalEdges = adjacencyList.Sum(kvp => kvp.Value.Count);
            
            // 计算平均度
            float averageDegree = totalEdges / (float)totalNodes;
            
            // 找到最依赖的资源
            string mostDependentResource = "";
            int maxDependencies = 0;
            
            foreach (var kvp in nodes)
            {
                if (kvp.Value.Dependencies.Count > maxDependencies)
                {
                    maxDependencies = kvp.Value.Dependencies.Count;
                    mostDependentResource = kvp.Key;
                }
            }
            
            // 找到最被依赖的资源
            string mostReferencedResource = "";
            int maxReferences = 0;
            
            foreach (var kvp in nodes)
            {
                if (kvp.Value.Dependents.Count > maxReferences)
                {
                    maxReferences = kvp.Value.Dependents.Count;
                    mostReferencedResource = kvp.Key;
                }
            }
            
            return $@"资源依赖图统计:
总资源数:{totalNodes}
总依赖关系:{totalEdges}
平均依赖数:{averageDegree:F2}
最依赖其他资源的资源:{mostDependentResource} ({maxDependencies}个依赖)
最被依赖的资源:{mostReferencedResource} ({maxReferences}个被依赖)";
        }
    }
    
    // 智能资源管理器
    public class IntelligentResourceManager : MonoBehaviour
    {
        private ResourceDependencyGraph dependencyGraph;
        private Dictionary<string, UnityEngine.Object> loadedResources;
        
        [Header("Memory Management")]
        public int MemoryWarningThresholdMB = 1024; // 1GB
        public int MemoryCriticalThresholdMB = 1536; // 1.5GB
        public float CleanupCheckInterval = 30f; // 每30秒检查一次
        
        private void Start()
        {
            dependencyGraph = new ResourceDependencyGraph();
            loadedResources = new Dictionary<string, UnityEngine.Object>();
            
            // 开始内存监控
            StartCoroutine(MemoryCleanupMonitor());
            
            // 示例:初始化一些测试资源
            InitializeTestResources();
        }
        
        private void InitializeTestResources()
        {
            // 这里添加一些测试资源及其依赖关系
            // 在实际项目中,这些信息应该从AssetBundle清单中加载
            
            AddResource("CharacterModel", null, 5000); // 5MB
            AddResource("CharacterTexture", null, 2000); // 2MB
            AddResource("CharacterAnimation", null, 3000); // 3MB
            
            AddDependency("CharacterModel", "CharacterTexture");
            AddDependency("CharacterAnimation", "CharacterModel");
            
            AddResource("Environment", null, 10000); // 10MB
            AddResource("EnvironmentTexture", null, 5000); // 5MB
            AddResource("EnvironmentLightmap", null, 8000); // 8MB
            
            AddDependency("Environment", "EnvironmentTexture");
            AddDependency("Environment", "EnvironmentLightmap");
        }
        
        public void AddResource(string resourceId, UnityEngine.Object resource, int sizeKB)
        {
            dependencyGraph.AddResource(resourceId, resource, sizeKB);
            
            if (resource != null)
            {
                loadedResources[resourceId] = resource;
            }
        }
        
        public void AddDependency(string dependent, string dependency)
        {
            dependencyGraph.AddDependency(dependent, dependency);
        }
        
        public void LoadResource(string resourceId)
        {
            // 实际加载资源的逻辑
            dependencyGraph.RecordResourceAccess(resourceId);
            
            // 确保所有依赖资源也被加载
            List<string> loadOrder = dependencyGraph.GetTopologicalLoadOrder();
            foreach (string depResourceId in loadOrder)
            {
                if (!loadedResources.ContainsKey(depResourceId))
                {
                    // 加载依赖资源
                    Debug.Log($"加载依赖资源:{depResourceId}");
                }
            }
        }
        
        private System.Collections.IEnumerator MemoryCleanupMonitor()
        {
            while (true)
            {
                yield return new WaitForSeconds(CleanupCheckInterval);
                
                float usedMemoryMB = UnityEngine.Profiling.Profiler.GetTotalAllocatedMemoryLong() / (1024f * 1024f);
                
                if (usedMemoryMB > MemoryCriticalThresholdMB)
                {
                    Debug.LogError($"内存使用严重:{usedMemoryMB:F0}MB,执行紧急清理");
                    PerformEmergencyCleanup();
                }
                else if (usedMemoryMB > MemoryWarningThresholdMB)
                {
                    Debug.LogWarning($"内存使用警告:{usedMemoryMB:F0}MB,执行预防性清理");
                    PerformPreventiveCleanup();
                }
            }
        }
        
        private void PerformEmergencyCleanup()
        {
            // 需要减少的内存(MB转换为KB)
            int targetReductionKB = (int)((MemoryCriticalThresholdMB - MemoryWarningThresholdMB) * 1024);
            
            List<string> candidates = dependencyGraph.FindBestUnloadCandidates(targetReductionKB);
            
            foreach (string resourceId in candidates)
            {
                UnloadResource(resourceId);
            }
            
            // 强制垃圾回收
            Resources.UnloadUnusedAssets();
            System.GC.Collect();
        }
        
        private void PerformPreventiveCleanup()
        {
            // 需要减少的内存(MB转换为KB)
            int targetReductionKB = (int)((MemoryWarningThresholdMB * 0.9f) * 1024);
            
            List<string> candidates = dependencyGraph.FindBestUnloadCandidates(targetReductionKB);
            
            foreach (string resourceId in candidates)
            {
                UnloadResource(resourceId);
            }
        }
        
        public void UnloadResource(string resourceId)
        {
            if (loadedResources.ContainsKey(resourceId))
            {
                // 获取所有需要一起卸载的资源
                List<string> resourcesToUnload = dependencyGraph.GetResourcesToUnload(resourceId);
                
                foreach (string resId in resourcesToUnload)
                {
                    if (loadedResources.ContainsKey(resId))
                    {
                        // 实际卸载资源的逻辑
                        Debug.Log($"卸载资源:{resId}");
                        
                        // 如果是UnityEngine.Object,可以使用Resources.UnloadAsset
                        // 或者Destroy,取决于资源类型
                        
                        loadedResources.Remove(resId);
                    }
                }
            }
        }
        
        // 调试和监控功能
        private void OnGUI()
        {
            #if UNITY_EDITOR || DEVELOPMENT_BUILD
            if (GUI.Button(new Rect(10, 10, 200, 30), "显示资源图统计"))
            {
                string stats = dependencyGraph.GetGraphStatistics();
                Debug.Log(stats);
            }
            
            if (GUI.Button(new Rect(10, 50, 200, 30), "显示加载顺序"))
            {
                List<string> loadOrder = dependencyGraph.GetTopologicalLoadOrder();
                string order = "资源加载顺序:\n" + string.Join("\n", loadOrder);
                Debug.Log(order);
            }
            
            // 显示当前内存使用
            float usedMemoryMB = UnityEngine.Profiling.Profiler.GetTotalAllocatedMemoryLong() / (1024f * 1024f);
            GUI.Label(new Rect(10, 90, 300, 30), $"内存使用:{usedMemoryMB:F1}MB");
            
            // 内存压力指示器
            Rect memoryBar = new Rect(10, 130, 200, 20);
            GUI.Box(memoryBar, "");
            
            float memoryRatio = usedMemoryMB / MemoryCriticalThresholdMB;
            memoryRatio = Mathf.Clamp01(memoryRatio);
            
            Color barColor = Color.green;
            if (memoryRatio > 0.7f) barColor = Color.yellow;
            if (memoryRatio > 0.9f) barColor = Color.red;
            
            GUI.color = barColor;
            GUI.Box(new Rect(memoryBar.x, memoryBar.y, memoryBar.width * memoryRatio, memoryBar.height), "");
            GUI.color = Color.white;
            #endif
        }
    }
}

以上内容涵盖了Unity3D游戏开发中数学应用的多个方面,包括场景加载优化、游戏对象分布、性能分析预测以及资源依赖管理。每个部分都包含了详细的理论说明、数学模型和可运行的C#代码实例,代码风格符合Allman规范,命名符合驼峰命名法,适合在Unity 2021.3.8f1c1和VS2022/VSCode中运行。这些实现都考虑了商业项目的实际需求,提供了实用的优化策略和算法。

Logo

这里是一个专注于游戏开发的社区,我们致力于为广大游戏爱好者提供一个良好的学习和交流平台。我们的专区包含了各大流行引擎的技术博文,涵盖了从入门到进阶的各个阶段,无论你是初学者还是资深开发者,都能在这里找到适合自己的内容。除此之外,我们还会不定期举办游戏开发相关的活动,让大家更好地交流互动。加入我们,一起探索游戏开发的奥秘吧!

更多推荐