第9章 汽车工业混合现实展示系统深度开发实战

9.1 工业级汽车展示系统架构设计与商业价值分析

在汽车工业领域,混合现实展示系统已经超越了简单的产品展示功能,成为集营销、培训、设计和售后支持于一体的综合性解决方案。工业级汽车展示系统需要处理高精度三维模型、实时物理交互、多用户协同以及与企业数据系统的深度集成。

以下是一个工业级汽车展示系统的整体架构设计:

using System;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.Toolkit;
using Microsoft.MixedReality.Toolkit.Input;

namespace AutomotiveIndustryMR
{
    /// <summary>
    /// 工业级汽车展示系统主控制器
    /// 负责协调所有子系统,管理应用状态和企业级功能
    /// </summary>
    public class IndustrialCarPresentationSystem : MonoBehaviour
    {
        [System.Serializable]
        public class SystemConfiguration
        {
            public string SystemId;
            public string EnterpriseLicenseKey;
            public bool EnableMultiUserMode;
            public bool EnableAnalyticsTracking;
            public bool EnableRemoteAssistance;
            public int MaxConcurrentUsers = 5;
            public DataSyncMode DataSyncMode;
            public PresentationMode DefaultMode;
        }

        public enum DataSyncMode
        {
            RealTime,
            OnDemand,
            Batch
        }

        public enum PresentationMode
        {
            MarketingDemo,
            TechnicalTraining,
            DesignReview,
            MaintenanceGuide,
            CustomizationStudio
        }

        private SystemConfiguration currentConfig;
        private PresentationMode currentMode;
        private Dictionary<string, CarModelData> loadedModels;
        private List<UserSession> activeSessions;
        private EnterpriseDataConnector dataConnector;
        private SystemPerformanceMonitor performanceMonitor;
        private SecurityManager securityManager;

        private CarModelController currentCarModel;
        private VisualizationManager visualizationManager;
        private InteractionSystem interactionSystem;
        private CollaborationManager collaborationManager;

        private float systemUptime;
        private DateTime systemStartTime;
        private int totalInteractions;
        private float averageSessionDuration;

        private void Awake()
        {
            InitializeEnterpriseSystem();
            LoadSystemConfiguration();
            InitializeSubsystems();
            StartPerformanceMonitoring();
            ConnectToEnterpriseServices();
        }

        private void InitializeEnterpriseSystem()
        {
            // 初始化企业级系统组件
            DontDestroyOnLoad(gameObject);
            
            systemStartTime = DateTime.Now;
            
            // 创建企业级数据连接器
            dataConnector = gameObject.AddComponent<EnterpriseDataConnector>();
            
            // 初始化安全管理器
            securityManager = gameObject.AddComponent<SecurityManager>();
            securityManager.Initialize(OnSecurityEvent);
            
            // 设置企业级日志系统
            ConfigureEnterpriseLogging();
        }

        private void LoadSystemConfiguration()
        {
            // 从企业配置服务器加载系统配置
            string configJson = EnterpriseConfigService.LoadConfiguration("AutomotiveMRSystem");
            
            if (!string.IsNullOrEmpty(configJson))
            {
                currentConfig = JsonUtility.FromJson<SystemConfiguration>(configJson);
            }
            else
            {
                // 使用默认配置
                currentConfig = CreateDefaultConfiguration();
            }
            
            currentMode = currentConfig.DefaultMode;
            
            // 验证企业许可证
            ValidateEnterpriseLicense();
        }

        private SystemConfiguration CreateDefaultConfiguration()
        {
            return new SystemConfiguration
            {
                SystemId = GenerateSystemId(),
                EnterpriseLicenseKey = "EVAL-2024-001",
                EnableMultiUserMode = true,
                EnableAnalyticsTracking = true,
                EnableRemoteAssistance = true,
                MaxConcurrentUsers = 5,
                DataSyncMode = DataSyncMode.RealTime,
                DefaultMode = PresentationMode.MarketingDemo
            };
        }

        private void InitializeSubsystems()
        {
            // 初始化汽车模型控制器
            currentCarModel = gameObject.AddComponent<CarModelController>();
            currentCarModel.OnModelLoaded += OnCarModelLoaded;
            currentCarModel.OnModelError += OnModelError;
            
            // 初始化可视化管理器
            visualizationManager = gameObject.AddComponent<VisualizationManager>();
            visualizationManager.Initialize(currentConfig);
            
            // 初始化交互系统
            interactionSystem = gameObject.AddComponent<InteractionSystem>();
            interactionSystem.Initialize(this);
            
            // 初始化协作管理器(如果启用多用户模式)
            if (currentConfig.EnableMultiUserMode)
            {
                collaborationManager = gameObject.AddComponent<CollaborationManager>();
                collaborationManager.Initialize(currentConfig.MaxConcurrentUsers);
            }
            
            // 初始化分析系统
            if (currentConfig.EnableAnalyticsTracking)
            {
                InitializeAnalyticsSystem();
            }
        }

        private void StartPerformanceMonitoring()
        {
            performanceMonitor = gameObject.AddComponent<SystemPerformanceMonitor>();
            performanceMonitor.StartMonitoring(OnPerformanceAlert);
            
            // 定期报告系统状态
            InvokeRepeating("ReportSystemStatus", 60f, 300f); // 每5分钟报告一次
        }

        private void ConnectToEnterpriseServices()
        {
            // 连接企业数据服务
            StartCoroutine(dataConnector.ConnectToEnterpriseServices(
                OnDataConnected,
                OnDataConnectionFailed
            ));
            
            // 加载汽车模型目录
            LoadCarModelCatalog();
        }

        /// <summary>
        /// 加载汽车模型目录
        /// 从企业服务器获取可用的汽车模型列表
        /// </summary>
        private void LoadCarModelCatalog()
        {
            StartCoroutine(dataConnector.LoadCarModelCatalog(
                OnCatalogLoaded,
                OnCatalogLoadFailed
            ));
        }

        private void OnCatalogLoaded(List<CarModelCatalogItem> catalog)
        {
            loadedModels = new Dictionary<string, CarModelData>();
            
            foreach (var item in catalog)
            {
                // 预加载模型元数据
                loadedModels[item.ModelId] = new CarModelData
                {
                    ModelId = item.ModelId,
                    ModelName = item.ModelName,
                    Manufacturer = item.Manufacturer,
                    Year = item.Year,
                    BasePrice = item.BasePrice,
                    AvailableColors = item.AvailableColors,
                    AvailableFeatures = item.AvailableFeatures,
                    ModelPath = item.ModelPath,
                    ModelSizeMB = item.ModelSizeMB,
                    LastUpdated = item.LastUpdated
                };
            }
            
            Debug.Log($"Loaded {catalog.Count} car models from enterprise catalog");
            
            // 触发UI更新
            UIManager.Instance.UpdateCarModelCatalog(catalog);
        }

        /// <summary>
        /// 加载指定的汽车模型
        /// </summary>
        public void LoadCarModel(string modelId, Action<CarModelController> onComplete = null)
        {
            if (!loadedModels.ContainsKey(modelId))
            {
                Debug.LogError($"Car model {modelId} not found in catalog");
                return;
            }
            
            CarModelData modelData = loadedModels[modelId];
            
            // 记录分析事件
            AnalyticsService.RecordEvent("CarModelLoadRequested", new
            {
                ModelId = modelId,
                ModelName = modelData.ModelName,
                Timestamp = DateTime.UtcNow,
                UserId = UserSession.Current.UserId
            });
            
            // 加载模型
            StartCoroutine(currentCarModel.LoadModel(
                modelData,
                (success) =>
                {
                    if (success)
                    {
                        OnCarModelLoadedSuccess(modelData);
                        onComplete?.Invoke(currentCarModel);
                    }
                }
            ));
        }

        private void OnCarModelLoadedSuccess(CarModelData modelData)
        {
            // 应用当前演示模式配置
            ConfigureForPresentationMode(currentMode);
            
            // 初始化交互功能
            interactionSystem.InitializeModelInteractions(currentCarModel);
            
            // 通知协作系统(如果启用)
            if (collaborationManager != null)
            {
                collaborationManager.OnModelLoaded(currentCarModel, modelData);
            }
            
            // 记录成功加载
            EnterpriseLoggingService.LogModelLoad(
                modelData.ModelId,
                UserSession.Current.UserId,
                true,
                null
            );
        }

        /// <summary>
        /// 切换演示模式
        /// </summary>
        public void SwitchPresentationMode(PresentationMode newMode)
        {
            PresentationMode previousMode = currentMode;
            currentMode = newMode;
            
            // 重新配置系统
            ConfigureForPresentationMode(newMode);
            
            // 记录模式切换
            AnalyticsService.RecordEvent("PresentationModeChanged", new
            {
                PreviousMode = previousMode.ToString(),
                NewMode = newMode.ToString(),
                Timestamp = DateTime.UtcNow,
                CarModelId = currentCarModel?.CurrentModelId
            });
            
            // 通知UI更新
            UIManager.Instance.OnPresentationModeChanged(previousMode, newMode);
        }

        private void ConfigureForPresentationMode(PresentationMode mode)
        {
            if (currentCarModel == null) return;
            
            switch (mode)
            {
                case PresentationMode.MarketingDemo:
                    ConfigureMarketingDemoMode();
                    break;
                    
                case PresentationMode.TechnicalTraining:
                    ConfigureTechnicalTrainingMode();
                    break;
                    
                case PresentationMode.DesignReview:
                    ConfigureDesignReviewMode();
                    break;
                    
                case PresentationMode.MaintenanceGuide:
                    ConfigureMaintenanceGuideMode();
                    break;
                    
                case PresentationMode.CustomizationStudio:
                    ConfigureCustomizationStudioMode();
                    break;
            }
        }

        private void ConfigureMarketingDemoMode()
        {
            // 营销演示模式:高视觉质量,简化交互
            visualizationManager.SetVisualQuality(VisualQuality.High);
            visualizationManager.EnableSpecialEffects(true);
            
            interactionSystem.EnableBasicInteractions(true);
            interactionSystem.EnableAdvancedInteractions(false);
            interactionSystem.SetInteractionSpeed(1.0f);
            
            currentCarModel.ConfigureForMarketing();
            
            // 显示营销信息叠加层
            UIManager.Instance.ShowMarketingOverlay(true);
        }

        private void ConfigureTechnicalTrainingMode()
        {
            // 技术培训模式:详细标注,分步指导
            visualizationManager.SetVisualQuality(VisualQuality.Medium);
            visualizationManager.EnableSpecialEffects(false);
            
            interactionSystem.EnableBasicInteractions(true);
            interactionSystem.EnableAdvancedInteractions(true);
            interactionSystem.SetInteractionSpeed(0.7f);
            
            currentCarModel.ConfigureForTraining();
            
            // 显示技术文档和标注
            UIManager.Instance.ShowTechnicalAnnotations(true);
        }

        /// <summary>
        /// 启动远程协助会话
        /// </summary>
        public void StartRemoteAssistanceSession(string expertId)
        {
            if (!currentConfig.EnableRemoteAssistance)
            {
                Debug.LogWarning("Remote assistance is not enabled in current configuration");
                return;
            }
            
            RemoteAssistanceSession session = new RemoteAssistanceSession
            {
                SessionId = Guid.NewGuid().ToString(),
                UserId = UserSession.Current.UserId,
                ExpertId = expertId,
                CarModelId = currentCarModel?.CurrentModelId,
                StartTime = DateTime.UtcNow,
                Status = SessionStatus.Connecting
            };
            
            StartCoroutine(RemoteAssistanceService.StartSession(
                session,
                OnRemoteAssistanceConnected,
                OnRemoteAssistanceFailed
            ));
        }

        private void OnRemoteAssistanceConnected(RemoteAssistanceSession session)
        {
            // 启用协作功能
            if (collaborationManager != null)
            {
                collaborationManager.EnableRemoteControl(true);
                collaborationManager.SetExpertUser(session.ExpertId);
            }
            
            // 通知用户
            UIManager.Instance.ShowNotification(
                $"Connected to expert: {session.ExpertId}",
                NotificationType.Success,
                3f
            );
            
            // 记录会话开始
            AnalyticsService.RecordEvent("RemoteAssistanceStarted", new
            {
                SessionId = session.SessionId,
                ExpertId = session.ExpertId,
                Timestamp = DateTime.UtcNow
            });
        }

        /// <summary>
        /// 导出当前配置为报价单
        /// </summary>
        public void ExportCurrentConfigurationAsQuote()
        {
            if (currentCarModel == null)
            {
                Debug.LogWarning("No car model loaded");
                return;
            }
            
            CarConfiguration config = currentCarModel.GetCurrentConfiguration();
            CustomerQuote quote = new CustomerQuote
            {
                QuoteId = GenerateQuoteId(),
                CustomerId = UserSession.Current.UserId,
                CarModelId = config.ModelId,
                BasePrice = config.BasePrice,
                SelectedOptions = config.SelectedOptions,
                TotalPrice = config.CalculateTotalPrice(),
                CreatedDate = DateTime.UtcNow,
                ValidUntil = DateTime.UtcNow.AddDays(30)
            };
            
            // 生成PDF报价单
            StartCoroutine(QuoteGenerator.GeneratePDFQuote(
                quote,
                OnQuoteGenerated,
                OnQuoteGenerationFailed
            ));
        }

        private void OnQuoteGenerated(byte[] pdfData)
        {
            // 保存到本地
            string filePath = Path.Combine(
                Application.persistentDataPath,
                $"Quote_{DateTime.Now:yyyyMMdd_HHmmss}.pdf"
            );
            
            File.WriteAllBytes(filePath, pdfData);
            
            // 上传到企业CRM系统
            StartCoroutine(CRMIntegrationService.UploadQuote(
                pdfData,
                OnQuoteUploaded,
                OnQuoteUploadFailed
            ));
            
            // 显示成功消息
            UIManager.Instance.ShowNotification(
                "Quote generated and saved successfully",
                NotificationType.Success,
                3f
            );
        }

        /// <summary>
        /// 生成系统性能报告
        /// </summary>
        public SystemPerformanceReport GeneratePerformanceReport()
        {
            systemUptime = (float)(DateTime.Now - systemStartTime).TotalHours;
            
            return new SystemPerformanceReport
            {
                ReportId = Guid.NewGuid().ToString(),
                GenerationTime = DateTime.Now,
                SystemUptimeHours = systemUptime,
                TotalSessions = UserSessionManager.TotalSessions,
                AverageSessionDuration = averageSessionDuration,
                TotalInteractions = totalInteractions,
                PerformanceMetrics = performanceMonitor.GetCurrentMetrics(),
                LoadedModelsCount = loadedModels?.Count ?? 0,
                ActiveSessionsCount = activeSessions?.Count ?? 0,
                SystemConfiguration = currentConfig
            };
        }

        private void ReportSystemStatus()
        {
            SystemPerformanceReport report = GeneratePerformanceReport();
            
            // 发送到监控服务器
            StartCoroutine(MonitoringService.ReportSystemStatus(
                report,
                OnStatusReported,
                OnStatusReportFailed
            ));
        }

        private void OnDestroy()
        {
            // 清理资源
            if (currentCarModel != null)
            {
                currentCarModel.Cleanup();
            }
            
            if (performanceMonitor != null)
            {
                performanceMonitor.StopMonitoring();
            }
            
            // 报告系统关闭
            ReportSystemShutdown();
        }

        private void ReportSystemShutdown()
        {
            SystemShutdownReport report = new SystemShutdownReport
            {
                ShutdownTime = DateTime.Now,
                TotalUptimeHours = systemUptime,
                FinalPerformanceMetrics = performanceMonitor?.GetCurrentMetrics(),
                Reason = "NormalShutdown"
            };
            
            // 异步发送关闭报告
            StartCoroutine(MonitoringService.ReportSystemShutdown(report));
        }
    }

    /// <summary>
    /// 汽车模型数据类
    /// </summary>
    [System.Serializable]
    public class CarModelData
    {
        public string ModelId;
        public string ModelName;
        public string Manufacturer;
        public int Year;
        public decimal BasePrice;
        public List<CarColor> AvailableColors;
        public List<CarFeature> AvailableFeatures;
        public string ModelPath;
        public float ModelSizeMB;
        public DateTime LastUpdated;
        public Dictionary<string, object> TechnicalSpecifications;
        public List<CarComponent> Components;
    }

    /// <summary>
    /// 汽车颜色配置
    /// </summary>
    [System.Serializable]
    public class CarColor
    {
        public string ColorId;
        public string ColorName;
        public Color UnityColor;
        public string PaintMaterialId;
        public decimal PricePremium;
        public bool IsMetallic;
        public bool IsPearlescent;
        public List<string> AvailableForModels;
    }

    /// <summary>
    /// 汽车功能特性
    /// </summary>
    [System.Serializable]
    public class CarFeature
    {
        public string FeatureId;
        public string FeatureName;
        public FeatureCategory Category;
        public decimal Price;
        public bool IsStandard;
        public List<string> IncompatibleFeatures;
        public GameObject FeaturePrefab;
        public string Description;
        public List<string> TechnicalDetails;
    }

    public enum FeatureCategory
    {
        Exterior,
        Interior,
        Performance,
        Safety,
        Technology,
        Comfort
    }

    /// <summary>
    /// 汽车组件定义
    /// </summary>
    [System.Serializable]
    public class CarComponent
    {
        public string ComponentId;
        public string ComponentName;
        public ComponentType Type;
        public GameObject ModelPrefab;
        public Vector3 DefaultPosition;
        public Quaternion DefaultRotation;
        public bool IsRemovable;
        public bool IsInteractable;
        public List<ComponentAttachmentPoint> AttachmentPoints;
        public TechnicalSpecification Specifications;
    }

    public enum ComponentType
    {
        Engine,
        Transmission,
        Suspension,
        Brakes,
        Wheels,
        BodyPanel,
        InteriorPanel,
        ElectronicModule,
        Lighting,
        Other
    }
}

9.2 工业级工程架构与资源管理系统

工业级汽车展示项目需要管理大量高精度资源,包括汽车模型、材质、音频、视频以及配置数据。以下是资源管理系统的实现:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;

namespace AutomotiveIndustryMR
{
    /// <summary>
    /// 工业级资源管理器
    /// 负责加载、缓存和管理所有项目资源
    /// </summary>
    public class IndustrialResourceManager : MonoBehaviour
    {
        [System.Serializable]
        public class ResourceCatalog
        {
            public string CatalogVersion;
            public DateTime LastUpdated;
            public List<ModelResource> CarModels;
            public List<MaterialResource> Materials;
            public List<TextureResource> Textures;
            public List<AudioResource> AudioClips;
            public List<VideoResource> Videos;
            public List<PrefabResource> Prefabs;
            public List<ConfigurationResource> Configurations;
        }

        [System.Serializable]
        public class ModelResource
        {
            public string ResourceId;
            public string ModelName;
            public string FilePath;
            public long FileSizeBytes;
            public string Checksum;
            public DateTime LastModified;
            public List<string> Dependencies;
            public ModelLoadSettings LoadSettings;
            public Dictionary<string, string> Metadata;
        }

        [System.Serializable]
        public class ModelLoadSettings
        {
            public bool LoadMaterials = true;
            public bool LoadAnimations = true;
            public bool LoadColliders = true;
            public float ScaleFactor = 1.0f;
            public bool GenerateLightmapUVs = false;
            public int MaxLODLevel = 3;
            public bool OptimizeMesh = true;
        }

        private ResourceCatalog currentCatalog;
        private Dictionary<string, ResourceCacheEntry> resourceCache;
        private Dictionary<string, GameObject> instantiatedModels;
        private Dictionary<string, Material> materialCache;
        private Dictionary<string, AudioClip> audioCache;
        private Dictionary<string, Texture2D> textureCache;

        private string cacheDirectory;
        private long maxCacheSizeBytes = 1024L * 1024L * 1024L * 2; // 2GB
        private long currentCacheSizeBytes = 0;
        private bool isInitialized = false;

        private List<ResourceLoadRequest> pendingRequests;
        private List<ResourceLoadRequest> activeRequests;
        private int maxConcurrentLoads = 3;

        private void Awake()
        {
            DontDestroyOnLoad(gameObject);
            
            InitializeCache();
            LoadResourceCatalog();
            StartCacheMaintenance();
        }

        private void InitializeCache()
        {
            cacheDirectory = Path.Combine(Application.persistentDataPath, "ResourceCache");
            
            if (!Directory.Exists(cacheDirectory))
            {
                Directory.CreateDirectory(cacheDirectory);
            }
            
            resourceCache = new Dictionary<string, ResourceCacheEntry>();
            instantiatedModels = new Dictionary<string, GameObject>();
            materialCache = new Dictionary<string, Material>();
            audioCache = new Dictionary<string, AudioClip>();
            textureCache = new Dictionary<string, Texture2D>();
            
            pendingRequests = new List<ResourceLoadRequest>();
            activeRequests = new List<ResourceLoadRequest>();
            
            // 加载现有缓存索引
            LoadCacheIndex();
        }

        private void LoadCacheIndex()
        {
            string indexFile = Path.Combine(cacheDirectory, "CacheIndex.json");
            
            if (File.Exists(indexFile))
            {
                try
                {
                    string json = File.ReadAllText(indexFile);
                    CacheIndex index = JsonUtility.FromJson<CacheIndex>(json);
                    
                    currentCacheSizeBytes = index.TotalSizeBytes;
                    
                    foreach (var entry in index.Entries)
                    {
                        resourceCache[entry.ResourceId] = entry;
                        
                        // 验证缓存文件是否存在
                        string cachedPath = GetCachedPath(entry.ResourceId);
                        if (!File.Exists(cachedPath))
                        {
                            resourceCache.Remove(entry.ResourceId);
                            currentCacheSizeBytes -= entry.SizeBytes;
                        }
                    }
                    
                    Debug.Log($"Loaded cache index with {resourceCache.Count} entries, total size: {FormatBytes(currentCacheSizeBytes)}");
                }
                catch (Exception ex)
                {
                    Debug.LogError($"Failed to load cache index: {ex.Message}");
                }
            }
        }

        private async void LoadResourceCatalog()
        {
            try
            {
                // 首先尝试从本地加载
                string localCatalogPath = Path.Combine(cacheDirectory, "ResourceCatalog.json");
                
                if (File.Exists(localCatalogPath))
                {
                    string localJson = await File.ReadAllTextAsync(localCatalogPath);
                    currentCatalog = JsonUtility.FromJson<ResourceCatalog>(localJson);
                    
                    // 检查是否需要更新
                    if (await CheckCatalogUpdateNeeded())
                    {
                        await DownloadUpdatedCatalog();
                    }
                }
                else
                {
                    await DownloadUpdatedCatalog();
                }
                
                isInitialized = true;
                OnCatalogLoaded?.Invoke(true);
            }
            catch (Exception ex)
            {
                Debug.LogError($"Failed to load resource catalog: {ex.Message}");
                OnCatalogLoaded?.Invoke(false);
            }
        }

        private async Task<bool> CheckCatalogUpdateNeeded()
        {
            if (currentCatalog == null) return true;
            
            try
            {
                string serverCatalogUrl = EnterpriseConfigService.GetResourceCatalogUrl();
                
                using (UnityWebRequest request = UnityWebRequest.Get(serverCatalogUrl))
                {
                    request.timeout = 10;
                    var operation = request.SendWebRequest();
                    
                    while (!operation.isDone)
                    {
                        await Task.Yield();
                    }
                    
                    if (request.result == UnityWebRequest.Result.Success)
                    {
                        string serverJson = request.downloadHandler.text;
                        ResourceCatalog serverCatalog = JsonUtility.FromJson<ResourceCatalog>(serverJson);
                        
                        return serverCatalog.LastUpdated > currentCatalog.LastUpdated;
                    }
                }
            }
            catch
            {
                // 网络错误时使用本地目录
            }
            
            return false;
        }

        /// <summary>
        /// 异步加载汽车模型
        /// </summary>
        public async Task<GameObject> LoadCarModelAsync(string modelId, Action<float> progressCallback = null)
        {
            if (!isInitialized)
            {
                throw new InvalidOperationException("Resource manager not initialized");
            }
            
            // 检查是否已实例化
            if (instantiatedModels.ContainsKey(modelId))
            {
                return instantiatedModels[modelId];
            }
            
            // 查找模型资源
            ModelResource modelResource = currentCatalog.CarModels.FirstOrDefault(m => m.ResourceId == modelId);
            
            if (modelResource == null)
            {
                throw new ArgumentException($"Model resource not found: {modelId}");
            }
            
            // 创建加载请求
            var request = new ResourceLoadRequest
            {
                ResourceId = modelId,
                ResourceType = ResourceType.Model,
                Priority = LoadPriority.High,
                ProgressCallback = progressCallback
            };
            
            // 添加到待处理队列
            pendingRequests.Add(request);
            
            // 等待请求完成
            await request.CompletionTask;
            
            if (!request.IsSuccessful)
            {
                throw new Exception($"Failed to load model {modelId}: {request.ErrorMessage}");
            }
            
            // 实例化模型
            GameObject modelInstance = Instantiate(request.LoadedObject as GameObject);
            instantiatedModels[modelId] = modelInstance;
            
            // 应用加载设置
            ApplyModelLoadSettings(modelInstance, modelResource.LoadSettings);
            
            return modelInstance;
        }

        private async Task ProcessLoadRequest(ResourceLoadRequest request)
        {
            try
            {
                // 检查缓存
                string cachedPath = GetCachedPath(request.ResourceId);
                
                if (File.Exists(cachedPath) && resourceCache.ContainsKey(request.ResourceId))
                {
                    // 从缓存加载
                    await LoadFromCache(request, cachedPath);
                }
                else
                {
                    // 从服务器下载
                    await DownloadAndCacheResource(request);
                }
                
                request.IsSuccessful = true;
                request.CompletionSource.SetResult(true);
            }
            catch (Exception ex)
            {
                request.IsSuccessful = false;
                request.ErrorMessage = ex.Message;
                request.CompletionSource.SetException(ex);
            }
            finally
            {
                activeRequests.Remove(request);
                ProcessNextRequest();
            }
        }

        private async Task DownloadAndCacheResource(ResourceLoadRequest request)
        {
            // 获取资源URL
            string downloadUrl = GetResourceDownloadUrl(request.ResourceId, request.ResourceType);
            
            // 创建临时文件路径
            string tempPath = Path.Combine(cacheDirectory, $"temp_{Guid.NewGuid()}");
            
            try
            {
                using (UnityWebRequest webRequest = UnityWebRequest.Get(downloadUrl))
                {
                    // 设置下载处理器
                    var downloadHandler = new DownloadHandlerFile(tempPath);
                    webRequest.downloadHandler = downloadHandler;
                    
                    // 发送请求
                    var operation = webRequest.SendWebRequest();
                    
                    // 更新进度
                    while (!operation.isDone)
                    {
                        await Task.Yield();
                        request.ProgressCallback?.Invoke(webRequest.downloadProgress);
                    }
                    
                    if (webRequest.result != UnityWebRequest.Result.Success)
                    {
                        throw new Exception($"Download failed: {webRequest.error}");
                    }
                    
                    // 验证文件
                    FileInfo fileInfo = new FileInfo(tempPath);
                    
                    if (fileInfo.Length == 0)
                    {
                        throw new Exception("Downloaded file is empty");
                    }
                    
                    // 计算校验和
                    string checksum = CalculateFileChecksum(tempPath);
                    
                    // 验证校验和(如果资源目录中有提供)
                    if (ShouldValidateChecksum(request.ResourceId))
                    {
                        string expectedChecksum = GetExpectedChecksum(request.ResourceId);
                        if (checksum != expectedChecksum)
                        {
                            throw new Exception($"Checksum mismatch for resource {request.ResourceId}");
                        }
                    }
                    
                    // 移动到缓存位置
                    string cachedPath = GetCachedPath(request.ResourceId);
                    File.Move(tempPath, cachedPath, true);
                    
                    // 添加到缓存索引
                    var cacheEntry = new ResourceCacheEntry
                    {
                        ResourceId = request.ResourceId,
                        CachePath = cachedPath,
                        SizeBytes = fileInfo.Length,
                        LastAccessed = DateTime.Now,
                        Checksum = checksum
                    };
                    
                    resourceCache[request.ResourceId] = cacheEntry;
                    currentCacheSizeBytes += fileInfo.Length;
                    
                    // 加载资源到内存
                    await LoadResourceFromFile(request, cachedPath);
                    
                    // 保存缓存索引
                    SaveCacheIndex();
                    
                    // 清理缓存(如果需要)
                    CleanupCacheIfNeeded();
                }
            }
            finally
            {
                // 清理临时文件
                if (File.Exists(tempPath))
                {
                    File.Delete(tempPath);
                }
            }
        }

        private async Task LoadResourceFromFile(ResourceLoadRequest request, string filePath)
        {
            switch (request.ResourceType)
            {
                case ResourceType.Model:
                    await LoadModelFromFile(request, filePath);
                    break;
                    
                case ResourceType.Material:
                    await LoadMaterialFromFile(request, filePath);
                    break;
                    
                case ResourceType.Texture:
                    await LoadTextureFromFile(request, filePath);
                    break;
                    
                case ResourceType.Audio:
                    await LoadAudioFromFile(request, filePath);
                    break;
                    
                case ResourceType.Video:
                    await LoadVideoFromFile(request, filePath);
                    break;
            }
        }

        private async Task LoadModelFromFile(ResourceLoadRequest request, string filePath)
        {
            // 这里需要根据实际文件格式实现模型加载
            // 例如:GLB, FBX, OBJ等格式
            
            string extension = Path.GetExtension(filePath).ToLower();
            
            switch (extension)
            {
                case ".glb":
                case ".gltf":
                    await LoadGLTFModel(request, filePath);
                    break;
                    
                case ".fbx":
                    await LoadFBXModel(request, filePath);
                    break;
                    
                case ".obj":
                    await LoadOBJModel(request, filePath);
                    break;
                    
                default:
                    throw new NotSupportedException($"Unsupported model format: {extension}");
            }
        }

        private async Task LoadGLTFModel(ResourceLoadRequest request, string filePath)
        {
            // 使用GLTF插件加载模型
            // 这里假设使用了UnityGLTF插件
            
            try
            {
                /*
                // 实际代码需要根据使用的GLTF插件调整
                var gltfImporter = new GLTFImporter();
                await gltfImporter.LoadAsync(filePath);
                
                GameObject model = gltfImporter.GetSceneObject();
                request.LoadedObject = model;
                */
                
                // 临时实现:创建一个立方体作为占位符
                await Task.Delay(100); // 模拟加载延迟
                
                GameObject placeholder = GameObject.CreatePrimitive(PrimitiveType.Cube);
                placeholder.name = $"Model_{request.ResourceId}";
                request.LoadedObject = placeholder;
                
                request.ProgressCallback?.Invoke(1.0f);
            }
            catch (Exception ex)
            {
                throw new Exception($"Failed to load GLTF model: {ex.Message}", ex);
            }
        }

        private void ApplyModelLoadSettings(GameObject model, ModelLoadSettings settings)
        {
            if (model == null || settings == null) return;
            
            // 应用缩放
            model.transform.localScale = Vector3.one * settings.ScaleFactor;
            
            // 配置LOD
            if (settings.MaxLODLevel > 0)
            {
                ConfigureModelLOD(model, settings.MaxLODLevel);
            }
            
            // 优化网格
            if (settings.OptimizeMesh)
            {
                OptimizeModelMeshes(model);
            }
            
            // 配置碰撞体
            if (settings.LoadColliders)
            {
                AddMissingColliders(model);
            }
            else
            {
                RemoveAllColliders(model);
            }
        }

        private void ConfigureModelLOD(GameObject model, int maxLODLevel)
        {
            // 为模型配置LOD组
            LODGroup lodGroup = model.GetComponent<LODGroup>();
            
            if (lodGroup == null)
            {
                lodGroup = model.AddComponent<LODGroup>();
            }
            
            // 创建LOD级别
            List<LOD> lods = new List<LOD>();
            
            // 获取所有渲染器
            Renderer[] allRenderers = model.GetComponentsInChildren<Renderer>();
            
            // 创建不同细节级别的LOD
            for (int i = 0; i < maxLODLevel; i++)
            {
                float screenRelativeHeight = 1.0f - (i * 0.2f); // 每个级别减少20%
                screenRelativeHeight = Mathf.Max(screenRelativeHeight, 0.05f); // 最小5%
                
                // 根据级别过滤渲染器(简化实现)
                Renderer[] levelRenderers = allRenderers; // 实际应该根据细节级别筛选
                
                lods.Add(new LOD(screenRelativeHeight, levelRenderers));
            }
            
            lodGroup.SetLODs(lods.ToArray());
        }

        /// <summary>
        /// 预加载常用资源
        /// </summary>
        public async Task PreloadCommonResources()
        {
            List<Task> preloadTasks = new List<Task>();
            
            // 预加载常用材质
            var commonMaterials = currentCatalog.Materials
                .Where(m => m.PreloadPriority > 0)
                .OrderByDescending(m => m.PreloadPriority)
                .Take(10);
            
            foreach (var material in commonMaterials)
            {
                preloadTasks.Add(LoadMaterialAsync(material.ResourceId));
            }
            
            // 预加载常用纹理
            var commonTextures = currentCatalog.Textures
                .Where(t => t.PreloadPriority > 0)
                .OrderByDescending(t => t.PreloadPriority)
                .Take(20);
            
            foreach (var texture in commonTextures)
            {
                preloadTasks.Add(LoadTextureAsync(texture.ResourceId));
            }
            
            // 并行预加载
            await Task.WhenAll(preloadTasks);
            
            Debug.Log($"Preloaded {preloadTasks.Count} common resources");
        }

        /// <summary>
        /// 清理未使用的资源
        /// </summary>
        public void CleanupUnusedResources()
        {
            // 清理未使用的模型实例
            List<string> modelsToRemove = new List<string>();
            
            foreach (var kvp in instantiatedModels)
            {
                if (kvp.Value == null || !kvp.Value.activeInHierarchy)
                {
                    modelsToRemove.Add(kvp.Key);
                    Destroy(kvp.Value);
                }
            }
            
            foreach (string modelId in modelsToRemove)
            {
                instantiatedModels.Remove(modelId);
            }
            
            // 清理材质缓存
            CleanupUnusedMaterials();
            
            // 清理纹理缓存
            CleanupUnusedTextures();
            
            // 清理音频缓存
            CleanupUnusedAudio();
            
            // 强制执行垃圾回收
            System.GC.Collect();
            Resources.UnloadUnusedAssets();
            
            Debug.Log($"Cleaned up unused resources. Remaining models: {instantiatedModels.Count}");
        }

        private void CleanupCacheIfNeeded()
        {
            if (currentCacheSizeBytes <= maxCacheSizeBytes) return;
            
            // 按最后访问时间排序,清理最旧的缓存项
            var oldEntries = resourceCache.Values
                .OrderBy(e => e.LastAccessed)
                .ToList();
            
            long sizeToFree = currentCacheSizeBytes - maxCacheSizeBytes / 2; // 清理到50%容量
            
            long freedSize = 0;
            foreach (var entry in oldEntries)
            {
                if (freedSize >= sizeToFree) break;
                
                try
                {
                    if (File.Exists(entry.CachePath))
                    {
                        File.Delete(entry.CachePath);
                    }
                    
                    resourceCache.Remove(entry.ResourceId);
                    freedSize += entry.SizeBytes;
                    currentCacheSizeBytes -= entry.SizeBytes;
                }
                catch (Exception ex)
                {
                    Debug.LogWarning($"Failed to delete cache file {entry.CachePath}: {ex.Message}");
                }
            }
            
            SaveCacheIndex();
            
            Debug.Log($"Cleaned up cache. Freed {FormatBytes(freedSize)}, remaining cache size: {FormatBytes(currentCacheSizeBytes)}");
        }

        private void StartCacheMaintenance()
        {
            // 每5分钟检查一次缓存
            InvokeRepeating("PerformCacheMaintenance", 300f, 300f);
        }

        private void PerformCacheMaintenance()
        {
            // 验证缓存完整性
            ValidateCacheIntegrity();
            
            // 清理过期缓存
            CleanupExpiredCache();
            
            // 压缩缓存(如果支持)
            CompressCacheIfNeeded();
        }

        public event Action<bool> OnCatalogLoaded;
    }

    /// <summary>
    /// 资源加载请求
    /// </summary>
    public class ResourceLoadRequest
    {
        public string ResourceId;
        public ResourceType ResourceType;
        public LoadPriority Priority;
        public Action<float> ProgressCallback;
        public object LoadedObject;
        public bool IsSuccessful;
        public string ErrorMessage;
        
        public TaskCompletionSource<bool> CompletionSource;
        public Task<bool> CompletionTask => CompletionSource.Task;
        
        public ResourceLoadRequest()
        {
            CompletionSource = new TaskCompletionSource<bool>();
        }
    }

    public enum ResourceType
    {
        Model,
        Material,
        Texture,
        Audio,
        Video,
        Prefab,
        Configuration
    }

    public enum LoadPriority
    {
        Low,
        Normal,
        High,
        Critical
    }

    /// <summary>
    /// 缓存索引
    /// </summary>
    [System.Serializable]
    public class CacheIndex
    {
        public List<ResourceCacheEntry> Entries;
        public long TotalSizeBytes;
        public DateTime LastUpdated;
    }

    /// <summary>
    /// 缓存条目
    /// </summary>
    [System.Serializable]
    public class ResourceCacheEntry
    {
        public string ResourceId;
        public string CachePath;
        public long SizeBytes;
        public DateTime LastAccessed;
        public string Checksum;
    }

    /// <summary>
    /// 材质资源
    /// </summary>
    [System.Serializable]
    public class MaterialResource
    {
        public string ResourceId;
        public string MaterialName;
        public string ShaderName;
        public string BaseTextureId;
        public List<string> AdditionalTextureIds;
        public MaterialProperties Properties;
        public int PreloadPriority;
    }

    /// <summary>
    /// 纹理资源
    /// </summary>
    [System.Serializable]
    public class TextureResource
    {
        public string ResourceId;
        public string TextureName;
        public TextureFormat Format;
        public int Width;
        public int Height;
        public bool GenerateMipMaps;
        public bool IsNormalMap;
        public int PreloadPriority;
    }

    /// <summary>
    /// 音频资源
    /// </summary>
    [System.Serializable]
    public class AudioResource
    {
        public string ResourceId;
        public string ClipName;
        public AudioType Type;
        public float Duration;
        public int SampleRate;
        public int Channels;
    }
}

9.3 工业级视频播放与多媒体演示系统

工业级汽车展示需要支持高质量的视频播放,包括产品介绍视频、技术讲解、广告片等。以下是多媒体演示系统的实现:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Video;
using Microsoft.MixedReality.Toolkit.Input;

namespace AutomotiveIndustryMR
{
    /// <summary>
    /// 工业级视频播放管理器
    /// 支持多种视频格式、流媒体、交互式视频和同步播放
    /// </summary>
    public class IndustrialVideoPlayer : MonoBehaviour
    {
        [System.Serializable]
        public class VideoPlaylist
        {
            public string PlaylistId;
            public string PlaylistName;
            public List<VideoItem> Videos;
            public PlayMode PlayMode;
            public bool LoopPlaylist;
            public float CrossfadeDuration = 1.0f;
        }

        [System.Serializable]
        public class VideoItem
        {
            public string VideoId;
            public string VideoName;
            public string VideoPath;
            public VideoSource SourceType;
            public float Duration;
            public VideoResolution Resolution;
            public List<VideoChapter> Chapters;
            public Dictionary<string, string> Metadata;
            public VideoPlaybackSettings PlaybackSettings;
        }

        [System.Serializable]
        public class VideoChapter
        {
            public string ChapterId;
            public string Title;
            public float StartTime;
            public float EndTime;
            public List<ChapterInteraction> Interactions;
        }

        [System.Serializable]
        public class ChapterInteraction
        {
            public float TimePosition;
            public InteractionType Type;
            public string TargetObjectId;
            public string ActionData;
            public bool PauseOnInteraction;
        }

        public enum VideoSource
        {
            LocalFile,
            StreamingURL,
            EmbeddedResource,
            AssetBundle
        }

        public enum VideoResolution
        {
            SD,
            HD,
            FullHD,
            UltraHD,
            Custom
        }

        public enum PlayMode
        {
            Sequential,
            Random,
            Shuffle
        }

        public enum InteractionType
        {
            ShowAnnotation,
            HighlightComponent,
            ChangeCamera,
            LoadModel,
            PlayAudio,
            ShowText,
            OpenURL
        }

        private VideoPlayer mainVideoPlayer;
        private VideoPlayer secondaryVideoPlayer; // 用于交叉淡入淡出
        private AudioSource audioOutput;
        private RenderTexture videoRenderTexture;

        private VideoPlaylist currentPlaylist;
        private VideoItem currentVideo;
        private int currentVideoIndex = -1;
        private bool isPlaying = false;
        private bool isBuffering = false;
        private float playbackStartTime;

        private Dictionary<string, VideoItem> videoCache = new Dictionary<string, VideoItem>();
        private List<VideoChapter> activeChapters = new List<VideoChapter>();
        private List<ChapterInteraction> pendingInteractions = new List<ChapterInteraction>();

        private VideoDisplayController displayController;
        private VideoInteractionHandler interactionHandler;
        private VideoAnalyticsTracker analyticsTracker;

        private float bufferProgress = 0f;
        private float playbackProgress = 0f;
        private long totalBytesRead = 0;
        private float averageDownloadSpeed = 0f;

        private void Awake()
        {
            InitializeVideoSystem();
            SetupDisplayController();
            InitializeAnalytics();
        }

        private void InitializeVideoSystem()
        {
            // 创建主视频播放器
            GameObject videoPlayerObj = new GameObject("MainVideoPlayer");
            videoPlayerObj.transform.SetParent(transform);
            
            mainVideoPlayer = videoPlayerObj.AddComponent<VideoPlayer>();
            ConfigureVideoPlayer(mainVideoPlayer);
            
            // 创建辅助视频播放器(用于平滑过渡)
            GameObject secondaryPlayerObj = new GameObject("SecondaryVideoPlayer");
            secondaryPlayerObj.transform.SetParent(transform);
            
            secondaryVideoPlayer = secondaryPlayerObj.AddComponent<VideoPlayer>();
            ConfigureVideoPlayer(secondaryVideoPlayer);
            secondaryVideoPlayer.gameObject.SetActive(false);
            
            // 创建音频输出
            audioOutput = gameObject.AddComponent<AudioSource>();
            audioOutput.spatialize = true;
            audioOutput.spatialBlend = 1.0f;
            audioOutput.rolloffMode = AudioRolloffMode.Logarithmic;
            
            mainVideoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;
            mainVideoPlayer.SetTargetAudioSource(0, audioOutput);
            
            // 创建渲染纹理
            videoRenderTexture = new RenderTexture(1920, 1080, 24, RenderTextureFormat.ARGB32);
            videoRenderTexture.Create();
            
            mainVideoPlayer.targetTexture = videoRenderTexture;
            
            // 设置事件处理
            mainVideoPlayer.prepareCompleted += OnVideoPrepared;
            mainVideoPlayer.seekCompleted += OnSeekCompleted;
            mainVideoPlayer.loopPointReached += OnVideoEnded;
            mainVideoPlayer.errorReceived += OnVideoError;
            
            // 初始化交互处理器
            interactionHandler = gameObject.AddComponent<VideoInteractionHandler>();
            interactionHandler.Initialize(this);
        }

        private void ConfigureVideoPlayer(VideoPlayer player)
        {
            player.playOnAwake = false;
            player.waitForFirstFrame = true;
            player.skipOnDrop = true;
            player.renderMode = VideoRenderMode.RenderTexture;
            player.aspectRatio = VideoAspectRatio.FitVertically;
            player.isLooping = false;
            player.controlledAudioTrackCount = 1;
        }

        private void SetupDisplayController()
        {
            // 创建视频显示控制器
            displayController = gameObject.AddComponent<VideoDisplayController>();
            displayController.Initialize(videoRenderTexture);
            
            // 设置显示模式
            displayController.SetDisplayMode(VideoDisplayMode.FloatingScreen);
            displayController.SetScreenSize(3.0f, 1.6875f); // 16:9 aspect ratio
            displayController.SetScreenPosition(new Vector3(0, 1.5f, 3.0f));
            
            // 配置交互
            displayController.EnableInteractions(true);
        }

        private void InitializeAnalytics()
        {
            analyticsTracker = gameObject.AddComponent<VideoAnalyticsTracker>();
            analyticsTracker.Initialize();
        }

        /// <summary>
        /// 加载播放列表
        /// </summary>
        public async Task<bool> LoadPlaylist(VideoPlaylist playlist)
        {
            if (playlist == null || playlist.Videos.Count == 0)
            {
                Debug.LogError("Invalid playlist provided");
                return false;
            }
            
            currentPlaylist = playlist;
            currentVideoIndex = -1;
            
            // 预加载播放列表中的视频
            await PreloadPlaylistVideos(playlist);
            
            // 记录分析事件
            analyticsTracker.RecordPlaylistLoad(playlist.PlaylistId);
            
            return true;
        }

        private async Task PreloadPlaylistVideos(VideoPlaylist playlist)
        {
            List<Task> preloadTasks = new List<Task>();
            
            foreach (var video in playlist.Videos)
            {
                preloadTasks.Add(PreloadVideo(video));
            }
            
            await Task.WhenAll(preloadTasks);
            Debug.Log($"Preloaded {preloadTasks.Count} videos from playlist");
        }

        private async Task PreloadVideo(VideoItem video)
        {
            // 检查是否已缓存
            if (videoCache.ContainsKey(video.VideoId))
            {
                return;
            }
            
            // 根据来源类型预加载
            switch (video.SourceType)
            {
                case VideoSource.LocalFile:
                    await PreloadLocalVideo(video);
                    break;
                    
                case VideoSource.StreamingURL:
                    await PreloadStreamingVideo(video);
                    break;
                    
                case VideoSource.EmbeddedResource:
                    await PreloadEmbeddedVideo(video);
                    break;
                    
                case VideoSource.AssetBundle:
                    await PreloadAssetBundleVideo(video);
                    break;
            }
            
            videoCache[video.VideoId] = video;
        }

        private async Task PreloadLocalVideo(VideoItem video)
        {
            // 验证文件存在
            if (!System.IO.File.Exists(video.VideoPath))
            {
                throw new System.IO.FileNotFoundException($"Video file not found: {video.VideoPath}");
            }
            
            // 获取文件信息
            var fileInfo = new System.IO.FileInfo(video.VideoPath);
            video.Duration = await GetVideoDuration(video.VideoPath);
            
            Debug.Log($"Preloaded local video: {video.VideoName}, Size: {FormatBytes(fileInfo.Length)}, Duration: {video.Duration:F1}s");
        }

        /// <summary>
        /// 播放指定视频
        /// </summary>
        public async Task PlayVideo(string videoId)
        {
            if (!videoCache.ContainsKey(videoId))
            {
                Debug.LogError($"Video not found in cache: {videoId}");
                return;
            }
            
            VideoItem video = videoCache[videoId];
            
            // 停止当前播放
            if (isPlaying)
            {
                StopPlayback();
            }
            
            currentVideo = video;
            isBuffering = true;
            
            // 准备视频
            await PrepareVideoForPlayback(video);
            
            // 开始播放
            StartPlayback();
            
            // 记录分析
            analyticsTracker.RecordVideoStart(videoId, video.VideoName);
        }

        private async Task PrepareVideoForPlayback(VideoItem video)
        {
            // 配置视频源
            ConfigureVideoSource(mainVideoPlayer, video);
            
            // 准备视频
            mainVideoPlayer.Prepare();
            
            // 等待准备完成
            await WaitForVideoPreparation();
            
            // 加载章节和交互
            LoadVideoChapters(video.Chapters);
            
            // 更新显示
            displayController.UpdateVideoInfo(video.VideoName, video.Duration);
            
            isBuffering = false;
        }

        private void ConfigureVideoSource(VideoPlayer player, VideoItem video)
        {
            player.source = VideoSource.Url;
            
            switch (video.SourceType)
            {
                case VideoSource.LocalFile:
                    player.url = "file://" + video.VideoPath;
                    break;
                    
                case VideoSource.StreamingURL:
                    player.url = video.VideoPath;
                    break;
                    
                case VideoSource.EmbeddedResource:
                    // 处理嵌入式资源
                    break;
                    
                case VideoSource.AssetBundle:
                    // 处理AssetBundle资源
                    break;
            }
            
            // 应用播放设置
            ApplyPlaybackSettings(player, video.PlaybackSettings);
        }

        private void ApplyPlaybackSettings(VideoPlayer player, VideoPlaybackSettings settings)
        {
            if (settings == null) return;
            
            player.playbackSpeed = settings.PlaybackSpeed;
            player.isLooping = settings.Loop;
            player.skipOnDrop = settings.SkipOnDrop;
            
            if (settings.AudioVolume >= 0)
            {
                audioOutput.volume = settings.AudioVolume;
            }
        }

        private void StartPlayback()
        {
            if (mainVideoPlayer == null || !mainVideoPlayer.isPrepared) return;
            
            playbackStartTime = Time.time;
            mainVideoPlayer.Play();
            isPlaying = true;
            
            // 开始播放进度监控
            StartCoroutine(MonitorPlaybackProgress());
            
            // 开始交互监控
            StartCoroutine(MonitorVideoInteractions());
            
            // 显示播放控制UI
            UIManager.Instance.ShowVideoControls(true);
        }

        private System.Collections.IEnumerator MonitorPlaybackProgress()
        {
            while (isPlaying && mainVideoPlayer.isPlaying)
            {
                playbackProgress = (float)(mainVideoPlayer.time / mainVideoPlayer.length);
                
                // 更新UI
                displayController.UpdatePlaybackProgress(playbackProgress, mainVideoPlayer.time, mainVideoPlayer.length);
                
                // 检查章节
                CheckChapterProgress(mainVideoPlayer.time);
                
                yield return new WaitForSeconds(0.1f);
            }
        }

        private System.Collections.IEnumerator MonitorVideoInteractions()
        {
            while (isPlaying)
            {
                float currentTime = (float)mainVideoPlayer.time;
                
                // 检查是否有到期的交互
                CheckPendingInteractions(currentTime);
                
                yield return new WaitForSeconds(0.05f);
            }
        }

        private void CheckChapterProgress(double currentTime)
        {
            foreach (var chapter in activeChapters)
            {
                if (currentTime >= chapter.StartTime && currentTime <= chapter.EndTime)
                {
                    // 触发章节激活
                    if (!chapter.IsActive)
                    {
                        OnChapterEntered(chapter);
                    }
                }
                else if (chapter.IsActive)
                {
                    // 触发章节退出
                    OnChapterExited(chapter);
                }
            }
        }

        private void OnChapterEntered(VideoChapter chapter)
        {
            chapter.IsActive = true;
            
            // 显示章节标题
            displayController.ShowChapterTitle(chapter.Title, 3f);
            
            // 激活章节交互
            foreach (var interaction in chapter.Interactions)
            {
                if (interaction.TimePosition <= 0) // 立即触发
                {
                    ExecuteInteraction(interaction);
                }
                else
                {
                    pendingInteractions.Add(interaction);
                }
            }
            
            // 记录分析
            analyticsTracker.RecordChapterEntered(chapter.ChapterId, chapter.Title);
        }

        private void CheckPendingInteractions(float currentTime)
        {
            List<ChapterInteraction> toRemove = new List<ChapterInteraction>();
            
            foreach (var interaction in pendingInteractions)
            {
                if (currentTime >= interaction.TimePosition)
                {
                    ExecuteInteraction(interaction);
                    toRemove.Add(interaction);
                }
            }
            
            foreach (var interaction in toRemove)
            {
                pendingInteractions.Remove(interaction);
            }
        }

        private void ExecuteInteraction(ChapterInteraction interaction)
        {
            // 如果需要,暂停视频
            if (interaction.PauseOnInteraction && isPlaying)
            {
                PausePlayback();
            }
            
            // 执行交互
            switch (interaction.Type)
            {
                case InteractionType.ShowAnnotation:
                    ShowAnnotation(interaction.TargetObjectId, interaction.ActionData);
                    break;
                    
                case InteractionType.HighlightComponent:
                    HighlightComponent(interaction.TargetObjectId);
                    break;
                    
                case InteractionType.ChangeCamera:
                    ChangeCameraAngle(interaction.ActionData);
                    break;
                    
                case InteractionType.LoadModel:
                    LoadAdditionalModel(interaction.TargetObjectId);
                    break;
                    
                case InteractionType.PlayAudio:
                    PlayAdditionalAudio(interaction.ActionData);
                    break;
                    
                case InteractionType.ShowText:
                    ShowInfoText(interaction.ActionData);
                    break;
                    
                case InteractionType.OpenURL:
                    OpenExternalURL(interaction.ActionData);
                    break;
            }
            
            // 记录交互
            analyticsTracker.RecordInteraction(
                interaction.Type.ToString(),
                currentVideo.VideoId,
                (float)mainVideoPlayer.time
            );
        }

        /// <summary>
        /// 暂停播放
        /// </summary>
        public void PausePlayback()
        {
            if (!isPlaying) return;
            
            mainVideoPlayer.Pause();
            isPlaying = false;
            
            displayController.OnPlaybackPaused();
            
            analyticsTracker.RecordPlaybackPaused(currentVideo.VideoId, (float)mainVideoPlayer.time);
        }

        /// <summary>
        /// 恢复播放
        /// </summary>
        public void ResumePlayback()
        {
            if (isPlaying) return;
            
            mainVideoPlayer.Play();
            isPlaying = true;
            
            displayController.OnPlaybackResumed();
            
            analyticsTracker.RecordPlaybackResumed(currentVideo.VideoId, (float)mainVideoPlayer.time);
        }

        /// <summary>
        /// 跳转到指定时间
        /// </summary>
        public async Task SeekToTime(float timeInSeconds)
        {
            if (mainVideoPlayer == null || !mainVideoPlayer.canSetTime) return;
            
            float targetTime = Mathf.Clamp(timeInSeconds, 0, (float)mainVideoPlayer.length - 0.1f);
            
            // 记录跳转前的状态
            analyticsTracker.RecordSeekStart(currentVideo.VideoId, (float)mainVideoPlayer.time, targetTime);
            
            bool wasPlaying = isPlaying;
            
            if (wasPlaying)
            {
                mainVideoPlayer.Pause();
            }
            
            // 执行跳转
            mainVideoPlayer.time = targetTime;
            
            // 等待跳转完成
            await Task.Delay(100);
            
            if (wasPlaying)
            {
                mainVideoPlayer.Play();
            }
            
            // 记录跳转完成
            analyticsTracker.RecordSeekComplete(currentVideo.VideoId, targetTime);
        }

        /// <summary>
        /// 启用画中画模式
        /// </summary>
        public void EnablePictureInPicture(VideoItem secondaryVideo)
        {
            if (secondaryVideoPlayer == null || secondaryVideo == null) return;
            
            // 配置并启动辅助视频播放器
            ConfigureVideoSource(secondaryVideoPlayer, secondaryVideo);
            secondaryVideoPlayer.Prepare();
            
            // 创建画中画显示
            displayController.EnablePictureInPicture(true, secondaryVideoPlayer.targetTexture);
            
            secondaryVideoPlayer.Play();
        }

        /// <summary>
        /// 同步多个视频播放
        /// </summary>
        public async Task SyncMultipleVideos(List<SyncVideoItem> videos)
        {
            if (videos == null || videos.Count == 0) return;
            
            // 准备所有视频
            List<Task> preparationTasks = new List<Task>();
            List<VideoPlayer> players = new List<VideoPlayer>();
            
            foreach (var syncVideo in videos)
            {
                var player = CreateAdditionalVideoPlayer();
                ConfigureVideoSource(player, syncVideo.Video);
                players.Add(player);
                
                preparationTasks.Add(PrepareVideoPlayer(player));
            }
            
            await Task.WhenAll(preparationTasks);
            
            // 同步开始播放
            foreach (var player in players)
            {
                player.Play();
            }
            
            // 启动同步监控
            StartCoroutine(MonitorVideoSync(players));
        }

        private System.Collections.IEnumerator MonitorVideoSync(List<VideoPlayer> players)
        {
            while (players.Any(p => p.isPlaying))
            {
                // 检查同步状态
                double masterTime = players[0].time;
                double maxTimeDifference = 0.033; // 33ms
                
                for (int i = 1; i < players.Count; i++)
                {
                    double timeDiff = Math.Abs(players[i].time - masterTime);
                    
                    if (timeDiff > maxTimeDifference)
                    {
                        // 重新同步
                        players[i].time = masterTime;
                    }
                }
                
                yield return new WaitForSeconds(0.1f);
            }
        }

        private void OnVideoPrepared(VideoPlayer source)
        {
            Debug.Log($"Video prepared: {source.url}, Duration: {source.length:F2}s");
            
            // 更新显示信息
            displayController.OnVideoPrepared(source.length);
            
            // 触发准备完成事件
            OnVideoPreparationComplete?.Invoke(true);
        }

        private void OnVideoEnded(VideoPlayer source)
        {
            isPlaying = false;
            
            // 记录播放完成
            analyticsTracker.RecordVideoComplete(
                currentVideo.VideoId,
                (float)source.time,
                Time.time - playbackStartTime
            );
            
            // 清理资源
            CleanupAfterPlayback();
            
            // 播放下一个视频(如果在播放列表中)
            if (currentPlaylist != null)
            {
                PlayNextInPlaylist();
            }
            
            OnPlaybackEnded?.Invoke();
        }

        private void PlayNextInPlaylist()
        {
            if (currentPlaylist == null || currentPlaylist.Videos.Count == 0) return;
            
            int nextIndex = GetNextVideoIndex();
            
            if (nextIndex >= 0 && nextIndex < currentPlaylist.Videos.Count)
            {
                VideoItem nextVideo = currentPlaylist.Videos[nextIndex];
                PlayVideo(nextVideo.VideoId);
            }
        }

        private int GetNextVideoIndex()
        {
            if (currentVideoIndex < 0) return 0;
            
            switch (currentPlaylist.PlayMode)
            {
                case PlayMode.Sequential:
                    int next = currentVideoIndex + 1;
                    return next < currentPlaylist.Videos.Count ? next : 
                           (currentPlaylist.LoopPlaylist ? 0 : -1);
                    
                case PlayMode.Random:
                    return UnityEngine.Random.Range(0, currentPlaylist.Videos.Count);
                    
                case PlayMode.Shuffle:
                    // 实现洗牌算法
                    return GetNextShuffledIndex();
                    
                default:
                    return -1;
            }
        }

        public event Action<bool> OnVideoPreparationComplete;
        public event Action OnPlaybackEnded;
    }

    /// <summary>
    /// 视频显示控制器
    /// </summary>
    public class VideoDisplayController : MonoBehaviour
    {
        private GameObject videoScreen;
        private Renderer videoRenderer;
        private Material videoMaterial;
        
        private TextMesh titleText;
        private TextMesh timeText;
        private GameObject progressBar;
        private GameObject controlPanel;
        
        private VideoDisplayMode currentMode;
        private Vector3 screenPosition;
        private Quaternion screenRotation;
        private Vector2 screenSize;
        
        private bool controlsVisible = true;
        private float controlsHideTimeout = 3f;
        private float lastInteractionTime;
        
        public void Initialize(RenderTexture videoTexture)
        {
            CreateVideoDisplay();
            SetupVideoMaterial(videoTexture);
            CreateUIElements();
            SetupInteractions();
        }
        
        private void CreateVideoDisplay()
        {
            // 创建视频屏幕
            videoScreen = GameObject.CreatePrimitive(PrimitiveType.Quad);
            videoScreen.name = "VideoDisplayScreen";
            videoScreen.transform.SetParent(transform);
            
            videoRenderer = videoScreen.GetComponent<Renderer>();
            videoRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
            videoRenderer.receiveShadows = false;
            
            // 添加碰撞体用于交互
            BoxCollider collider = videoScreen.GetComponent<BoxCollider>();
            collider.size = new Vector3(1, 1, 0.01f);
        }
        
        private void SetupVideoMaterial(RenderTexture videoTexture)
        {
            videoMaterial = new Material(Shader.Find("Unlit/Texture"));
            videoMaterial.mainTexture = videoTexture;
            videoRenderer.material = videoMaterial;
            
            // 添加混合现实效果
            AddMixedRealityEffects();
        }
        
        private void AddMixedRealityEffects()
        {
            // 添加环境反射
            MaterialExtension.AddEnvironmentReflection(videoMaterial, 0.3f);
            
            // 添加轻微透明度
            videoMaterial.SetFloat("_Alpha", 0.95f);
            
            // 添加边框效果
            MaterialExtension.AddBorderEffect(videoMaterial, 0.02f, Color.black);
        }
        
        public void SetDisplayMode(VideoDisplayMode mode)
        {
            currentMode = mode;
            
            switch (mode)
            {
                case VideoDisplayMode.FloatingScreen:
                    ConfigureFloatingScreen();
                    break;
                    
                case VideoDisplayMode.WorldLocked:
                    ConfigureWorldLocked();
                    break;
                    
                case VideoDisplayMode.HeadLocked:
                    ConfigureHeadLocked();
                    break;
                    
                case VideoDisplayMode.Spherical:
                    ConfigureSpherical();
                    break;
            }
        }
        
        private void ConfigureFloatingScreen()
        {
            // 配置为漂浮屏幕
            videoScreen.transform.position = screenPosition;
            videoScreen.transform.rotation = screenRotation;
            videoScreen.transform.localScale = new Vector3(screenSize.x, screenSize.y, 1);
            
            // 添加轻微浮动动画
            AddFloatingAnimation();
        }
        
        private void AddFloatingAnimation()
        {
            // 添加上下浮动效果
            FloatingAnimation anim = videoScreen.AddComponent<FloatingAnimation>();
            anim.amplitude = 0.01f;
            anim.frequency = 0.5f;
        }
        
        public void UpdatePlaybackProgress(float progress, double currentTime, double totalTime)
        {
            if (progressBar != null)
            {
                // 更新进度条
                UpdateProgressBar(progress);
            }
            
            if (timeText != null)
            {
                // 更新时间显示
                timeText.text = $"{FormatTime(currentTime)} / {FormatTime(totalTime)}";
            }
        }
        
        private string FormatTime(double seconds)
        {
            TimeSpan timeSpan = TimeSpan.FromSeconds(seconds);
            
            if (timeSpan.Hours > 0)
            {
                return string.Format("{0:00}:{1:00}:{2:00}", 
                    timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds);
            }
            else
            {
                return string.Format("{0:00}:{1:00}", 
                    timeSpan.Minutes, timeSpan.Seconds);
            }
        }
    }
    
    public enum VideoDisplayMode
    {
        FloatingScreen,
        WorldLocked,
        HeadLocked,
        Spherical
    }
    
    [System.Serializable]
    public class VideoPlaybackSettings
    {
        public float PlaybackSpeed = 1.0f;
        public bool Loop = false;
        public bool SkipOnDrop = true;
        public float AudioVolume = 1.0f;
        public bool AutoPlay = true;
        public bool Muted = false;
    }
    
    [System.Serializable]
    public class SyncVideoItem
    {
        public VideoItem Video;
        public float SyncOffset;
        public bool IsMaster;
    }
}

9.4 汽车动态模拟与物理交互系统

工业级汽车展示需要真实的动态模拟和物理交互。以下是汽车动态模拟系统的实现:

using System;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.Toolkit.Input;

namespace AutomotiveIndustryMR
{
    /// <summary>
    /// 汽车动态模拟控制器
    /// 实现真实的汽车运动、物理反馈和交互式控制
    /// </summary>
    public class CarDynamicSimulator : MonoBehaviour
    {
        [System.Serializable]
        public class CarPhysicsProfile
        {
            public string ProfileId;
            public string CarModelId;
            public float Mass; // 质量 (kg)
            public Vector3 CenterOfMass; // 重心
            public WheelPhysics[] Wheels;
            public EngineSpecification Engine;
            public TransmissionSpecification Transmission;
            public BrakeSpecification Brakes;
            public SuspensionSpecification Suspension;
            public AerodynamicsSpecification Aerodynamics;
        }

        [System.Serializable]
        public class WheelPhysics
        {
            public WheelPosition Position;
            public float Mass;
            public float Radius;
            public float Width;
            public float SuspensionTravel;
            public float SpringRate;
            public float DamperRate;
            public float FrictionCoefficient;
            public bool IsSteering;
            public float MaxSteerAngle;
        }

        [System.Serializable]
        public class EngineSpecification
        {
            public EngineType Type;
            public float Displacement; // 排量 (L)
            public int Cylinders;
            public float MaxPower; // 最大功率 (kW)
            public float MaxTorque; // 最大扭矩 (Nm)
            public float[] PowerCurve; // 功率曲线
            public float[] TorqueCurve; // 扭矩曲线
            public float RedlineRPM;
            public float IdleRPM;
        }

        [System.Serializable]
        public class TransmissionSpecification
        {
            public TransmissionType Type;
            public int Gears;
            public float[] GearRatios;
            public float FinalDriveRatio;
            public float ShiftTime;
            public bool HasReverse;
            public float ReverseRatio;
        }

        private CarPhysicsProfile currentPhysicsProfile;
        private Rigidbody carRigidbody;
        private WheelCollider[] wheelColliders;
        private GameObject[] wheelMeshes;

        private float currentSpeed;
        private float currentRPM;
        private int currentGear = 1;
        private bool isEngineRunning = false;
        private float throttleInput = 0f;
        private float brakeInput = 0f;
        private float steerInput = 0f;
        private float clutchInput = 0f;

        private float engineTorque;
        private float wheelTorque;
        private float aerodynamicDrag;
        private float rollingResistance;

        private CarInputSystem inputSystem;
        private CarAudioSystem audioSystem;
        private CarEffectsSystem effectsSystem;
        private CarTelemetrySystem telemetrySystem;

        private Dictionary<WheelPosition, WheelData> wheelData;
        private List<CarComponent> interactiveComponents;

        private bool simulationActive = false;
        private float simulationTime = 0f;
        private int simulationFrame = 0;

        private void Awake()
        {
            InitializePhysicsSystem();
            SetupWheelSystem();
            InitializeSubsystems();
            StartTelemetryRecording();
        }

        private void InitializePhysicsSystem()
        {
            // 添加刚体组件
            carRigidbody = gameObject.AddComponent<Rigidbody>();
            carRigidbody.mass = 1500f; // 默认质量
            carRigidbody.drag = 0.1f;
            carRigidbody.angularDrag = 0.5f;
            carRigidbody.useGravity = true;
            carRigidbody.isKinematic = false;
            carRigidbody.interpolation = RigidbodyInterpolation.Interpolate;
            carRigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
        }

        public void LoadPhysicsProfile(CarPhysicsProfile profile)
        {
            if (profile == null)
            {
                Debug.LogError("Physics profile is null");
                return;
            }

            currentPhysicsProfile = profile;
            
            // 应用物理配置
            ApplyPhysicsProfile(profile);
            
            // 初始化轮子数据
            InitializeWheelData();
            
            // 配置子系统
            ConfigureSubsystemsForProfile(profile);
            
            Debug.Log($"Loaded physics profile: {profile.ProfileId} for {profile.CarModelId}");
        }

        private void ApplyPhysicsProfile(CarPhysicsProfile profile)
        {
            // 设置质量
            carRigidbody.mass = profile.Mass;
            
            // 设置重心
            carRigidbody.centerOfMass = profile.CenterOfMass;
            
            // 创建轮子碰撞体
            CreateWheelColliders(profile.Wheels);
            
            // 配置空气动力学
            ConfigureAerodynamics(profile.Aerodynamics);
        }

        private void CreateWheelColliders(WheelPhysics[] wheels)
        {
            wheelColliders = new WheelCollider[wheels.Length];
            wheelMeshes = new GameObject[wheels.Length];
            wheelData = new Dictionary<WheelPosition, WheelData>();
            
            for (int i = 0; i < wheels.Length; i++)
            {
                WheelPhysics wheelPhysics = wheels[i];
                
                // 创建轮子碰撞体
                GameObject wheelColliderObj = new GameObject($"WheelCollider_{wheelPhysics.Position}");
                wheelColliderObj.transform.SetParent(transform);
                
                // 根据位置设置轮子位置
                Vector3 wheelPosition = CalculateWheelPosition(wheelPhysics.Position);
                wheelColliderObj.transform.localPosition = wheelPosition;
                
                WheelCollider wheelCollider = wheelColliderObj.AddComponent<WheelCollider>();
                ConfigureWheelCollider(wheelCollider, wheelPhysics);
                
                wheelColliders[i] = wheelCollider;
                
                // 创建轮子网格
                CreateWheelMesh(wheelPhysics, i);
                
                // 初始化轮子数据
                wheelData[wheelPhysics.Position] = new WheelData
                {
                    Physics = wheelPhysics,
                    Collider = wheelCollider,
                    Mesh = wheelMeshes[i],
                    Position = wheelPhysics.Position
                };
            }
        }

        private Vector3 CalculateWheelPosition(WheelPosition position)
        {
            // 根据汽车尺寸计算轮子位置
            Bounds carBounds = GetComponent<Renderer>().bounds;
            float wheelBase = carBounds.size.z * 0.8f;
            float trackWidth = carBounds.size.x * 0.9f;
            
            float xPos = 0f;
            float zPos = 0f;
            
            switch (position)
            {
                case WheelPosition.FrontLeft:
                    xPos = -trackWidth / 2;
                    zPos = wheelBase / 2;
                    break;
                    
                case WheelPosition.FrontRight:
                    xPos = trackWidth / 2;
                    zPos = wheelBase / 2;
                    break;
                    
                case WheelPosition.RearLeft:
                    xPos = -trackWidth / 2;
                    zPos = -wheelBase / 2;
                    break;
                    
                case WheelPosition.RearRight:
                    xPos = trackWidth / 2;
                    zPos = -wheelBase / 2;
                    break;
            }
            
            return new Vector3(xPos, 0, zPos);
        }

        private void ConfigureWheelCollider(WheelCollider collider, WheelPhysics physics)
        {
            collider.mass = physics.Mass;
            collider.radius = physics.Radius;
            collider.wheelDampingRate = physics.DamperRate;
            collider.suspensionDistance = physics.SuspensionTravel;
            
            // 配置悬架弹簧
            JointSpring suspensionSpring = new JointSpring
            {
                spring = physics.SpringRate,
                damper = physics.DamperRate,
                targetPosition = 0.5f
            };
            
            collider.suspensionSpring = suspensionSpring;
            
            // 配置轮胎摩擦
            WheelFrictionCurve forwardFriction = new WheelFrictionCurve
            {
                extremumSlip = 0.4f,
                extremumValue = 1f,
                asymptoteSlip = 0.8f,
                asymptoteValue = 0.5f,
                stiffness = physics.FrictionCoefficient
            };
            
            WheelFrictionCurve sidewaysFriction = new WheelFrictionCurve
            {
                extremumSlip = 0.2f,
                extremumValue = 1f,
                asymptoteSlip = 0.5f,
                asymptoteValue = 0.75f,
                stiffness = physics.FrictionCoefficient
            };
            
            collider.forwardFriction = forwardFriction;
            collider.sidewaysFriction = sidewaysFriction;
        }

        private void CreateWheelMesh(WheelPhysics physics, int index)
        {
            GameObject wheelMesh = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
            wheelMesh.name = $"WheelMesh_{physics.Position}";
            wheelMesh.transform.SetParent(wheelColliders[index].transform);
            wheelMesh.transform.localPosition = Vector3.zero;
            wheelMesh.transform.localRotation = Quaternion.Euler(0, 0, 90);
            wheelMesh.transform.localScale = new Vector3(
                physics.Radius * 2,
                physics.Width / 2,
                physics.Radius * 2
            );
            
            // 配置轮子材质
            Renderer renderer = wheelMesh.GetComponent<Renderer>();
            renderer.material = Resources.Load<Material>("Materials/Car/Wheel");
            
            wheelMeshes[index] = wheelMesh;
        }

        private void InitializeSubsystems()
        {
            // 初始化输入系统
            inputSystem = gameObject.AddComponent<CarInputSystem>();
            inputSystem.Initialize(this);
            
            // 初始化音频系统
            audioSystem = gameObject.AddComponent<CarAudioSystem>();
            audioSystem.Initialize(this);
            
            // 初始化特效系统
            effectsSystem = gameObject.AddComponent<CarEffectsSystem>();
            effectsSystem.Initialize(this);
            
            // 初始化遥测系统
            telemetrySystem = gameObject.AddComponent<CarTelemetrySystem>();
            telemetrySystem.Initialize(this);
        }

        private void Update()
        {
            if (!simulationActive) return;
            
            float deltaTime = Time.deltaTime;
            simulationTime += deltaTime;
            simulationFrame++;
            
            // 处理输入
            ProcessInputs();
            
            // 更新物理模拟
            UpdatePhysics(deltaTime);
            
            // 更新子系统
            UpdateSubsystems(deltaTime);
            
            // 更新轮子视觉
            UpdateWheelVisuals();
            
            // 记录遥测数据
            telemetrySystem.RecordFrame(this);
        }

        private void ProcessInputs()
        {
            // 从输入系统获取输入
            throttleInput = inputSystem.GetThrottleInput();
            brakeInput = inputSystem.GetBrakeInput();
            steerInput = inputSystem.GetSteerInput();
            clutchInput = inputSystem.GetClutchInput();
            
            // 处理换挡
            if (inputSystem.GetShiftUp())
            {
                ShiftGear(1);
            }
            else if (inputSystem.GetShiftDown())
            {
                ShiftGear(-1);
            }
            
            // 处理引擎启动/停止
            if (inputSystem.GetEngineToggle())
            {
                ToggleEngine();
            }
        }

        private void UpdatePhysics(float deltaTime)
        {
            // 计算当前速度
            currentSpeed = carRigidbody.velocity.magnitude * 3.6f; // 转换为km/h
            
            // 计算引擎RPM
            CalculateEngineRPM();
            
            // 计算引擎扭矩
            CalculateEngineTorque();
            
            // 计算传动系统扭矩
            CalculateTransmissionTorque();
            
            // 应用扭矩到轮子
            ApplyWheelTorque();
            
            // 应用转向
            ApplySteering();
            
            // 应用刹车
            ApplyBraking();
            
            // 计算阻力
            CalculateResistances();
            
            // 更新空气动力学
            UpdateAerodynamics();
        }

        private void CalculateEngineRPM()
        {
            if (!isEngineRunning)
            {
                currentRPM = 0;
                return;
            }
            
            // 基于速度和档位计算RPM
            float wheelRPM = GetAverageWheelRPM();
            float gearRatio = currentGear > 0 ? 
                currentPhysicsProfile.Transmission.GearRatios[currentGear - 1] : 
                currentPhysicsProfile.Transmission.ReverseRatio;
            
            float driveRatio = gearRatio * currentPhysicsProfile.Transmission.FinalDriveRatio;
            
            currentRPM = wheelRPM * driveRatio;
            
            // 限制RPM范围
            currentRPM = Mathf.Clamp(
                currentRPM,
                currentPhysicsProfile.Engine.IdleRPM,
                currentPhysicsProfile.Engine.RedlineRPM
            );
            
            // 怠速控制
            if (throttleInput == 0 && currentRPM < currentPhysicsProfile.Engine.IdleRPM)
            {
                currentRPM = currentPhysicsProfile.Engine.IdleRPM;
            }
        }

        private void CalculateEngineTorque()
        {
            if (!isEngineRunning)
            {
                engineTorque = 0;
                return;
            }
            
            // 从扭矩曲线获取扭矩
            float rpmNormalized = (currentRPM - currentPhysicsProfile.Engine.IdleRPM) / 
                                 (currentPhysicsProfile.Engine.RedlineRPM - currentPhysicsProfile.Engine.IdleRPM);
            
            int curveIndex = Mathf.FloorToInt(rpmNormalized * (currentPhysicsProfile.Engine.TorqueCurve.Length - 1));
            curveIndex = Mathf.Clamp(curveIndex, 0, currentPhysicsProfile.Engine.TorqueCurve.Length - 1);
            
            engineTorque = currentPhysicsProfile.Engine.TorqueCurve[curveIndex];
            
            // 应用油门输入
            engineTorque *= throttleInput;
            
            // 应用离合器打滑
            if (clutchInput < 1f)
            {
                engineTorque *= clutchInput;
            }
        }

        private void CalculateTransmissionTorque()
        {
            if (currentGear == 0) // 空档
            {
                wheelTorque = 0;
                return;
            }
            
            float gearRatio = currentGear > 0 ? 
                currentPhysicsProfile.Transmission.GearRatios[currentGear - 1] : 
                currentPhysicsProfile.Transmission.ReverseRatio;
            
            float totalRatio = gearRatio * currentPhysicsProfile.Transmission.FinalDriveRatio;
            float transmissionEfficiency = 0.85f; // 传动效率
            
            wheelTorque = engineTorque * totalRatio * transmissionEfficiency;
        }

        private void ApplyWheelTorque()
        {
            // 根据驱动类型分配扭矩
            switch (currentPhysicsProfile.Transmission.Type)
            {
                case TransmissionType.FWD: // 前驱
                    ApplyTorqueToWheels(new[] { WheelPosition.FrontLeft, WheelPosition.FrontRight });
                    break;
                    
                case TransmissionType.RWD: // 后驱
                    ApplyTorqueToWheels(new[] { WheelPosition.RearLeft, WheelPosition.RearRight });
                    break;
                    
                case TransmissionType.AWD: // 全驱
                    ApplyTorqueToAllWheels();
                    break;
                    
                case TransmissionType.FourWD: // 四驱
                    ApplyTorqueToAllWheelsWithCenterDiff();
                    break;
            }
        }

        private void ApplyTorqueToWheels(WheelPosition[] positions)
        {
            float torquePerWheel = wheelTorque / positions.Length;
            
            foreach (var position in positions)
            {
                if (wheelData.ContainsKey(position))
                {
                    WheelData data = wheelData[position];
                    data.Collider.motorTorque = torquePerWheel;
                }
            }
        }

        private void ApplySteering()
        {
            foreach (var kvp in wheelData)
            {
                WheelData data = kvp.Value;
                
                if (data.Physics.IsSteering)
                {
                    float maxSteerAngle = data.Physics.MaxSteerAngle;
                    
                    // 根据速度调整转向角度(高速时减少转向)
                    float speedFactor = Mathf.Clamp01(1.0f - currentSpeed / 100f);
                    float actualSteerAngle = steerInput * maxSteerAngle * speedFactor;
                    
                    data.Collider.steerAngle = actualSteerAngle;
                }
            }
        }

        private void ApplyBraking()
        {
            float totalBrakeTorque = brakeInput * currentPhysicsProfile.Brakes.MaxTorque;
            float brakePerWheel = totalBrakeTorque / wheelData.Count;
            
            foreach (var kvp in wheelData)
            {
                kvp.Value.Collider.brakeTorque = brakePerWheel;
            }
        }

        private void CalculateResistances()
        {
            // 计算滚动阻力
            rollingResistance = CalculateRollingResistance();
            
            // 计算空气阻力
            aerodynamicDrag = CalculateAerodynamicDrag();
            
            // 应用阻力
            Vector3 resistanceForce = -carRigidbody.velocity.normalized * (rollingResistance + aerodynamicDrag);
            carRigidbody.AddForce(resistanceForce, ForceMode.Force);
        }

        private float CalculateRollingResistance()
        {
            // 滚动阻力 = 摩擦系数 * 质量 * 重力加速度
            float rollingCoefficient = 0.015f; // 典型轮胎滚动阻力系数
            return rollingCoefficient * currentPhysicsProfile.Mass * 9.81f;
        }

        private float CalculateAerodynamicDrag()
        {
            // 空气阻力 = 0.5 * 空气密度 * 阻力系数 * 迎风面积 * 速度²
            float airDensity = 1.225f; // kg/m³ (海平面)
            float dragCoefficient = currentPhysicsProfile.Aerodynamics.DragCoefficient;
            float frontalArea = currentPhysicsProfile.Aerodynamics.FrontalArea;
            float velocitySquared = carRigidbody.velocity.sqrMagnitude;
            
            return 0.5f * airDensity * dragCoefficient * frontalArea * velocitySquared;
        }

        private void UpdateWheelVisuals()
        {
            foreach (var kvp in wheelData)
            {
                WheelData data = kvp.Value;
                
                // 更新轮子位置
                data.Collider.GetWorldPose(out Vector3 position, out Quaternion rotation);
                
                if (data.Mesh != null)
                {
                    data.Mesh.transform.position = position;
                    data.Mesh.transform.rotation = rotation;
                    
                    // 根据转向调整轮子方向
                    if (data.Physics.IsSteering)
                    {
                        data.Mesh.transform.Rotate(Vector3.up, data.Collider.steerAngle);
                    }
                }
            }
        }

        /// <summary>
        /// 启动引擎
        /// </summary>
        public void StartEngine()
        {
            if (isEngineRunning) return;
            
            isEngineRunning = true;
            currentRPM = currentPhysicsProfile.Engine.IdleRPM;
            
            // 播放引擎启动音效
            audioSystem.PlayEngineStart();
            
            // 显示启动特效
            effectsSystem.PlayEngineStartEffect();
            
            Debug.Log("Engine started");
        }

        /// <summary>
        /// 关闭引擎
        /// </summary>
        public void StopEngine()
        {
            if (!isEngineRunning) return;
            
            isEngineRunning = false;
            currentRPM = 0;
            
            // 播放引擎关闭音效
            audioSystem.PlayEngineStop();
            
            // 停止所有扭矩输出
            foreach (var wheelCollider in wheelColliders)
            {
                wheelCollider.motorTorque = 0;
            }
            
            Debug.Log("Engine stopped");
        }

        /// <summary>
        /// 切换引擎状态
        /// </summary>
        public void ToggleEngine()
        {
            if (isEngineRunning)
            {
                StopEngine();
            }
            else
            {
                StartEngine();
            }
        }

        /// <summary>
        /// 换挡
        /// </summary>
        public void ShiftGear(int direction)
        {
            int newGear = currentGear + direction;
            
            // 检查档位范围
            if (newGear >= -1 && newGear <= currentPhysicsProfile.Transmission.Gears)
            {
                // 检查是否有倒档
                if (newGear == -1 && !currentPhysicsProfile.Transmission.HasReverse)
                {
                    return;
                }
                
                // 执行换挡
                PerformGearShift(newGear);
            }
        }

        private void PerformGearShift(int newGear)
        {
            int oldGear = currentGear;
            currentGear = newGear;
            
            // 播放换挡音效
            audioSystem.PlayGearShift(oldGear, newGear);
            
            // 记录换挡事件
            telemetrySystem.RecordGearShift(oldGear, newGear, currentSpeed, currentRPM);
            
            Debug.Log($"Shifted from gear {oldGear} to {newGear}");
        }

        /// <summary>
        /// 启用模拟
        /// </summary>
        public void EnableSimulation(bool enable)
        {
            simulationActive = enable;
            
            if (enable)
            {
                // 重置模拟状态
                simulationTime = 0f;
                simulationFrame = 0;
                
                // 开始遥测记录
                telemetrySystem.StartRecording();
                
                Debug.Log("Car simulation enabled");
            }
            else
            {
                // 停止遥测记录
                telemetrySystem.StopRecording();
                
                Debug.Log("Car simulation disabled");
            }
        }

        /// <summary>
        /// 获取汽车遥测数据
        /// </summary>
        public CarTelemetry GetTelemetryData()
        {
            return new CarTelemetry
            {
                Timestamp = DateTime.Now,
                Speed = currentSpeed,
                RPM = currentRPM,
                Gear = currentGear,
                Throttle = throttleInput,
                Brake = brakeInput,
                Steer = steerInput,
                EngineRunning = isEngineRunning,
                Position = transform.position,
                Rotation = transform.rotation,
                Velocity = carRigidbody.velocity,
                WheelData = GetWheelTelemetry()
            };
        }

        private Dictionary<WheelPosition, WheelTelemetry> GetWheelTelemetry()
        {
            Dictionary<WheelPosition, WheelTelemetry> telemetry = new Dictionary<WheelPosition, WheelTelemetry>();
            
            foreach (var kvp in wheelData)
            {
                WheelCollider collider = kvp.Value.Collider;
                
                telemetry[kvp.Key] = new WheelTelemetry
                {
                    RPM = collider.rpm,
                    Torque = collider.motorTorque,
                    BrakeTorque = collider.brakeTorque,
                    SteerAngle = collider.steerAngle,
                    IsGrounded = collider.isGrounded,
                    SuspensionForce = GetSuspensionForce(collider)
                };
            }
            
            return telemetry;
        }

        private void StartTelemetryRecording()
        {
            // 开始记录遥测数据
            InvokeRepeating("RecordTelemetrySnapshot", 0f, 0.1f); // 每秒10次
        }

        private void RecordTelemetrySnapshot()
        {
            if (!simulationActive) return;
            
            telemetrySystem.RecordSnapshot(GetTelemetryData());
        }

        /// <summary>
        /// 执行性能测试
        /// </summary>
        public PerformanceTestResult PerformAccelerationTest()
        {
            if (!simulationActive)
            {
                EnableSimulation(true);
            }
            
            // 重置汽车位置
            transform.position = Vector3.zero;
            transform.rotation = Quaternion.identity;
            carRigidbody.velocity = Vector3.zero;
            carRigidbody.angularVelocity = Vector3.zero;
            
            // 确保引擎运行
            if (!isEngineRunning)
            {
                StartEngine();
            }
            
            // 设置到一档
            currentGear = 1;
            
            // 开始加速测试
            return StartAccelerationTestCoroutine();
        }

        private PerformanceTestResult StartAccelerationTestCoroutine()
        {
            PerformanceTestResult result = new PerformanceTestResult
            {
                TestStartTime = DateTime.Now,
                CarModelId = currentPhysicsProfile.CarModelId,
                TestType = PerformanceTestType.ZeroToHundred
            };
            
            StartCoroutine(RunAccelerationTest(result));
            
            return result;
        }

        private System.Collections.IEnumerator RunAccelerationTest(PerformanceTestResult result)
        {
            List<AccelerationPoint> accelerationPoints = new List<AccelerationPoint>();
            
            // 全油门
            throttleInput = 1.0f;
            brakeInput = 0.0f;
            
            float startTime = Time.time;
            float targetSpeed = 100f; // 100 km/h
            
            while (currentSpeed < targetSpeed)
            {
                // 记录数据点
                accelerationPoints.Add(new AccelerationPoint
                {
                    Time = Time.time - startTime,
                    Speed = currentSpeed,
                    RPM = currentRPM,
                    Gear = currentGear
                });
                
                // 检查换挡点
                if (currentRPM >= currentPhysicsProfile.Engine.RedlineRPM * 0.9f)
                {
                    ShiftGear(1);
                }
                
                yield return new WaitForSeconds(0.01f); // 100Hz采样
            }
            
            // 记录结果
            result.TestEndTime = DateTime.Now;
            result.AccelerationData = accelerationPoints.ToArray();
            result.ZeroToHundredTime = Time.time - startTime;
            result.MaxSpeedReached = currentSpeed;
            
            // 重置输入
            throttleInput = 0f;
            
            // 触发测试完成事件
            OnPerformanceTestComplete?.Invoke(result);
            
            // 记录分析
            AnalyticsService.RecordPerformanceTest(result);
        }

        public event Action<PerformanceTestResult> OnPerformanceTestComplete;
    }

    /// <summary>
    /// 轮子数据
    /// </summary>
    public class WheelData
    {
        public WheelPhysics Physics;
        public WheelCollider Collider;
        public GameObject Mesh;
        public WheelPosition Position;
        public float CurrentRPM;
        public float CurrentTorque;
        public bool IsLocked;
    }

    /// <summary>
    /// 汽车遥测数据
    /// </summary>
    [System.Serializable]
    public class CarTelemetry
    {
        public DateTime Timestamp;
        public float Speed; // km/h
        public float RPM;
        public int Gear;
        public float Throttle;
        public float Brake;
        public float Steer;
        public bool EngineRunning;
        public Vector3 Position;
        public Quaternion Rotation;
        public Vector3 Velocity;
        public Dictionary<WheelPosition, WheelTelemetry> WheelData;
        public float EngineTemperature;
        public float OilPressure;
        public float FuelLevel;
    }

    /// <summary>
    /// 轮子遥测数据
    /// </summary>
    [System.Serializable]
    public class WheelTelemetry
    {
        public float RPM;
        public float Torque;
        public float BrakeTorque;
        public float SteerAngle;
        public bool IsGrounded;
        public float SuspensionForce;
        public float SlipRatio;
        public float SlipAngle;
    }

    /// <summary>
    /// 性能测试结果
    /// </summary>
    [System.Serializable]
    public class PerformanceTestResult
    {
        public DateTime TestStartTime;
        public DateTime TestEndTime;
        public string CarModelId;
        public PerformanceTestType TestType;
        public float ZeroToHundredTime; // 0-100km/h加速时间
        public float QuarterMileTime; // 1/4英里加速时间
        public float MaxSpeedReached;
        public float BrakingDistance; // 100-0km/h制动距离
        public AccelerationPoint[] AccelerationData;
        public Dictionary<string, object> AdditionalMetrics;
    }

    [System.Serializable]
    public class AccelerationPoint
    {
        public float Time;
        public float Speed;
        public float RPM;
        public int Gear;
    }

    public enum PerformanceTestType
    {
        ZeroToHundred,
        QuarterMile,
        BrakingTest,
        SlalomTest,
        SkidpadTest,
        TopSpeed
    }

    public enum WheelPosition
    {
        FrontLeft,
        FrontRight,
        RearLeft,
        RearRight
    }

    public enum EngineType
    {
        Gasoline,
        Diesel,
        Electric,
        Hybrid,
        Hydrogen
    }

    public enum TransmissionType
    {
        Manual,
        Automatic,
        CVT,
        DCT,
        FWD, // 前驱
        RWD, // 后驱
        AWD, // 全驱
        FourWD // 四驱
    }

    [System.Serializable]
    public class BrakeSpecification
    {
        public BrakeType Type;
        public float MaxTorque; // 最大制动力矩 (Nm)
        public float DiscDiameter; // 刹车盘直径 (mm)
        public bool HasABS;
        public bool HasESC;
        public float BrakeBias; // 制动力分配 (前/后)
    }

    public enum BrakeType
    {
        Disc,
        Drum,
        Ceramic,
        CarbonCeramic
    }

    [System.Serializable]
    public class SuspensionSpecification
    {
        public SuspensionType Type;
        public float SpringRate;
        public float DamperRate;
        public float AntiRollBarStiffness;
        public float RideHeight;
        public bool HasAdaptiveDamping;
        public bool HasAirSuspension;
    }

    public enum SuspensionType
    {
        McPherson,
        DoubleWishbone,
        MultiLink,
        TrailingArm,
        SolidAxle
    }

    [System.Serializable]
    public class AerodynamicsSpecification
    {
        public float DragCoefficient;
        public float FrontalArea; // 迎风面积 (m²)
        public float LiftCoefficient;
        public bool HasActiveAero;
        public float DownforceAtSpeed; // 在特定速度下的下压力
        public float ReferenceSpeed; // 参考速度 (km/h)
    }
}

以上内容详细介绍了工业级汽车混合现实展示系统的深度开发,涵盖了系统架构设计、资源管理、多媒体播放和动态模拟等关键领域。每个部分都提供了详细的Unity C#实现代码,并针对工业应用场景进行了优化。这些代码可以在Unity 2021.3.8f1c1和VS2022/VSCode中正确运行。

Logo

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

更多推荐