007-游戏循环及实时模拟

游戏循环及实时模拟

游戏循环是游戏程序的核心,它负责持续更新游戏状态并将结果渲染到屏幕上。本章将详细介绍游戏循环的设计与实现,以及在实时游戏中的各种应用技术。

7.1 渲染循环

渲染循环是游戏引擎的心脏,负责将游戏世界的状态转换为玩家可见的画面。一个高效的渲染循环对于提供流畅的游戏体验至关重要。

基本渲染循环结构

csharp

public class GameLoop : MonoBehaviour
{
    private float targetFrameRate = 60.0f;
    private float targetFrameTime;
    
    void Start()
    {
        // 设置目标帧率
        targetFrameTime = 1.0f / targetFrameRate;
        Application.targetFrameRate = (int)targetFrameRate;
    }
    
    void Update()
    {
        // 游戏逻辑更新
        UpdateGameLogic(Time.deltaTime);
        
        // 输入处理
        ProcessInput();
        
        // 物理模拟(如果不使用FixedUpdate)
        UpdatePhysicsSimulation(Time.deltaTime);
    }
    
    void LateUpdate()
    {
        // 相机更新
        UpdateCameras();
        
        // UI更新
        UpdateUI();
    }
    
    void OnRenderObject()
    {
        // 自定义渲染
        CustomRender();
    }
}

高级渲染循环实现

csharp

public class AdvancedRenderLoop : MonoBehaviour
{
    // 渲染统计
    private class RenderStats
    {
        public int frameCount;
        public float totalFrameTime;
        public float minFrameTime = float.MaxValue;
        public float maxFrameTime = float.MinValue;
        public float averageFPS;
        
        public void Update(float frameTime)
        {
            frameCount++;
            totalFrameTime += frameTime;
            minFrameTime = Mathf.Min(minFrameTime, frameTime);
            maxFrameTime = Mathf.Max(maxFrameTime, frameTime);
            averageFPS = frameCount / totalFrameTime;
        }
    }
    
    private RenderStats stats = new RenderStats();
    private float lastFrameTime;
    
    // 渲染队列
    private Queue<RenderCommand> renderQueue = new Queue<RenderCommand>();
    
    // 渲染命令基类
    public abstract class RenderCommand
    {
        public abstract void Execute();
    }
    
    // 具体渲染命令示例
    public class DrawMeshCommand : RenderCommand
    {
        public Mesh mesh;
        public Material material;
        public Matrix4x4 matrix;
        
        public override void Execute()
        {
            Graphics.DrawMesh(mesh, matrix, material, 0);
        }
    }
    
    void Update()
    {
        float currentTime = Time.realtimeSinceStartup;
        float frameTime = currentTime - lastFrameTime;
        lastFrameTime = currentTime;
        
        // 更新统计信息
        stats.Update(frameTime);
        
        // 性能监控
        if (frameTime > targetFrameTime * 1.5f)
        {
            Debug.LogWarning($"Frame time spike: {frameTime * 1000}ms");
        }
        
        // 处理渲染队列
        ProcessRenderQueue();
    }
    
    private void ProcessRenderQueue()
    {
        int commandCount = renderQueue.Count;
        for (int i = 0; i < commandCount; i++)
        {
            RenderCommand command = renderQueue.Dequeue();
            command.Execute();
        }
    }
    
    public void EnqueueRenderCommand(RenderCommand command)
    {
        renderQueue.Enqueue(command);
    }
}

多线程渲染优化

csharp

public class MultiThreadedRenderer : MonoBehaviour
{
    private readonly object renderLock = new object();
    private List<RenderBatch> renderBatches = new List<RenderBatch>();
    private Thread renderThread;
    private bool isRunning = true;
    
    public class RenderBatch
    {
        public List<Matrix4x4> matrices = new List<Matrix4x4>();
        public Mesh mesh;
        public Material material;
        
        public void Render()
        {
            if (matrices.Count > 0)
            {
                Graphics.DrawMeshInstanced(mesh, 0, material, matrices);
            }
        }
    }
    
    void Start()
    {
        // 启动渲染线程
        renderThread = new Thread(RenderThreadFunction);
        renderThread.Start();
    }
    
    void RenderThreadFunction()
    {
        while (isRunning)
        {
            List<RenderBatch> batchesToRender = null;
            
            lock (renderLock)
            {
                if (renderBatches.Count > 0)
                {
                    batchesToRender = new List<RenderBatch>(renderBatches);
                    renderBatches.Clear();
                }
            }
            
            if (batchesToRender != null)
            {
                foreach (var batch in batchesToRender)
                {
                    batch.Render();
                }
            }
            
            Thread.Sleep(1); // 避免CPU占用过高
        }
    }
    
    public void AddRenderBatch(RenderBatch batch)
    {
        lock (renderLock)
        {
            renderBatches.Add(batch);
        }
    }
    
    void OnDestroy()
    {
        isRunning = false;
        renderThread?.Join();
    }
}

渲染优化技术

csharp

public class RenderOptimizer : MonoBehaviour
{
    [System.Serializable]
    public class LODSettings
    {
        public float[] distances = { 10f, 25f, 50f, 100f };
        public int[] qualityLevels = { 3, 2, 1, 0 };
    }
    
    public LODSettings lodSettings;
    private Camera mainCamera;
    private Dictionary<Renderer, int> currentLODLevels = new Dictionary<Renderer, int>();
    
    // 视锥体剔除
    public class FrustumCuller
    {
        private Plane[] frustumPlanes;
        
        public void UpdateFrustumPlanes(Camera camera)
        {
            frustumPlanes = GeometryUtility.CalculateFrustumPlanes(camera);
        }
        
        public bool IsVisible(Bounds bounds)
        {
            return GeometryUtility.TestPlanesAABB(frustumPlanes, bounds);
        }
    }
    
    private FrustumCuller frustumCuller = new FrustumCuller();
    
    // 遮挡剔除
    public class OcclusionCuller
    {
        private RenderTexture depthTexture;
        private ComputeShader occlusionShader;
        
        public void Initialize(int width, int height)
        {
            depthTexture = new RenderTexture(width, height, 24, 
                RenderTextureFormat.Depth);
            // 加载遮挡剔除计算着色器
            occlusionShader = Resources.Load<ComputeShader>("OcclusionCulling");
        }
        
        public bool IsOccluded(Bounds bounds)
        {
            // 实现遮挡测试逻辑
            // 这里简化处理,实际需要复杂的GPU计算
            return false;
        }
    }
    
    void Start()
    {
        mainCamera = Camera.main;
    }
    
    void Update()
    {
        // 更新视锥体平面
        frustumCuller.UpdateFrustumPlanes(mainCamera);
        
        // 处理场景中的所有渲染器
        Renderer[] renderers = FindObjectsOfType<Renderer>();
        
        foreach (var renderer in renderers)
        {
            // 视锥体剔除
            if (!frustumCuller.IsVisible(renderer.bounds))
            {
                renderer.enabled = false;
                continue;
            }
            
            renderer.enabled = true;
            
            // LOD处理
            UpdateLOD(renderer);
            
            // 批处理优化
            OptimizeBatching(renderer);
        }
    }
    
    private void UpdateLOD(Renderer renderer)
    {
        float distance = Vector3.Distance(mainCamera.transform.position, 
            renderer.transform.position);
        
        int lodLevel = 0;
        for (int i = 0; i < lodSettings.distances.Length; i++)
        {
            if (distance > lodSettings.distances[i])
            {
                lodLevel = i;
            }
        }
        
        // 应用LOD级别
        if (currentLODLevels.ContainsKey(renderer))
        {
            if (currentLODLevels[renderer] != lodLevel)
            {
                ApplyLODLevel(renderer, lodLevel);
                currentLODLevels[renderer] = lodLevel;
            }
        }
        else
        {
            currentLODLevels.Add(renderer, lodLevel);
            ApplyLODLevel(renderer, lodLevel);
        }
    }
    
    private void ApplyLODLevel(Renderer renderer, int level)
    {
        // 应用LOD设置
        // 例如:切换模型、调整着色器质量等
        LODGroup lodGroup = renderer.GetComponent<LODGroup>();
        if (lodGroup != null)
        {
            // Unity内置LOD系统会自动处理
        }
    }
    
    private void OptimizeBatching(Renderer renderer)
    {
        // 动态批处理优化
        if (renderer.sharedMaterial != null)
        {
            // 确保使用共享材质
            renderer.material = renderer.sharedMaterial;
        }
        
        // 设置合适的静态标记
        if (!renderer.GetComponent<Rigidbody>())
        {
            renderer.gameObject.isStatic = true;
        }
    }
}

7.2 游戏循环

游戏循环是游戏运行的主体框架,负责协调游戏中的各个系统,确保游戏状态的正确更新和渲染。

固定时间步长游戏循环

csharp

public class FixedTimeStepGameLoop : MonoBehaviour
{
    public float fixedDeltaTime = 0.016667f; // 60 FPS
    private float accumulator = 0.0f;
    private float currentTime = 0.0f;
    private float frameStart;
    
    // 游戏状态
    public class GameState
    {
        public Vector3 playerPosition;
        public Quaternion playerRotation;
        public float gameTime;
        
        public GameState Clone()
        {
            return new GameState
            {
                playerPosition = playerPosition,
                playerRotation = playerRotation,
                gameTime = gameTime
            };
        }
        
        public static GameState Interpolate(GameState a, GameState b, float t)
        {
            return new GameState
            {
                playerPosition = Vector3.Lerp(a.playerPosition, b.playerPosition, t),
                playerRotation = Quaternion.Slerp(a.playerRotation, b.playerRotation, t),
                gameTime = Mathf.Lerp(a.gameTime, b.gameTime, t)
            };
        }
    }
    
    private GameState previousState = new GameState();
    private GameState currentState = new GameState();
    
    void Start()
    {
        frameStart = Time.realtimeSinceStartup;
        Time.fixedDeltaTime = fixedDeltaTime;
    }
    
    void Update()
    {
        float frameTime = Time.realtimeSinceStartup - frameStart;
        frameStart = Time.realtimeSinceStartup;
        
        // 防止螺旋死亡
        frameTime = Mathf.Min(frameTime, 0.25f);
        
        accumulator += frameTime;
        
        // 固定时间步长更新
        while (accumulator >= fixedDeltaTime)
        {
            previousState = currentState.Clone();
            
            // 更新游戏逻辑
            UpdateGameLogic(fixedDeltaTime);
            
            currentTime += fixedDeltaTime;
            accumulator -= fixedDeltaTime;
        }
        
        // 插值渲染
        float interpolation = accumulator / fixedDeltaTime;
        GameState interpolatedState = GameState.Interpolate(previousState, 
            currentState, interpolation);
        
        // 渲染插值状态
        RenderGameState(interpolatedState);
    }
    
    private void UpdateGameLogic(float deltaTime)
    {
        // 更新物理
        UpdatePhysics(deltaTime);
        
        // 更新AI
        UpdateAI(deltaTime);
        
        // 更新游戏规则
        UpdateGameRules(deltaTime);
        
        currentState.gameTime = currentTime;
    }
    
    private void UpdatePhysics(float deltaTime)
    {
        // 物理更新逻辑
    }
    
    private void UpdateAI(float deltaTime)
    {
        // AI更新逻辑
    }
    
    private void UpdateGameRules(float deltaTime)
    {
        // 游戏规则更新
    }
    
    private void RenderGameState(GameState state)
    {
        // 根据插值状态渲染
        transform.position = state.playerPosition;
        transform.rotation = state.playerRotation;
    }
}

变时间步长游戏循环

csharp

public class VariableTimeStepGameLoop : MonoBehaviour
{
    private float maxDeltaTime = 0.1f; // 最大时间步长
    private float timeScale = 1.0f;
    
    // 时间管理器
    public class TimeManager
    {
        public float deltaTime { get; private set; }
        public float unscaledDeltaTime { get; private set; }
        public float time { get; private set; }
        public float unscaledTime { get; private set; }
        public float timeScale = 1.0f;
        
        private float lastFrameTime;
        
        public void Update()
        {
            float currentTime = Time.realtimeSinceStartup;
            unscaledDeltaTime = currentTime - lastFrameTime;
            unscaledDeltaTime = Mathf.Min(unscaledDeltaTime, 0.1f); // 防止过大
            
            deltaTime = unscaledDeltaTime * timeScale;
            time += deltaTime;
            unscaledTime += unscaledDeltaTime;
            
            lastFrameTime = currentTime;
        }
        
        public void SetTimeScale(float scale)
        {
            timeScale = Mathf.Max(0, scale);
        }
    }
    
    private TimeManager timeManager = new TimeManager();
    
    // 子系统更新优先级
    private enum UpdatePriority
    {
        Input = 0,
        Physics = 1,
        AI = 2,
        Animation = 3,
        Rendering = 4
    }
    
    private class UpdateSystem
    {
        public UpdatePriority priority;
        public System.Action<float> updateAction;
        public bool isActive = true;
    }
    
    private List<UpdateSystem> updateSystems = new List<UpdateSystem>();
    
    void Start()
    {
        // 注册更新系统
        RegisterUpdateSystem(UpdatePriority.Input, UpdateInput);
        RegisterUpdateSystem(UpdatePriority.Physics, UpdatePhysics);
        RegisterUpdateSystem(UpdatePriority.AI, UpdateAI);
        RegisterUpdateSystem(UpdatePriority.Animation, UpdateAnimation);
        RegisterUpdateSystem(UpdatePriority.Rendering, UpdateRendering);
        
        // 按优先级排序
        updateSystems.Sort((a, b) => a.priority.CompareTo(b.priority));
    }
    
    void Update()
    {
        // 更新时间
        timeManager.Update();
        
        // 执行所有活跃的更新系统
        foreach (var system in updateSystems)
        {
            if (system.isActive)
            {
                system.updateAction(timeManager.deltaTime);
            }
        }
        
        // 性能监控
        MonitorPerformance();
    }
    
    private void RegisterUpdateSystem(UpdatePriority priority, 
        System.Action<float> updateAction)
    {
        updateSystems.Add(new UpdateSystem
        {
            priority = priority,
            updateAction = updateAction,
            isActive = true
        });
    }
    
    private void UpdateInput(float deltaTime)
    {
        // 处理输入
    }
    
    private void UpdatePhysics(float deltaTime)
    {
        // 物理更新
        // 可能需要细分为多个固定步长
        float fixedDeltaTime = 0.02f;
        float physicsAccumulator = deltaTime;
        
        while (physicsAccumulator >= fixedDeltaTime)
        {
            // 执行固定步长物理
            Physics.Simulate(fixedDeltaTime);
            physicsAccumulator -= fixedDeltaTime;
        }
    }
    
    private void UpdateAI(float deltaTime)
    {
        // AI更新
    }
    
    private void UpdateAnimation(float deltaTime)
    {
        // 动画更新
    }
    
    private void UpdateRendering(float deltaTime)
    {
        // 渲染准备
    }
    
    private void MonitorPerformance()
    {
        if (timeManager.deltaTime > maxDeltaTime)
        {
            Debug.LogWarning($"Frame time exceeded max: {timeManager.deltaTime}s");
        }
    }
}

7.3 游戏循环的架构风格

游戏循环的架构设计直接影响游戏的性能、可维护性和扩展性。

组件化游戏循环架构

csharp

public class ComponentBasedGameLoop : MonoBehaviour
{
    // 游戏组件接口
    public interface IGameComponent
    {
        bool Enabled { get; set; }
        int UpdateOrder { get; }
        void Initialize();
        void Update(float deltaTime);
        void Destroy();
    }
    
    // 可绘制组件接口
    public interface IDrawableComponent : IGameComponent
    {
        int DrawOrder { get; }
        void Draw();
    }
    
    // 组件管理器
    public class ComponentManager
    {
        private List<IGameComponent> components = new List<IGameComponent>();
        private List<IDrawableComponent> drawableComponents = new List<IDrawableComponent>();
        private bool isInitialized = false;
        
        public void AddComponent(IGameComponent component)
        {
            components.Add(component);
            
            if (component is IDrawableComponent drawable)
            {
                drawableComponents.Add(drawable);
            }
            
            if (isInitialized)
            {
                component.Initialize();
            }
            
            // 重新排序
            SortComponents();
        }
        
        public void RemoveComponent(IGameComponent component)
        {
            component.Destroy();
            components.Remove(component);
            
            if (component is IDrawableComponent drawable)
            {
                drawableComponents.Remove(drawable);
            }
        }
        
        public void Initialize()
        {
            foreach (var component in components)
            {
                component.Initialize();
            }
            isInitialized = true;
        }
        
        public void Update(float deltaTime)
        {
            foreach (var component in components)
            {
                if (component.Enabled)
                {
                    component.Update(deltaTime);
                }
            }
        }
        
        public void Draw()
        {
            foreach (var drawable in drawableComponents)
            {
                if (drawable.Enabled)
                {
                    drawable.Draw();
                }
            }
        }
        
        private void SortComponents()
        {
            components.Sort((a, b) => a.UpdateOrder.CompareTo(b.UpdateOrder));
            drawableComponents.Sort((a, b) => a.DrawOrder.CompareTo(b.DrawOrder));
        }
    }
    
    // 示例组件:输入系统
    public class InputComponent : IGameComponent
    {
        public bool Enabled { get; set; } = true;
        public int UpdateOrder => 0; // 最先更新
        
        public void Initialize()
        {
            Debug.Log("Input system initialized");
        }
        
        public void Update(float deltaTime)
        {
            // 处理输入
            if (Input.GetKeyDown(KeyCode.Space))
            {
                Debug.Log("Space pressed");
            }
        }
        
        public void Destroy()
        {
            Debug.Log("Input system destroyed");
        }
    }
    
    // 示例组件:物理系统
    public class PhysicsComponent : IGameComponent
    {
        public bool Enabled { get; set; } = true;
        public int UpdateOrder => 1;
        
        private float accumulator = 0f;
        private const float FixedTimeStep = 0.02f;
        
        public void Initialize()
        {
            Physics.autoSimulation = false;
        }
        
        public void Update(float deltaTime)
        {
            accumulator += deltaTime;
            
            while (accumulator >= FixedTimeStep)
            {
                Physics.Simulate(FixedTimeStep);
                accumulator -= FixedTimeStep;
            }
        }
        
        public void Destroy()
        {
            Physics.autoSimulation = true;
        }
    }
    
    private ComponentManager componentManager = new ComponentManager();
    
    void Start()
    {
        // 添加游戏组件
        componentManager.AddComponent(new InputComponent());
        componentManager.AddComponent(new PhysicsComponent());
        
        // 初始化所有组件
        componentManager.Initialize();
    }
    
    void Update()
    {
        componentManager.Update(Time.deltaTime);
    }
    
    void LateUpdate()
    {
        componentManager.Draw();
    }
}

事件驱动游戏循环

csharp

public class EventDrivenGameLoop : MonoBehaviour
{
    // 事件系统
    public class EventSystem
    {
        private Dictionary<System.Type, System.Delegate> eventHandlers = 
            new Dictionary<System.Type, System.Delegate>();
        
        public void Subscribe<T>(System.Action<T> handler) where T : IGameEvent
        {
            System.Type eventType = typeof(T);
            
            if (eventHandlers.ContainsKey(eventType))
            {
                eventHandlers[eventType] = 
                    System.Delegate.Combine(eventHandlers[eventType], handler);
            }
            else
            {
                eventHandlers[eventType] = handler;
            }
        }
        
        public void Unsubscribe<T>(System.Action<T> handler) where T : IGameEvent
        {
            System.Type eventType = typeof(T);
            
            if (eventHandlers.ContainsKey(eventType))
            {
                eventHandlers[eventType] = 
                    System.Delegate.Remove(eventHandlers[eventType], handler);
            }
        }
        
        public void Publish<T>(T gameEvent) where T : IGameEvent
        {
            System.Type eventType = typeof(T);
            
            if (eventHandlers.ContainsKey(eventType))
            {
                var handler = eventHandlers[eventType] as System.Action<T>;
                handler?.Invoke(gameEvent);
            }
        }
    }
    
    // 游戏事件接口
    public interface IGameEvent
    {
        float Timestamp { get; }
    }
    
    // 具体事件示例
    public class InputEvent : IGameEvent
    {
        public float Timestamp { get; }
        public KeyCode Key { get; }
        public bool IsPressed { get; }
        
        public InputEvent(KeyCode key, bool isPressed)
        {
            Timestamp = Time.time;
            Key = key;
            IsPressed = isPressed;
        }
    }
    
    public class CollisionEvent : IGameEvent
    {
        public float Timestamp { get; }
        public GameObject Object1 { get; }
        public GameObject Object2 { get; }
        public Vector3 CollisionPoint { get; }
        
        public CollisionEvent(GameObject obj1, GameObject obj2, Vector3 point)
        {
            Timestamp = Time.time;
            Object1 = obj1;
            Object2 = obj2;
            CollisionPoint = point;
        }
    }
    
    public class GameStateChangeEvent : IGameEvent
    {
        public float Timestamp { get; }
        public string OldState { get; }
        public string NewState { get; }
        
        public GameStateChangeEvent(string oldState, string newState)
        {
            Timestamp = Time.time;
            OldState = oldState;
            NewState = newState;
        }
    }
    
    private EventSystem eventSystem = new EventSystem();
    
    // 游戏状态机
    public class GameStateMachine
    {
        private EventSystem eventSystem;
        private string currentState = "Menu";
        
        public GameStateMachine(EventSystem eventSystem)
        {
            this.eventSystem = eventSystem;
        }
        
        public void ChangeState(string newState)
        {
            string oldState = currentState;
            currentState = newState;
            
            eventSystem.Publish(new GameStateChangeEvent(oldState, newState));
        }
    }
    
    private GameStateMachine stateMachine;
    
    void Start()
    {
        stateMachine = new GameStateMachine(eventSystem);
        
        // 订阅事件
        eventSystem.Subscribe<InputEvent>(OnInputEvent);
        eventSystem.Subscribe<CollisionEvent>(OnCollisionEvent);
        eventSystem.Subscribe<GameStateChangeEvent>(OnStateChange);
    }
    
    void Update()
    {
        // 检测输入并发布事件
        if (Input.GetKeyDown(KeyCode.Space))
        {
            eventSystem.Publish(new InputEvent(KeyCode.Space, true));
        }
        
        // 主游戏循环逻辑
        UpdateGameSystems();
    }
    
    private void UpdateGameSystems()
    {
        // 各系统独立更新,通过事件通信
    }
    
    private void OnInputEvent(InputEvent e)
    {
        Debug.Log($"Input event: {e.Key} pressed at {e.Timestamp}");
    }
    
    private void OnCollisionEvent(CollisionEvent e)
    {
        Debug.Log($"Collision between {e.Object1.name} and {e.Object2.name}");
    }
    
    private void OnStateChange(GameStateChangeEvent e)
    {
        Debug.Log($"State changed from {e.OldState} to {e.NewState}");
    }
}

多线程游戏循环架构

csharp

public class MultiThreadedGameLoop : MonoBehaviour
{
    // 线程安全的任务队列
    public class ThreadSafeTaskQueue<T>
    {
        private Queue<T> queue = new Queue<T>();
        private object lockObject = new object();
        
        public void Enqueue(T item)
        {
            lock (lockObject)
            {
                queue.Enqueue(item);
            }
        }
        
        public bool TryDequeue(out T item)
        {
            lock (lockObject)
            {
                if (queue.Count > 0)
                {
                    item = queue.Dequeue();
                    return true;
                }
                item = default(T);
                return false;
            }
        }
        
        public int Count
        {
            get
            {
                lock (lockObject)
                {
                    return queue.Count;
                }
            }
        }
    }
    
    // 工作线程任务
    public abstract class WorkerTask
    {
        public abstract void Execute();
    }
    
    // AI计算任务
    public class AICalculationTask : WorkerTask
    {
        public GameObject target;
        public Vector3 result;
        
        public override void Execute()
        {
            // 执行AI计算(pathfinding等)
            // 这里简化处理
            result = target.transform.position + Random.insideUnitSphere * 5;
        }
    }
    
    // 物理预测任务
    public class PhysicsPredictionTask : WorkerTask
    {
        public Rigidbody rigidbody;
        public float timeStep;
        public Vector3 predictedPosition;
        
        public override void Execute()
        {
            // 预测物理对象位置
            predictedPosition = rigidbody.position + 
                rigidbody.velocity * timeStep;
        }
    }
    
    // 工作线程池
    public class WorkerThreadPool
    {
        private Thread[] threads;
        private ThreadSafeTaskQueue<WorkerTask> taskQueue;
        private bool isRunning = true;
        
        public WorkerThreadPool(int threadCount)
        {
            taskQueue = new ThreadSafeTaskQueue<WorkerTask>();
            threads = new Thread[threadCount];
            
            for (int i = 0; i < threadCount; i++)
            {
                threads[i] = new Thread(WorkerThreadFunction)
                {
                    Name = $"WorkerThread_{i}"
                };
                threads[i].Start();
            }
        }
        
        private void WorkerThreadFunction()
        {
            while (isRunning)
            {
                WorkerTask task;
                if (taskQueue.TryDequeue(out task))
                {
                    try
                    {
                        task.Execute();
                    }
                    catch (Exception e)
                    {
                        Debug.LogError($"Worker task error: {e}");
                    }
                }
                else
                {
                    Thread.Sleep(1);
                }
            }
        }
        
        public void QueueTask(WorkerTask task)
        {
            taskQueue.Enqueue(task);
        }
        
        public void Shutdown()
        {
            isRunning = false;
            foreach (var thread in threads)
            {
                thread.Join();
            }
        }
    }
    
    private WorkerThreadPool threadPool;
    private ThreadSafeTaskQueue<WorkerTask> completedTasks;
    
    void Start()
    {
        int workerCount = SystemInfo.processorCount - 1; // 留一个给主线程
        threadPool = new WorkerThreadPool(Mathf.Max(1, workerCount));
        completedTasks = new ThreadSafeTaskQueue<WorkerTask>();
    }
    
    void Update()
    {
        // 主线程:分发任务
        DispatchTasks();
        
        // 主线程:处理完成的任务
        ProcessCompletedTasks();
        
        // 主线程:更新Unity对象
        UpdateUnityObjects();
    }
    
    private void DispatchTasks()
    {
        // 分发AI任务
        GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");
        foreach (var enemy in enemies)
        {
            var task = new AICalculationTask { target = enemy };
            threadPool.QueueTask(task);
        }
    }
    
    private void ProcessCompletedTasks()
    {
        WorkerTask task;
        while (completedTasks.TryDequeue(out task))
        {
            if (task is AICalculationTask aiTask)
            {
                // 应用AI计算结果
                aiTask.target.transform.position = 
                    Vector3.Lerp(aiTask.target.transform.position, 
                    aiTask.result, Time.deltaTime);
            }
        }
    }
    
    private void UpdateUnityObjects()
    {
        // 只在主线程更新Unity对象
    }
    
    void OnDestroy()
    {
        threadPool?.Shutdown();
    }
}

7.4 抽象时间线

抽象时间线允许游戏中不同系统以不同的时间速率运行,实现慢动作、快进等效果。

时间线系统实现

csharp

public class TimelineSystem : MonoBehaviour
{
    // 时间线定义
    public class Timeline
    {
        public string name;
        public float timeScale = 1.0f;
        public float currentTime = 0.0f;
        public bool isPaused = false;
        
        private List<TimelineEvent> events = new List<TimelineEvent>();
        private List<ITimelineUpdateable> updateables = new List<ITimelineUpdateable>();
        
        public void Update(float deltaTime)
        {
            if (!isPaused)
            {
                float scaledDelta = deltaTime * timeScale;
                currentTime += scaledDelta;
                
                // 更新所有可更新对象
                foreach (var updateable in updateables)
                {
                    updateable.UpdateTimeline(scaledDelta);
                }
                
                // 处理时间线事件
                ProcessEvents();
            }
        }
        
        public void RegisterUpdateable(ITimelineUpdateable updateable)
        {
            if (!updateables.Contains(updateable))
            {
                updateables.Add(updateable);
            }
        }
        
        public void UnregisterUpdateable(ITimelineUpdateable updateable)
        {
            updateables.Remove(updateable);
        }
        
        public void ScheduleEvent(TimelineEvent timelineEvent)
        {
            events.Add(timelineEvent);
            events.Sort((a, b) => a.triggerTime.CompareTo(b.triggerTime));
        }
        
        private void ProcessEvents()
        {
            while (events.Count > 0 && events[0].triggerTime <= currentTime)
            {
                TimelineEvent evt = events[0];
                events.RemoveAt(0);
                evt.Execute();
            }
        }
    }
    
    // 时间线事件
    public abstract class TimelineEvent
    {
        public float triggerTime;
        public abstract void Execute();
    }
    
    // 可更新接口
    public interface ITimelineUpdateable
    {
        void UpdateTimeline(float deltaTime);
    }
    
    // 时间线管理器
    private Dictionary<string, Timeline> timelines = new Dictionary<string, Timeline>();
    private Timeline globalTimeline;
    
    void Start()
    {
        // 创建全局时间线
        globalTimeline = new Timeline { name = "Global" };
        timelines["Global"] = globalTimeline;
        
        // 创建其他时间线
        CreateTimeline("Player", 1.0f);
        CreateTimeline("Enemy", 1.0f);
        CreateTimeline("Environment", 1.0f);
        CreateTimeline("UI", 1.0f);
    }
    
    public Timeline CreateTimeline(string name, float initialTimeScale = 1.0f)
    {
        if (!timelines.ContainsKey(name))
        {
            Timeline timeline = new Timeline
            {
                name = name,
                timeScale = initialTimeScale
            };
            timelines[name] = timeline;
            return timeline;
        }
        return timelines[name];
    }
    
    public Timeline GetTimeline(string name)
    {
        return timelines.ContainsKey(name) ? timelines[name] : null;
    }
    
    void Update()
    {
        float deltaTime = Time.deltaTime;
        
        // 更新所有时间线
        foreach (var timeline in timelines.Values)
        {
            timeline.Update(deltaTime);
        }
    }
    
    // 时间操纵功能
    public void SetTimeScale(string timelineName, float timeScale)
    {
        Timeline timeline = GetTimeline(timelineName);
        if (timeline != null)
        {
            timeline.timeScale = timeScale;
        }
    }
    
    public void PauseTimeline(string timelineName)
    {
        Timeline timeline = GetTimeline(timelineName);
        if (timeline != null)
        {
            timeline.isPaused = true;
        }
    }
    
    public void ResumeTimeline(string timelineName)
    {
        Timeline timeline = GetTimeline(timelineName);
        if (timeline != null)
        {
            timeline.isPaused = false;
        }
    }
    
    // 示例:子弹时间效果
    public void ActivateBulletTime(float duration, float timeScale = 0.2f)
    {
        // 减慢除UI外的所有时间线
        foreach (var timeline in timelines.Values)
        {
            if (timeline.name != "UI")
            {
                timeline.timeScale = timeScale;
            }
        }
        
        // 计划恢复正常时间
        globalTimeline.ScheduleEvent(new RestoreTimeScaleEvent
        {
            triggerTime = globalTimeline.currentTime + duration,
            targetTimeScale = 1.0f
        });
    }
    
    // 时间线事件示例
    public class RestoreTimeScaleEvent : TimelineEvent
    {
        public float targetTimeScale;
        
        public override void Execute()
        {
            TimelineSystem system = FindObjectOfType<TimelineSystem>();
            foreach (var timeline in system.timelines.Values)
            {
                if (timeline.name != "UI")
                {
                    timeline.timeScale = targetTimeScale;
                }
            }
        }
    }
}

// 使用时间线的组件示例
public class TimelineAnimator : MonoBehaviour, TimelineSystem.ITimelineUpdateable
{
    public string timelineName = "Global";
    private Animator animator;
    private TimelineSystem.Timeline timeline;
    
    void Start()
    {
        animator = GetComponent<Animator>();
        TimelineSystem timelineSystem = FindObjectOfType<TimelineSystem>();
        timeline = timelineSystem.GetTimeline(timelineName);
        timeline?.RegisterUpdateable(this);
    }
    
    public void UpdateTimeline(float deltaTime)
    {
        // 使用时间线的时间更新动画
        animator.speed = timeline.timeScale;
    }
    
    void OnDestroy()
    {
        timeline?.UnregisterUpdateable(this);
    }
}

高级时间控制

csharp

public class AdvancedTimeControl : MonoBehaviour
{
    // 时间曲线
    [System.Serializable]
    public class TimeCurve
    {
        public AnimationCurve curve;
        public float duration;
        public bool loop;
        
        private float currentTime = 0;
        
        public float Evaluate(float deltaTime)
        {
            currentTime += deltaTime;
            
            if (loop)
            {
                currentTime = currentTime % duration;
            }
            else
            {
                currentTime = Mathf.Clamp(currentTime, 0, duration);
            }
            
            return curve.Evaluate(currentTime / duration);
        }
        
        public void Reset()
        {
            currentTime = 0;
        }
    }
    
    // 时间层
    public class TimeLayer
    {
        public string name;
        public float baseTimeScale = 1.0f;
        public TimeCurve timeCurve;
        public List<GameObject> affectedObjects = new List<GameObject>();
        
        private float effectiveTimeScale;
        
        public float GetEffectiveTimeScale(float deltaTime)
        {
            if (timeCurve != null && timeCurve.curve != null)
            {
                effectiveTimeScale = baseTimeScale * timeCurve.Evaluate(deltaTime);
            }
            else
            {
                effectiveTimeScale = baseTimeScale;
            }
            
            return effectiveTimeScale;
        }
    }
    
    private List<TimeLayer> timeLayers = new List<TimeLayer>();
    
    // 时间效果
    public abstract class TimeEffect
    {
        public float duration;
        public float elapsedTime;
        public bool isActive = true;
        
        public abstract void Apply(TimeLayer layer, float deltaTime);
        
        public virtual void Update(float deltaTime)
        {
            elapsedTime += deltaTime;
            if (duration > 0 && elapsedTime >= duration)
            {
                isActive = false;
            }
        }
    }
    
    // 渐变时间效果
    public class TimeScaleTransition : TimeEffect
    {
        public float startScale;
        public float endScale;
        public AnimationCurve transitionCurve;
        
        public override void Apply(TimeLayer layer, float deltaTime)
        {
            float t = elapsedTime / duration;
            float curveValue = transitionCurve?.Evaluate(t) ?? t;
            layer.baseTimeScale = Mathf.Lerp(startScale, endScale, curveValue);
        }
    }
    
    // 脉冲时间效果
    public class TimePulseEffect : TimeEffect
    {
        public float pulseFrequency = 1.0f;
        public float pulseAmplitude = 0.5f;
        public float baseScale = 1.0f;
        
        public override void Apply(TimeLayer layer, float deltaTime)
        {
            float pulse = Mathf.Sin(elapsedTime * pulseFrequency * 2 * Mathf.PI) * 
                pulseAmplitude;
            layer.baseTimeScale = baseScale + pulse;
        }
    }
    
    private Dictionary<TimeLayer, List<TimeEffect>> activeEffects = 
        new Dictionary<TimeLayer, List<TimeEffect>>();
    
    void Start()
    {
        // 创建默认时间层
        CreateTimeLayer("Player");
        CreateTimeLayer("Enemies");
        CreateTimeLayer("Projectiles");
        CreateTimeLayer("Environment");
    }
    
    public TimeLayer CreateTimeLayer(string name)
    {
        TimeLayer layer = new TimeLayer { name = name };
        timeLayers.Add(layer);
        activeEffects[layer] = new List<TimeEffect>();
        return layer;
    }
    
    public void ApplyTimeEffect(string layerName, TimeEffect effect)
    {
        TimeLayer layer = timeLayers.Find(l => l.name == layerName);
        if (layer != null)
        {
            activeEffects[layer].Add(effect);
        }
    }
    
    void Update()
    {
        float deltaTime = Time.deltaTime;
        
        foreach (var layer in timeLayers)
        {
            // 应用所有活跃效果
            List<TimeEffect> effects = activeEffects[layer];
            for (int i = effects.Count - 1; i >= 0; i--)
            {
                TimeEffect effect = effects[i];
                effect.Update(deltaTime);
                
                if (effect.isActive)
                {
                    effect.Apply(layer, deltaTime);
                }
                else
                {
                    effects.RemoveAt(i);
                }
            }
            
            // 获取最终时间缩放
            float finalTimeScale = layer.GetEffectiveTimeScale(deltaTime);
            
            // 应用到受影响的对象
            foreach (var obj in layer.affectedObjects)
            {
                ApplyTimeScaleToObject(obj, finalTimeScale);
            }
        }
    }
    
    private void ApplyTimeScaleToObject(GameObject obj, float timeScale)
    {
        // 应用到动画
        Animator animator = obj.GetComponent<Animator>();
        if (animator != null)
        {
            animator.speed = timeScale;
        }
        
        // 应用到粒子系统
        ParticleSystem particles = obj.GetComponent<ParticleSystem>();
        if (particles != null)
        {
            var main = particles.main;
            main.simulationSpeed = timeScale;
        }
        
        // 应用到刚体
        Rigidbody rb = obj.GetComponent<Rigidbody>();
        if (rb != null)
        {
            // 这里需要自定义物理时间缩放逻辑
            // Unity的物理引擎不直接支持个体时间缩放
        }
    }
    
    // 便捷方法
    public void SlowMotion(string layerName, float timeScale, float duration)
    {
        ApplyTimeEffect(layerName, new TimeScaleTransition
        {
            startScale = 1.0f,
            endScale = timeScale,
            duration = duration * 0.2f, // 过渡时间
            transitionCurve = AnimationCurve.EaseInOut(0, 0, 1, 1)
        });
        
        // 自动恢复
        StartCoroutine(RestoreTimeScale(layerName, duration));
    }
    
    private IEnumerator RestoreTimeScale(string layerName, float delay)
    {
        yield return new WaitForSeconds(delay);
        
        ApplyTimeEffect(layerName, new TimeScaleTransition
        {
            startScale = GetTimeLayer(layerName).baseTimeScale,
            endScale = 1.0f,
            duration = 0.5f,
            transitionCurve = AnimationCurve.EaseInOut(0, 0, 1, 1)
        });
    }
    
    private TimeLayer GetTimeLayer(string name)
    {
        return timeLayers.Find(l => l.name == name);
    }
}

7.5 测量及处理时间

准确的时间测量和处理对于游戏的流畅运行至关重要。

高精度时间测量

csharp

public class HighPrecisionTimer : MonoBehaviour
{
    // 高精度计时器
    public class PrecisionTimer
    {
        private System.Diagnostics.Stopwatch stopwatch;
        private double frequency;
        
        public PrecisionTimer()
        {
            stopwatch = new System.Diagnostics.Stopwatch();
            frequency = System.Diagnostics.Stopwatch.Frequency;
        }
        
        public void Start()
        {
            stopwatch.Start();
        }
        
        public void Stop()
        {
            stopwatch.Stop();
        }
        
        public void Reset()
        {
            stopwatch.Reset();
        }
        
        public double ElapsedSeconds
        {
            get { return stopwatch.ElapsedTicks / frequency; }
        }
        
        public double ElapsedMilliseconds
        {
            get { return ElapsedSeconds * 1000.0; }
        }
        
        public double ElapsedMicroseconds
        {
            get { return ElapsedSeconds * 1000000.0; }
        }
    }
    
    // 性能分析器
    public class PerformanceProfiler
    {
        private Dictionary<string, ProfileData> profiles = 
            new Dictionary<string, ProfileData>();
        
        private class ProfileData
        {
            public PrecisionTimer timer = new PrecisionTimer();
            public double totalTime = 0;
            public int sampleCount = 0;
            public double minTime = double.MaxValue;
            public double maxTime = double.MinValue;
            public Queue<double> recentSamples = new Queue<double>();
            private const int MaxSamples = 100;
            
            public void AddSample(double time)
            {
                totalTime += time;
                sampleCount++;
                minTime = Math.Min(minTime, time);
                maxTime = Math.Max(maxTime, time);
                
                recentSamples.Enqueue(time);
                if (recentSamples.Count > MaxSamples)
                {
                    recentSamples.Dequeue();
                }
            }
            
            public double AverageTime
            {
                get { return sampleCount > 0 ? totalTime / sampleCount : 0; }
            }
            
            public double RecentAverage
            {
                get
                {
                    if (recentSamples.Count == 0) return 0;
                    return recentSamples.Average();
                }
            }
        }
        
        public void BeginProfile(string name)
        {
            if (!profiles.ContainsKey(name))
            {
                profiles[name] = new ProfileData();
            }
            
            profiles[name].timer.Reset();
            profiles[name].timer.Start();
        }
        
        public void EndProfile(string name)
        {
            if (profiles.ContainsKey(name))
            {
                profiles[name].timer.Stop();
                double elapsed = profiles[name].timer.ElapsedMilliseconds;
                profiles[name].AddSample(elapsed);
            }
        }
        
        public string GetReport()
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.AppendLine("Performance Report:");
            sb.AppendLine("==================");
            
            foreach (var kvp in profiles.OrderByDescending(x => x.Value.totalTime))
            {
                var data = kvp.Value;
                sb.AppendLine($"{kvp.Key}:");
                sb.AppendLine($"  Average: {data.AverageTime:F3}ms");
                sb.AppendLine($"  Recent Avg: {data.RecentAverage:F3}ms");
                sb.AppendLine($"  Min: {data.minTime:F3}ms");
                sb.AppendLine($"  Max: {data.maxTime:F3}ms");
                sb.AppendLine($"  Total: {data.totalTime:F3}ms");
                sb.AppendLine($"  Samples: {data.sampleCount}");
                sb.AppendLine();
            }
            
            return sb.ToString();
        }
    }
    
    private static PerformanceProfiler profiler = new PerformanceProfiler();
    
    // 自动性能分析作用域
    public struct ProfileScope : IDisposable
    {
        private string name;
        
        public ProfileScope(string name)
        {
            this.name = name;
            profiler.BeginProfile(name);
        }
        
        public void Dispose()
        {
            profiler.EndProfile(name);
        }
    }
    
    // 使用示例
    void Update()
    {
        using (new ProfileScope("Update"))
        {
            using (new ProfileScope("Physics"))
            {
                UpdatePhysics();
            }
            
            using (new ProfileScope("AI"))
            {
                UpdateAI();
            }
            
            using (new ProfileScope("Rendering"))
            {
                UpdateRendering();
            }
        }
        
        // 每秒输出一次报告
        if (Time.frameCount % 60 == 0)
        {
            Debug.Log(profiler.GetReport());
        }
    }
    
    private void UpdatePhysics()
    {
        // 物理更新逻辑
        System.Threading.Thread.Sleep(1); // 模拟耗时
    }
    
    private void UpdateAI()
    {
        // AI更新逻辑
        System.Threading.Thread.Sleep(2); // 模拟耗时
    }
    
    private void UpdateRendering()
    {
        // 渲染更新逻辑
        System.Threading.Thread.Sleep(3); // 模拟耗时
    }
}

时间平滑和预测

csharp

public class TimeSmoothing : MonoBehaviour
{
    // 时间平滑器
    public class TimeSmoother
    {
        private Queue<float> samples = new Queue<float>();
        private int maxSamples;
        private float smoothingFactor;
        
        public TimeSmoother(int maxSamples = 10, float smoothingFactor = 0.9f)
        {
            this.maxSamples = maxSamples;
            this.smoothingFactor = smoothingFactor;
        }
        
        public float AddSample(float sample)
        {
            samples.Enqueue(sample);
            
            if (samples.Count > maxSamples)
            {
                samples.Dequeue();
            }
            
            return GetSmoothedValue();
        }
        
        public float GetSmoothedValue()
        {
            if (samples.Count == 0) return 0;
            
            // 加权移动平均
            float weight = 1.0f;
            float totalWeight = 0;
            float weightedSum = 0;
            
            foreach (float sample in samples.Reverse())
            {
                weightedSum += sample * weight;
                totalWeight += weight;
                weight *= smoothingFactor;
            }
            
            return weightedSum / totalWeight;
        }
    }
    
    // 时间预测器
    public class TimePredictor
    {
        private List<float> timeHistory = new List<float>();
        private int historySize;
        
        public TimePredictor(int historySize = 30)
        {
            this.historySize = historySize;
        }
        
        public void RecordTime(float time)
        {
            timeHistory.Add(time);
            
            if (timeHistory.Count > historySize)
            {
                timeHistory.RemoveAt(0);
            }
        }
        
        public float PredictNextFrameTime()
        {
            if (timeHistory.Count < 2) return 0.016f; // 默认60fps
            
            // 简单线性预测
            float sum = 0;
            for (int i = 1; i < timeHistory.Count; i++)
            {
                sum += timeHistory[i] - timeHistory[i - 1];
            }
            
            return sum / (timeHistory.Count - 1);
        }
        
        public float PredictTimeAtFrame(int framesAhead)
        {
            float predictedFrameTime = PredictNextFrameTime();
            return Time.time + (predictedFrameTime * framesAhead);
        }
    }
    
    // 自适应时间步长
    public class AdaptiveTimeStep
    {
        private float targetFrameTime;
        private float minTimeStep;
        private float maxTimeStep;
        private TimeSmoother smoother;
        
        public AdaptiveTimeStep(float targetFPS = 60f)
        {
            targetFrameTime = 1.0f / targetFPS;
            minTimeStep = targetFrameTime * 0.5f;
            maxTimeStep = targetFrameTime * 2.0f;
            smoother = new TimeSmoother(5, 0.8f);
        }
        
        public float GetAdaptiveTimeStep(float actualFrameTime)
        {
            // 平滑实际帧时间
            float smoothedTime = smoother.AddSample(actualFrameTime);
            
            // 计算自适应时间步长
            float adaptiveStep = smoothedTime;
            
            // 限制在合理范围内
            adaptiveStep = Mathf.Clamp(adaptiveStep, minTimeStep, maxTimeStep);
            
            // 如果性能很差,使用固定步长避免螺旋死亡
            if (smoothedTime > maxTimeStep * 1.5f)
            {
                return targetFrameTime;
            }
            
            return adaptiveStep;
        }
    }
    
    private TimeSmoother deltaSmoother = new TimeSmoother(10);
    private TimePredictor timePredictor = new TimePredictor(30);
    private AdaptiveTimeStep adaptiveTimeStep = new AdaptiveTimeStep(60);
    
    void Update()
    {
        // 记录和平滑时间
        float rawDeltaTime = Time.deltaTime;
        float smoothedDeltaTime = deltaSmoother.AddSample(rawDeltaTime);
        
        // 预测下一帧时间
        timePredictor.RecordTime(Time.time);
        float predictedNextFrameTime = timePredictor.PredictNextFrameTime();
        
        // 获取自适应时间步长
        float adaptiveStep = adaptiveTimeStep.GetAdaptiveTimeStep(rawDeltaTime);
        
        // 使用处理后的时间值
        UpdateGameLogic(smoothedDeltaTime);
        
        // 调试信息
        if (Time.frameCount % 60 == 0)
        {
            Debug.Log($"Raw Delta: {rawDeltaTime:F4}, " +
                     $"Smoothed: {smoothedDeltaTime:F4}, " +
                     $"Predicted: {predictedNextFrameTime:F4}, " +
                     $"Adaptive: {adaptiveStep:F4}");
        }
    }
    
    private void UpdateGameLogic(float deltaTime)
    {
        // 使用平滑后的时间更新游戏逻辑
    }
}

时间同步系统

csharp

public class TimeSynchronization : MonoBehaviour
{
    // 网络时间同步
    public class NetworkTimeSync
    {
        private double serverTime;
        private double clientTime;
        private double offset;
        private double rtt; // Round Trip Time
        private Queue<double> offsetSamples = new Queue<double>();
        private const int MaxSamples = 10;
        
        public void SendTimeRequest()
        {
            double requestTime = GetHighPrecisionTime();
            // 发送时间请求到服务器
            SendToServer(new TimeRequest { clientTime = requestTime });
        }
        
        public void ReceiveTimeResponse(TimeResponse response)
        {
            double receiveTime = GetHighPrecisionTime();
            double sendTime = response.clientTime;
            
            // 计算往返时间
            rtt = receiveTime - sendTime;
            
            // 估算当前服务器时间
            double estimatedServerTime = response.serverTime + (rtt / 2);
            
            // 计算时间偏移
            double newOffset = estimatedServerTime - receiveTime;
            
            // 保存偏移样本
            offsetSamples.Enqueue(newOffset);
            if (offsetSamples.Count > MaxSamples)
            {
                offsetSamples.Dequeue();
            }
            
            // 使用中位数作为最终偏移(抗干扰)
            offset = GetMedian(offsetSamples.ToArray());
        }
        
        public double GetSynchronizedTime()
        {
            return GetHighPrecisionTime() + offset;
        }
        
        private double GetHighPrecisionTime()
        {
            return System.Diagnostics.Stopwatch.GetTimestamp() / 
                   (double)System.Diagnostics.Stopwatch.Frequency;
        }
        
        private double GetMedian(double[] values)
        {
            Array.Sort(values);
            int n = values.Length;
            if (n % 2 == 0)
            {
                return (values[n / 2 - 1] + values[n / 2]) / 2;
            }
            return values[n / 2];
        }
        
        private void SendToServer(TimeRequest request)
        {
            // 实际网络发送逻辑
        }
    }
    
    // 时间请求和响应结构
    [System.Serializable]
    public struct TimeRequest
    {
        public double clientTime;
    }
    
    [System.Serializable]
    public struct TimeResponse
    {
        public double clientTime;
        public double serverTime;
    }
    
    // 本地时间校准
    public class LocalTimeCalibration
    {
        private double calibrationOffset = 0;
        private double driftRate = 0;
        private double lastCalibrationTime;
        
        public void Calibrate(double referenceTime, double localTime)
        {
            double newOffset = referenceTime - localTime;
            
            if (lastCalibrationTime > 0)
            {
                double timeSinceLastCalibration = localTime - lastCalibrationTime;
                double offsetChange = newOffset - calibrationOffset;
                
                // 计算漂移率
                driftRate = offsetChange / timeSinceLastCalibration;
            }
            
            calibrationOffset = newOffset;
            lastCalibrationTime = localTime;
        }
        
        public double GetCalibratedTime(double localTime)
        {
            double timeSinceCalibration = localTime - lastCalibrationTime;
            double estimatedDrift = driftRate * timeSinceCalibration;
            
            return localTime + calibrationOffset + estimatedDrift;
        }
    }
    
    private NetworkTimeSync networkSync = new NetworkTimeSync();
    private LocalTimeCalibration localCalibration = new LocalTimeCalibration();
    private float syncInterval = 30f; // 30秒同步一次
    private float nextSyncTime = 0;
    
    void Start()
    {
        // 初始时间同步
        StartCoroutine(InitialTimeSync());
    }
    
    IEnumerator InitialTimeSync()
    {
        // 发送多次请求以获得准确的时间
        for (int i = 0; i < 5; i++)
        {
            networkSync.SendTimeRequest();
            yield return new WaitForSeconds(0.5f);
        }
    }
    
    void Update()
    {
        // 定期同步
        if (Time.time >= nextSyncTime)
        {
            networkSync.SendTimeRequest();
            nextSyncTime = Time.time + syncInterval;
        }
        
        // 使用同步的时间
        double synchronizedTime = networkSync.GetSynchronizedTime();
        
        // 本地校准
        if (Time.frameCount % 300 == 0) // 每5秒校准一次
        {
            localCalibration.Calibrate(synchronizedTime, Time.time);
        }
    }
    
    public double GetGameTime()
    {
        return localCalibration.GetCalibratedTime(Time.time);
    }
}

7.6 多处理器的游戏循环

现代游戏需要充分利用多核处理器的性能优势。

并行游戏循环架构

csharp

public class ParallelGameLoop : MonoBehaviour
{
    // 任务调度器
    public class TaskScheduler
    {
        private class ScheduledTask
        {
            public System.Action<float> action;
            public float priority;
            public bool canRunInParallel;
            public List<string> dependencies = new List<string>();
            public string name;
        }
        
        private List<ScheduledTask> tasks = new List<ScheduledTask>();
        private Dictionary<string, ScheduledTask> taskMap = 
            new Dictionary<string, ScheduledTask>();
        
        public void RegisterTask(string name, System.Action<float> action, 
            float priority = 0, bool canRunInParallel = true)
        {
            var task = new ScheduledTask
            {
                name = name,
                action = action,
                priority = priority,
                canRunInParallel = canRunInParallel
            };
            
            tasks.Add(task);
            taskMap[name] = task;
        }
        
        public void AddDependency(string taskName, string dependsOn)
        {
            if (taskMap.ContainsKey(taskName))
            {
                taskMap[taskName].dependencies.Add(dependsOn);
            }
        }
        
        public void ExecuteTasks(float deltaTime)
        {
            // 按优先级排序
            tasks.Sort((a, b) => b.priority.CompareTo(a.priority));
            
            // 构建执行计划
            List<List<ScheduledTask>> executionPlan = BuildExecutionPlan();
            
            // 执行任务
            foreach (var batch in executionPlan)
            {
                if (batch.Count == 1 || !batch[0].canRunInParallel)
                {
                    // 串行执行
                    foreach (var task in batch)
                    {
                        task.action(deltaTime);
                    }
                }
                else
                {
                    // 并行执行
                    Parallel.ForEach(batch, task =>
                    {
                        task.action(deltaTime);
                    });
                }
            }
        }
        
        private List<List<ScheduledTask>> BuildExecutionPlan()
        {
            List<List<ScheduledTask>> plan = new List<List<ScheduledTask>>();
            HashSet<string> completed = new HashSet<string>();
            List<ScheduledTask> remaining = new List<ScheduledTask>(tasks);
            
            while (remaining.Count > 0)
            {
                List<ScheduledTask> batch = new List<ScheduledTask>();
                
                for (int i = remaining.Count - 1; i >= 0; i--)
                {
                    var task = remaining[i];
                    
                    // 检查依赖是否满足
                    bool dependenciesMet = true;
                    foreach (var dep in task.dependencies)
                    {
                        if (!completed.Contains(dep))
                        {
                            dependenciesMet = false;
                            break;
                        }
                    }
                    
                    if (dependenciesMet)
                    {
                        batch.Add(task);
                        remaining.RemoveAt(i);
                    }
                }
                
                if (batch.Count > 0)
                {
                    plan.Add(batch);
                    foreach (var task in batch)
                    {
                        completed.Add(task.name);
                    }
                }
                else
                {
                    Debug.LogError("Circular dependency detected!");
                    break;
                }
            }
            
            return plan;
        }
    }
    
    // 并行物理系统
    public class ParallelPhysicsSystem
    {
        private struct PhysicsJob
        {
            public Rigidbody rigidbody;
            public Vector3 force;
            public Vector3 torque;
        }
        
        private List<PhysicsJob> physicsJobs = new List<PhysicsJob>();
        private object jobLock = new object();
        
        public void AddForce(Rigidbody rb, Vector3 force, Vector3 torque)
        {
            lock (jobLock)
            {
                physicsJobs.Add(new PhysicsJob
                {
                    rigidbody = rb,
                    force = force,
                    torque = torque
                });
            }
        }
        
        public void ProcessPhysicsJobs()
        {
            List<PhysicsJob> jobsToProcess;
            
            lock (jobLock)
            {
                jobsToProcess = new List<PhysicsJob>(physicsJobs);
                physicsJobs.Clear();
            }
            
            // 并行处理物理作业
            Parallel.ForEach(jobsToProcess, job =>
            {
                // 注意:Unity的物理API不是线程安全的
                // 这里仅作示例,实际应用需要其他方案
                lock (job.rigidbody)
                {
                    // 计算物理更新
                    Vector3 newVelocity = job.rigidbody.velocity + job.force;
                    Vector3 newAngularVelocity = job.rigidbody.angularVelocity + job.torque;
                    
                    // 存储结果,稍后在主线程应用
                    StorePhysicsResult(job.rigidbody, newVelocity, newAngularVelocity);
                }
            });
        }
        
        private Dictionary<Rigidbody, (Vector3 velocity, Vector3 angularVelocity)> 
            physicsResults = new Dictionary<Rigidbody, (Vector3, Vector3)>();
        
        private void StorePhysicsResult(Rigidbody rb, Vector3 velocity, 
            Vector3 angularVelocity)
        {
            lock (physicsResults)
            {
                physicsResults[rb] = (velocity, angularVelocity);
            }
        }
        
        public void ApplyPhysicsResults()
        {
            lock (physicsResults)
            {
                foreach (var kvp in physicsResults)
                {
                    kvp.Key.velocity = kvp.Value.velocity;
                    kvp.Key.angularVelocity = kvp.Value.angularVelocity;
                }
                physicsResults.Clear();
            }
        }
    }
    
    // 并行AI系统
    public class ParallelAISystem
    {
        public interface IAIAgent
        {
            void Think(float deltaTime);
            void Act();
        }
        
        private List<IAIAgent> agents = new List<IAIAgent>();
        private ConcurrentBag<System.Action> aiActions = new ConcurrentBag<System.Action>();
        
        public void RegisterAgent(IAIAgent agent)
        {
            agents.Add(agent);
        }
        
        public void UpdateAI(float deltaTime)
        {
            // 并行思考阶段
            Parallel.ForEach(agents, agent =>
            {
                agent.Think(deltaTime);
            });
            
            // 串行执行阶段(如果需要修改Unity对象)
            foreach (var agent in agents)
            {
                agent.Act();
            }
        }
    }
    
    private TaskScheduler taskScheduler = new TaskScheduler();
    private ParallelPhysicsSystem physicsSystem = new ParallelPhysicsSystem();
    private ParallelAISystem aiSystem = new ParallelAISystem();
    
    void Start()
    {
        // 注册游戏系统任务
        taskScheduler.RegisterTask("Input", UpdateInput, 100, false);
        taskScheduler.RegisterTask("Physics", UpdatePhysics, 90, true);
        taskScheduler.RegisterTask("AI", UpdateAI, 80, true);
        taskScheduler.RegisterTask("Animation", UpdateAnimation, 70, true);
        taskScheduler.RegisterTask("Rendering", PrepareRendering, 60, false);
        
        // 设置依赖关系
        taskScheduler.AddDependency("Physics", "Input");
        taskScheduler.AddDependency("AI", "Input");
        taskScheduler.AddDependency("Animation", "Physics");
        taskScheduler.AddDependency("Animation", "AI");
        taskScheduler.AddDependency("Rendering", "Animation");
    }
    
    void Update()
    {
        float deltaTime = Time.deltaTime;
        
        // 执行所有任务
        taskScheduler.ExecuteTasks(deltaTime);
    }
    
    private void UpdateInput(float deltaTime)
    {
        // 输入处理(必须在主线程)
    }
    
    private void UpdatePhysics(float deltaTime)
    {
        // 处理物理作业
        physicsSystem.ProcessPhysicsJobs();
        
        // 在主线程应用结果
        UnityMainThreadDispatcher.Instance.Enqueue(() =>
        {
            physicsSystem.ApplyPhysicsResults();
        });
    }
    
    private void UpdateAI(float deltaTime)
    {
        aiSystem.UpdateAI(deltaTime);
    }
    
    private void UpdateAnimation(float deltaTime)
    {
        // 动画更新
    }
    
    private void PrepareRendering(float deltaTime)
    {
        // 准备渲染数据
    }
}

// Unity主线程分发器
public class UnityMainThreadDispatcher : MonoBehaviour
{
    private static UnityMainThreadDispatcher instance;
    private Queue<System.Action> actionQueue = new Queue<System.Action>();
    
    public static UnityMainThreadDispatcher Instance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType<UnityMainThreadDispatcher>();
                if (instance == null)
                {
                    GameObject go = new GameObject("MainThreadDispatcher");
                    instance = go.AddComponent<UnityMainThreadDispatcher>();
                    DontDestroyOnLoad(go);
                }
            }
            return instance;
        }
    }
    
    public void Enqueue(System.Action action)
    {
        lock (actionQueue)
        {
            actionQueue.Enqueue(action);
        }
    }
    
    void Update()
    {
        lock (actionQueue)
        {
            while (actionQueue.Count > 0)
            {
                actionQueue.Dequeue()?.Invoke();
            }
        }
    }
}

Job System集成

csharp

using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;

public class JobSystemGameLoop : MonoBehaviour
{
    // 物理模拟Job
    [BurstCompile]
    struct PhysicsSimulationJob : IJobParallelFor
    {
        [ReadOnly] public NativeArray<float3> positions;
        [ReadOnly] public NativeArray<float3> velocities;
        [ReadOnly] public float deltaTime;
        
        [WriteOnly] public NativeArray<float3> newPositions;
        [WriteOnly] public NativeArray<float3> newVelocities;
        
        public void Execute(int index)
        {
            float3 pos = positions[index];
            float3 vel = velocities[index];
            
            // 简单的物理模拟
            vel.y -= 9.81f * deltaTime; // 重力
            pos += vel * deltaTime;
            
            // 地面碰撞
            if (pos.y < 0)
            {
                pos.y = 0;
                vel.y = -vel.y * 0.8f; // 弹性碰撞
            }
            
            newPositions[index] = pos;
            newVelocities[index] = vel;
        }
    }
    
    // 路径寻找Job
    [BurstCompile]
    struct PathfindingJob : IJob
    {
        [ReadOnly] public float3 start;
        [ReadOnly] public float3 goal;
        [ReadOnly] public NativeArray<int> gridData;
        public int gridWidth;
        public int gridHeight;
        
        [WriteOnly] public NativeList<float3> path;
        
        public void Execute()
        {
            // A*路径寻找算法的简化版本
            NativeList<int2> openList = new NativeList<int2>(Allocator.Temp);
            NativeHashMap<int2, float> gScore = new NativeHashMap<int2, float>(100, Allocator.Temp);
            NativeHashMap<int2, float> fScore = new NativeHashMap<int2, float>(100, Allocator.Temp);
            NativeHashMap<int2, int2> cameFrom = new NativeHashMap<int2, int2>(100, Allocator.Temp);
            
            int2 startNode = new int2((int)start.x, (int)start.z);
            int2 goalNode = new int2((int)goal.x, (int)goal.z);
            
            openList.Add(startNode);
            gScore[startNode] = 0;
            fScore[startNode] = Heuristic(startNode, goalNode);
            
            while (openList.Length > 0)
            {
                int2 current = GetLowestFScore(openList, fScore);
                
                if (current.Equals(goalNode))
                {
                    ReconstructPath(cameFrom, current, path);
                    break;
                }
                
                openList.RemoveAtSwapBack(GetIndex(openList, current));
                
                // 检查邻居
                for (int dx = -1; dx <= 1; dx++)
                {
                    for (int dy = -1; dy <= 1; dy++)
                    {
                        if (dx == 0 && dy == 0) continue;
                        
                        int2 neighbor = current + new int2(dx, dy);
                        
                        if (!IsWalkable(neighbor)) continue;
                        
                        float tentativeGScore = gScore[current] + Distance(current, neighbor);
                        
                        if (!gScore.ContainsKey(neighbor) || tentativeGScore < gScore[neighbor])
                        {
                            cameFrom[neighbor] = current;
                            gScore[neighbor] = tentativeGScore;
                            fScore[neighbor] = tentativeGScore + Heuristic(neighbor, goalNode);
                            
                            if (!Contains(openList, neighbor))
                            {
                                openList.Add(neighbor);
                            }
                        }
                    }
                }
            }
            
            openList.Dispose();
            gScore.Dispose();
            fScore.Dispose();
            cameFrom.Dispose();
        }
        
        float Heuristic(int2 a, int2 b)
        {
            return math.distance(new float2(a), new float2(b));
        }
        
        float Distance(int2 a, int2 b)
        {
            return math.distance(new float2(a), new float2(b));
        }
        
        bool IsWalkable(int2 pos)
        {
            if (pos.x < 0 || pos.x >= gridWidth || pos.y < 0 || pos.y >= gridHeight)
                return false;
            
            int index = pos.y * gridWidth + pos.x;
            return gridData[index] == 0; // 0表示可通行
        }
        
        int2 GetLowestFScore(NativeList<int2> list, NativeHashMap<int2, float> scores)
        {
            int2 lowest = list[0];
            float lowestScore = scores[lowest];
            
            for (int i = 1; i < list.Length; i++)
            {
                float score = scores[list[i]];
                if (score < lowestScore)
                {
                    lowest = list[i];
                    lowestScore = score;
                }
            }
            
            return lowest;
        }
        
        int GetIndex(NativeList<int2> list, int2 value)
        {
            for (int i = 0; i < list.Length; i++)
            {
                if (list[i].Equals(value))
                    return i;
            }
            return -1;
        }
        
        bool Contains(NativeList<int2> list, int2 value)
        {
            return GetIndex(list, value) >= 0;
        }
        
        void ReconstructPath(NativeHashMap<int2, int2> cameFrom, int2 current, NativeList<float3> path)
        {
            path.Add(new float3(current.x, 0, current.y));
            
            while (cameFrom.ContainsKey(current))
            {
                current = cameFrom[current];
                path.Add(new float3(current.x, 0, current.y));
            }
        }
    }
    
    // Job管理器
    public class JobManager
    {
        private NativeArray<float3> positions;
        private NativeArray<float3> velocities;
        private NativeArray<float3> newPositions;
        private NativeArray<float3> newVelocities;
        
        private JobHandle physicsJobHandle;
        private List<JobHandle> pathfindingHandles = new List<JobHandle>();
        
        public void Initialize(int entityCount)
        {
            positions = new NativeArray<float3>(entityCount, Allocator.Persistent);
            velocities = new NativeArray<float3>(entityCount, Allocator.Persistent);
            newPositions = new NativeArray<float3>(entityCount, Allocator.Persistent);
            newVelocities = new NativeArray<float3>(entityCount, Allocator.Persistent);
            
            // 初始化数据
            for (int i = 0; i < entityCount; i++)
            {
                positions[i] = new float3(
                    UnityEngine.Random.Range(-50f, 50f),
                    UnityEngine.Random.Range(10f, 50f),
                    UnityEngine.Random.Range(-50f, 50f)
                );
                velocities[i] = new float3(
                    UnityEngine.Random.Range(-5f, 5f),
                    0,
                    UnityEngine.Random.Range(-5f, 5f)
                );
            }
        }
        
        public void SchedulePhysicsJobs(float deltaTime)
        {
            var physicsJob = new PhysicsSimulationJob
            {
                positions = positions,
                velocities = velocities,
                deltaTime = deltaTime,
                newPositions = newPositions,
                newVelocities = newVelocities
            };
            
            physicsJobHandle = physicsJob.Schedule(positions.Length, 64);
        }
        
        public void CompletePhysicsJobs()
        {
            physicsJobHandle.Complete();
            
            // 交换缓冲区
            var temp = positions;
            positions = newPositions;
            newPositions = temp;
            
            temp = velocities;
            velocities = newVelocities;
            newVelocities = temp;
        }
        
        public void Dispose()
        {
            physicsJobHandle.Complete();
            
            positions.Dispose();
            velocities.Dispose();
            newPositions.Dispose();
            newVelocities.Dispose();
        }
    }
    
    private JobManager jobManager = new JobManager();
    
    void Start()
    {
        jobManager.Initialize(1000);
    }
    
    void Update()
    {
        // 调度Jobs
        jobManager.SchedulePhysicsJobs(Time.deltaTime);
        
        // 在等待Jobs完成时可以做其他工作
        UpdateUI();
        ProcessInput();
        
        // 完成Jobs
        jobManager.CompletePhysicsJobs();
        
        // 应用结果
        ApplyResults();
    }
    
    void OnDestroy()
    {
        jobManager.Dispose();
    }
    
    private void UpdateUI()
    {
        // UI更新逻辑
    }
    
    private void ProcessInput()
    {
        // 输入处理逻辑
    }
    
    private void ApplyResults()
    {
        // 应用Job计算结果
    }
}

7.7 网络多人游戏循环

网络游戏需要特殊的循环设计来处理延迟、同步和预测。

客户端预测和服务器协调

csharp

public class NetworkGameLoop : MonoBehaviour
{
    // 网络时间管理
    public class NetworkTime
    {
        private float serverTime;
        private float clientTime;
        private float latency;
        private float timeOffset;
        
        public void UpdateServerTime(float newServerTime, float roundTripTime)
        {
            latency = roundTripTime / 2f;
            float estimatedServerTime = newServerTime + latency;
            timeOffset = estimatedServerTime - Time.time;
            serverTime = estimatedServerTime;
        }
        
        public float GetServerTime()
        {
            return Time.time + timeOffset;
        }
        
        public float GetClientTime()
        {
            return Time.time;
        }
        
        public float GetLatency()
        {
            return latency;
        }
    }
    
    // 客户端预测系统
    public class ClientPrediction
    {
        private class PredictedState
        {
            public int inputSequence;
            public Vector3 position;
            public Quaternion rotation;
            public Vector3 velocity;
            public float timestamp;
        }
        
        private Queue<PredictedState> stateHistory = new Queue<PredictedState>();
        private int maxHistorySize = 60; // 1秒的历史(60fps)
        
        public void RecordState(int inputSequence, Vector3 position, 
            Quaternion rotation, Vector3 velocity)
        {
            var state = new PredictedState
            {
                inputSequence = inputSequence,
                position = position,
                rotation = rotation,
                velocity = velocity,
                timestamp = Time.time
            };
            
            stateHistory.Enqueue(state);
            
            // 限制历史大小
            while (stateHistory.Count > maxHistorySize)
            {
                stateHistory.Dequeue();
            }
        }
        
        public void ReconcileWithServer(int acknowledgedInput, Vector3 serverPosition, 
            Quaternion serverRotation, Vector3 serverVelocity)
        {
            // 找到对应的历史状态
            PredictedState[] history = stateHistory.ToArray();
            int reconcileIndex = -1;
            
            for (int i = 0; i < history.Length; i++)
            {
                if (history[i].inputSequence == acknowledgedInput)
                {
                    reconcileIndex = i;
                    break;
                }
            }
            
            if (reconcileIndex >= 0)
            {
                // 检查预测误差
                Vector3 positionError = serverPosition - history[reconcileIndex].position;
                float rotationError = Quaternion.Angle(serverRotation, 
                    history[reconcileIndex].rotation);
                
                // 如果误差太大,进行修正
                if (positionError.magnitude > 0.1f || rotationError > 5f)
                {
                    // 重新模拟从服务器状态开始的所有输入
                    ResimulateFromState(reconcileIndex, serverPosition, 
                        serverRotation, serverVelocity);
                }
            }
        }
        
        private void ResimulateFromState(int startIndex, Vector3 position, 
            Quaternion rotation, Vector3 velocity)
        {
            // 从服务器确认的状态开始重新模拟
            PredictedState[] history = stateHistory.ToArray();
            
            for (int i = startIndex + 1; i < history.Length; i++)
            {
                // 重新应用输入
                // 这里需要存储和重放输入
            }
        }
    }
    
    // 输入缓冲系统
    public class InputBuffer
    {
        public struct InputCommand
        {
            public int sequence;
            public float timestamp;
            public Vector2 movement;
            public bool jump;
            public bool fire;
            public Vector3 lookDirection;
        }
        
        private Queue<InputCommand> unacknowledgedInputs = new Queue<InputCommand>();
        private int currentSequence = 0;
        
        public InputCommand CreateInput(Vector2 movement, bool jump, bool fire, 
            Vector3 lookDirection)
        {
            var input = new InputCommand
            {
                sequence = currentSequence++,
                timestamp = Time.time,
                movement = movement,
                jump = jump,
                fire = fire,
                lookDirection = lookDirection
            };
            
            unacknowledgedInputs.Enqueue(input);
            
            return input;
        }
        
        public void AcknowledgeInput(int sequence)
        {
            // 移除已确认的输入
            while (unacknowledgedInputs.Count > 0 && 
                   unacknowledgedInputs.Peek().sequence <= sequence)
            {
                unacknowledgedInputs.Dequeue();
            }
        }
        
        public InputCommand[] GetUnacknowledgedInputs()
        {
            return unacknowledgedInputs.ToArray();
        }
    }
    
    // 延迟补偿系统
    public class LagCompensation
    {
        private class WorldSnapshot
        {
            public float timestamp;
            public Dictionary<int, EntityState> entities = new Dictionary<int, EntityState>();
        }
        
        private class EntityState
        {
            public Vector3 position;
            public Quaternion rotation;
            public Bounds bounds;
        }
        
        private Queue<WorldSnapshot> snapshotHistory = new Queue<WorldSnapshot>();
        private float historyDuration = 1.0f; // 保留1秒的历史
        
        public void RecordSnapshot()
        {
            var snapshot = new WorldSnapshot
            {
                timestamp = Time.time
            };
            
            // 记录所有实体状态
            GameObject[] entities = GameObject.FindGameObjectsWithTag("NetworkEntity");
            foreach (var entity in entities)
            {
                int entityId = entity.GetComponent<NetworkEntity>().entityId;
                
                snapshot.entities[entityId] = new EntityState
                {
                    position = entity.transform.position,
                    rotation = entity.transform.rotation,
                    bounds = entity.GetComponent<Collider>().bounds
                };
            }
            
            snapshotHistory.Enqueue(snapshot);
            
            // 清理旧快照
            float cutoffTime = Time.time - historyDuration;
            while (snapshotHistory.Count > 0 && 
                   snapshotHistory.Peek().timestamp < cutoffTime)
            {
                snapshotHistory.Dequeue();
            }
        }
        
        public bool RaycastAtTime(float timestamp, Vector3 origin, Vector3 direction, 
            out RaycastHit hit, float maxDistance, int layerMask)
        {
            // 找到最接近的历史快照
            WorldSnapshot snapshot = GetSnapshotAtTime(timestamp);
            
            if (snapshot != null)
            {
                // 临时移动所有实体到历史位置
                Dictionary<Transform, Vector3> originalPositions = 
                    new Dictionary<Transform, Vector3>();
                Dictionary<Transform, Quaternion> originalRotations = 
                    new Dictionary<Transform, Quaternion>();
                
                foreach (var kvp in snapshot.entities)
                {
                    GameObject entity = FindEntityById(kvp.Key);
                    if (entity != null)
                    {
                        Transform transform = entity.transform;
                        originalPositions[transform] = transform.position;
                        originalRotations[transform] = transform.rotation;
                        
                        transform.position = kvp.Value.position;
                        transform.rotation = kvp.Value.rotation;
                    }
                }
                
                // 执行射线检测
                bool result = Physics.Raycast(origin, direction, out hit, 
                    maxDistance, layerMask);
                
                // 恢复原始位置
                foreach (var kvp in originalPositions)
                {
                    kvp.Key.position = kvp.Value;
                }
                foreach (var kvp in originalRotations)
                {
                    kvp.Key.rotation = kvp.Value;
                }
                
                return result;
            }
            
            // 如果没有历史数据,使用当前状态
            return Physics.Raycast(origin, direction, out hit, maxDistance, layerMask);
        }
        
        private WorldSnapshot GetSnapshotAtTime(float timestamp)
        {
            WorldSnapshot closest = null;
            float minDelta = float.MaxValue;
            
            foreach (var snapshot in snapshotHistory)
            {
                float delta = Mathf.Abs(snapshot.timestamp - timestamp);
                if (delta < minDelta)
                {
                    minDelta = delta;
                    closest = snapshot;
                }
            }
            
            return closest;
        }
        
        private GameObject FindEntityById(int id)
        {
            GameObject[] entities = GameObject.FindGameObjectsWithTag("NetworkEntity");
            foreach (var entity in entities)
            {
                if (entity.GetComponent<NetworkEntity>().entityId == id)
                {
                    return entity;
                }
            }
            return null;
        }
    }
    
    // 网络实体组件
    [System.Serializable]
    public class NetworkEntity : MonoBehaviour
    {
        public int entityId;
        public bool isLocalPlayer;
        public bool isPredicted;
        
        private Vector3 networkPosition;
        private Quaternion networkRotation;
        private float lastUpdateTime;
        
        void Start()
        {
            if (isLocalPlayer)
            {
                // 本地玩家使用预测
                isPredicted = true;
            }
        }
        
        public void SetNetworkState(Vector3 position, Quaternion rotation)
        {
            networkPosition = position;
            networkRotation = rotation;
            lastUpdateTime = Time.time;
        }
        
        void Update()
        {
            if (!isLocalPlayer && !isPredicted)
            {
                // 插值到网络位置
                float timeSinceUpdate = Time.time - lastUpdateTime;
                float lerpFactor = Mathf.Clamp01(timeSinceUpdate / 0.1f); // 100ms插值
                
                transform.position = Vector3.Lerp(transform.position, 
                    networkPosition, lerpFactor);
                transform.rotation = Quaternion.Slerp(transform.rotation, 
                    networkRotation, lerpFactor);
            }
        }
    }
    
    private NetworkTime networkTime = new NetworkTime();
    private ClientPrediction clientPrediction = new ClientPrediction();
    private InputBuffer inputBuffer = new InputBuffer();
    private LagCompensation lagCompensation = new LagCompensation();
    
    void Start()
    {
        // 启动网络时间同步
        StartCoroutine(SyncNetworkTime());
    }
    
    void Update()
    {
        // 记录世界快照(用于延迟补偿)
        lagCompensation.RecordSnapshot();
        
        // 处理本地输入
        if (IsLocalPlayer())
        {
            ProcessLocalInput();
        }
        
        // 更新网络实体
        UpdateNetworkEntities();
    }
    
    void FixedUpdate()
    {
        // 固定时间步长的物理更新
        if (IsLocalPlayer())
        {
            // 客户端预测
            SimulateLocalPlayer();
        }
    }
    
    private void ProcessLocalInput()
    {
        Vector2 movement = new Vector2(Input.GetAxis("Horizontal"), 
            Input.GetAxis("Vertical"));
        bool jump = Input.GetButtonDown("Jump");
        bool fire = Input.GetButton("Fire1");
        Vector3 lookDirection = GetLookDirection();
        
        // 创建输入命令
        var inputCmd = inputBuffer.CreateInput(movement, jump, fire, lookDirection);
        
        // 发送到服务器
        SendInputToServer(inputCmd);
    }
    
    private void SimulateLocalPlayer()
    {
        // 应用客户端预测
        GameObject player = GetLocalPlayer();
        if (player != null)
        {
            // 这里实现具体的移动逻辑
            
            // 记录预测状态
            clientPrediction.RecordState(
                GetCurrentInputSequence(),
                player.transform.position,
                player.transform.rotation,
                player.GetComponent<Rigidbody>().velocity
            );
        }
    }
    
    private void UpdateNetworkEntities()
    {
        // 更新所有网络实体的状态
    }
    
    IEnumerator SyncNetworkTime()
    {
        while (true)
        {
            // 发送时间同步请求
            SendTimeSyncRequest();
            
            yield return new WaitForSeconds(5f); // 每5秒同步一次
        }
    }
    
    // 网络消息处理
    public void OnReceiveServerUpdate(ServerUpdateMessage message)
    {
        // 更新服务器时间
        networkTime.UpdateServerTime(message.serverTime, message.roundTripTime);
        
        // 处理实体更新
        foreach (var entityUpdate in message.entities)
        {
            GameObject entity = FindEntityById(entityUpdate.id);
            if (entity != null)
            {
                NetworkEntity netEntity = entity.GetComponent<NetworkEntity>();
                
                if (netEntity.isLocalPlayer)
                {
                    // 本地玩家:进行预测协调
                    clientPrediction.ReconcileWithServer(
                        message.acknowledgedInput,
                        entityUpdate.position,
                        entityUpdate.rotation,
                        entityUpdate.velocity
                    );
                }
                else
                {
                    // 其他玩家:设置网络状态
                    netEntity.SetNetworkState(entityUpdate.position, 
                        entityUpdate.rotation);
                }
            }
        }
        
        // 确认输入
        inputBuffer.AcknowledgeInput(message.acknowledgedInput);
    }
    
    // 辅助方法
    private bool IsLocalPlayer()
    {
        // 判断是否是本地玩家
        return true; // 示例实现
    }
    
    private GameObject GetLocalPlayer()
    {
        // 获取本地玩家对象
        return GameObject.FindWithTag("LocalPlayer");
    }
    
    private Vector3 GetLookDirection()
    {
        // 获取视线方向
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        return ray.direction;
    }
    
    private int GetCurrentInputSequence()
    {
        // 获取当前输入序列号
        return 0; // 示例实现
    }
    
    private GameObject FindEntityById(int id)
    {
        // 根据ID查找实体
        return null; // 示例实现
    }
    
    private void SendInputToServer(InputBuffer.InputCommand input)
    {
        // 发送输入到服务器
    }
    
    private void SendTimeSyncRequest()
    {
        // 发送时间同步请求
    }
}

// 服务器更新消息
[System.Serializable]
public class ServerUpdateMessage
{
    public float serverTime;
    public float roundTripTime;
    public int acknowledgedInput;
    public List<EntityUpdate> entities = new List<EntityUpdate>();
}

[System.Serializable]
public class EntityUpdate
{
    public int id;
    public Vector3 position;
    public Quaternion rotation;
    public Vector3 velocity;
}

确定性模拟

csharp

public class DeterministicGameLoop : MonoBehaviour
{
    // 定点数学库
    public struct FixedPoint
    {
        private long rawValue;
        private const int SHIFT_AMOUNT = 16; // 16位小数
        private const long ONE = 1L << SHIFT_AMOUNT;
        
        public static FixedPoint FromFloat(float value)
        {
            return new FixedPoint { rawValue = (long)(value * ONE) };
        }
        
        public static FixedPoint FromInt(int value)
        {
            return new FixedPoint { rawValue = value * ONE };
        }
        
        public float ToFloat()
        {
            return (float)rawValue / ONE;
        }
        
        // 运算符重载
        public static FixedPoint operator +(FixedPoint a, FixedPoint b)
        {
            return new FixedPoint { rawValue = a.rawValue + b.rawValue };
        }
        
        public static FixedPoint operator -(FixedPoint a, FixedPoint b)
        {
            return new FixedPoint { rawValue = a.rawValue - b.rawValue };
        }
        
        public static FixedPoint operator *(FixedPoint a, FixedPoint b)
        {
            return new FixedPoint { rawValue = (a.rawValue * b.rawValue) >> SHIFT_AMOUNT };
        }
        
        public static FixedPoint operator /(FixedPoint a, FixedPoint b)
        {
            return new FixedPoint { rawValue = (a.rawValue << SHIFT_AMOUNT) / b.rawValue };
        }
    }
    
    // 定点向量
    public struct FixedVector3
    {
        public FixedPoint x, y, z;
        
        public static FixedVector3 FromVector3(Vector3 v)
        {
            return new FixedVector3
            {
                x = FixedPoint.FromFloat(v.x),
                y = FixedPoint.FromFloat(v.y),
                z = FixedPoint.FromFloat(v.z)
            };
        }
        
        public Vector3 ToVector3()
        {
            return new Vector3(x.ToFloat(), y.ToFloat(), z.ToFloat());
        }
        
        public static FixedVector3 operator +(FixedVector3 a, FixedVector3 b)
        {
            return new FixedVector3
            {
                x = a.x + b.x,
                y = a.y + b.y,
                z = a.z + b.z
            };
        }
    }
    
    // 确定性随机数生成器
    public class DeterministicRandom
    {
        private uint seed;
        
        public DeterministicRandom(uint seed)
        {
            this.seed = seed;
        }
        
        public uint Next()
        {
            // Linear Congruential Generator
            seed = seed * 1664525u + 1013904223u;
            return seed;
        }
        
        public float NextFloat()
        {
            return (float)(Next() & 0xFFFFFF) / 16777216f;
        }
        
        public int NextInt(int min, int max)
        {
            return min + (int)(Next() % (uint)(max - min));
        }
    }
    
    // 游戏状态
    public class GameState
    {
        public int frame;
        public uint checksum;
        public Dictionary<int, EntityState> entities = new Dictionary<int, EntityState>();
        public DeterministicRandom random;
        
        public GameState Clone()
        {
            var clone = new GameState
            {
                frame = frame,
                checksum = checksum,
                random = new DeterministicRandom(random.Next())
            };
            
            foreach (var kvp in entities)
            {
                clone.entities[kvp.Key] = kvp.Value.Clone();
            }
            
            return clone;
        }
        
        public uint CalculateChecksum()
        {
            uint sum = 0;
            foreach (var entity in entities.Values)
            {
                sum ^= entity.GetChecksum();
            }
            return sum;
        }
    }
    
    // 实体状态
    public class EntityState
    {
        public int id;
        public FixedVector3 position;
        public FixedVector3 velocity;
        public FixedPoint health;
        
        public EntityState Clone()
        {
            return new EntityState
            {
                id = id,
                position = position,
                velocity = velocity,
                health = health
            };
        }
        
        public uint GetChecksum()
        {
            uint sum = (uint)id;
            sum ^= (uint)position.x.ToFloat() * 73856093u;
            sum ^= (uint)position.y.ToFloat() * 19349663u;
            sum ^= (uint)position.z.ToFloat() * 83492791u;
            return sum;
        }
    }
    
    // 输入帧
    public class InputFrame
    {
        public int frame;
        public Dictionary<int, PlayerInput> inputs = new Dictionary<int, PlayerInput>();
    }
    
    public struct PlayerInput
    {
        public byte movement; // 8方向移动
        public byte actions;  // 8个动作按钮
        public ushort angle;  // 360度角度(0-65535映射到0-360)
    }
    
    // 回滚系统
    public class RollbackSystem
    {
        private Dictionary<int, GameState> stateHistory = new Dictionary<int, GameState>();
        private int maxHistoryFrames = 120; // 2秒@60fps
        
        public void SaveState(int frame, GameState state)
        {
            stateHistory[frame] = state.Clone();
            
            // 清理旧状态
            List<int> framesToRemove = new List<int>();
            foreach (var kvp in stateHistory)
            {
                if (frame - kvp.Key > maxHistoryFrames)
                {
                    framesToRemove.Add(kvp.Key);
                }
            }
            
            foreach (int f in framesToRemove)
            {
                stateHistory.Remove(f);
            }
        }
        
        public GameState GetState(int frame)
        {
            if (stateHistory.ContainsKey(frame))
            {
                return stateHistory[frame].Clone();
            }
            
            // 找到最近的状态
            int closestFrame = -1;
            foreach (int f in stateHistory.Keys)
            {
                if (f < frame && f > closestFrame)
                {
                    closestFrame = f;
                }
            }
            
            return closestFrame >= 0 ? stateHistory[closestFrame].Clone() : null;
        }
    }
    
    private GameState currentState;
    private RollbackSystem rollbackSystem = new RollbackSystem();
    private Queue<InputFrame> inputQueue = new Queue<InputFrame>();
    private int currentFrame = 0;
    private int confirmedFrame = 0;
    
    void Start()
    {
        // 初始化游戏状态
        currentState = new GameState
        {
            frame = 0,
            random = new DeterministicRandom(12345)
        };
        
        // 创建初始实体
        CreateInitialEntities();
    }
    
    void FixedUpdate()
    {
        // 收集本地输入
        PlayerInput localInput = CollectLocalInput();
        
        // 创建输入帧
        InputFrame inputFrame = new InputFrame
        {
            frame = currentFrame,
            inputs = { [GetLocalPlayerId()] = localInput }
        };
        
        // 发送输入到其他客户端
        BroadcastInput(inputFrame);
        
        // 处理输入队列
        ProcessInputQueue();
        
        // 步进模拟
        StepSimulation();
        
        currentFrame++;
    }
    
    private void ProcessInputQueue()
    {
        // 处理接收到的输入
        while (inputQueue.Count > 0)
        {
            InputFrame frame = inputQueue.Peek();
            
            if (frame.frame <= confirmedFrame)
            {
                // 已确认的帧,跳过
                inputQueue.Dequeue();
                continue;
            }
            
            if (frame.frame > currentFrame)
            {
                // 未来的帧,等待
                break;
            }
            
            // 需要回滚
            if (frame.frame < currentFrame)
            {
                Rollback(frame.frame);
            }
            
            // 应用输入
            ApplyInputFrame(frame);
            
            inputQueue.Dequeue();
        }
    }
    
    private void Rollback(int targetFrame)
    {
        Debug.Log($"Rolling back from frame {currentFrame} to {targetFrame}");
        
        // 恢复到目标帧的状态
        GameState state = rollbackSystem.GetState(targetFrame);
        if (state != null)
        {
            currentState = state;
            currentFrame = targetFrame;
            
            // 重新模拟到当前帧
            while (currentFrame < Time.frameCount)
            {
                StepSimulation();
                currentFrame++;
            }
        }
    }
    
    private void StepSimulation()
    {
        // 保存当前状态
        rollbackSystem.SaveState(currentFrame, currentState);
        
        // 确定性物理模拟
        foreach (var entity in currentState.entities.Values)
        {
            // 应用重力
            entity.velocity.y = entity.velocity.y - FixedPoint.FromFloat(9.81f * 0.016f);
            
            // 更新位置
            entity.position = entity.position + entity.velocity;
            
            // 地面碰撞
            if (entity.position.y.ToFloat() < 0)
            {
                entity.position.y = FixedPoint.FromFloat(0);
                entity.velocity.y = FixedPoint.FromFloat(0);
            }
        }
        
        // 计算校验和
        currentState.checksum = currentState.CalculateChecksum();
        
        // 每隔一定帧数验证校验和
        if (currentFrame % 60 == 0)
        {
            VerifyChecksum();
        }
    }
    
    private void VerifyChecksum()
    {
        // 与其他客户端比较校验和
        // 如果不一致,需要从主机重新同步状态
    }
    
    private PlayerInput CollectLocalInput()
    {
        PlayerInput input = new PlayerInput();
        
        // 收集移动输入(8方向)
        Vector2 movement = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
        if (movement.magnitude > 0.1f)
        {
            float angle = Mathf.Atan2(movement.y, movement.x) * Mathf.Rad2Deg;
            int direction = Mathf.RoundToInt((angle + 180) / 45) % 8;
            input.movement = (byte)direction;
        }
        
        // 收集动作输入
        if (Input.GetButton("Fire1")) input.actions |= 1;
        if (Input.GetButton("Fire2")) input.actions |= 2;
        if (Input.GetButton("Jump")) input.actions |= 4;
        
        // 收集角度输入(鼠标方向)
        Vector3 mousePos = Input.mousePosition;
        Vector3 screenCenter = new Vector3(Screen.width / 2, Screen.height / 2, 0);
        Vector3 dir = mousePos - screenCenter;
        float mouseAngle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
        input.angle = (ushort)((mouseAngle + 180) / 360 * 65535);
        
        return input;
    }
    
    private void ApplyInputFrame(InputFrame frame)
    {
        foreach (var kvp in frame.inputs)
        {
            int playerId = kvp.Key;
            PlayerInput input = kvp.Value;
            
            if (currentState.entities.ContainsKey(playerId))
            {
                ApplyInputToEntity(currentState.entities[playerId], input);
            }
        }
    }
    
    private void ApplyInputToEntity(EntityState entity, PlayerInput input)
    {
        // 应用移动
        if (input.movement < 8)
        {
            float angle = input.movement * 45 * Mathf.Deg2Rad;
            FixedVector3 moveDir = new FixedVector3
            {
                x = FixedPoint.FromFloat(Mathf.Cos(angle) * 5),
                z = FixedPoint.FromFloat(Mathf.Sin(angle) * 5)
            };
            entity.velocity = moveDir;
        }
        
        // 应用动作
        if ((input.actions & 4) != 0) // Jump
        {
            if (entity.position.y.ToFloat() <= 0.1f)
            {
                entity.velocity.y = FixedPoint.FromFloat(10);
            }
        }
    }
    
    private void CreateInitialEntities()
    {
        // 创建玩家实体
        for (int i = 0; i < 4; i++)
        {
            currentState.entities[i] = new EntityState
            {
                id = i,
                position = FixedVector3.FromVector3(new Vector3(i * 5, 0, 0)),
                velocity = FixedVector3.FromVector3(Vector3.zero),
                health = FixedPoint.FromFloat(100)
            };
        }
    }
    
    private int GetLocalPlayerId()
    {
        return 0; // 示例实现
    }
    
    private void BroadcastInput(InputFrame frame)
    {
        // 发送输入到其他客户端
    }
    
    public void OnReceiveInput(InputFrame frame)
    {
        // 接收其他客户端的输入
        inputQueue.Enqueue(frame);
    }
}

总结

本章详细介绍了游戏循环及实时模拟的各个方面:

渲染循环 – 高效的渲染架构和优化技术
游戏循环 – 固定和可变时间步长的实现
架构风格 – 组件化、事件驱动和多线程架构
抽象时间线 – 灵活的时间控制系统
时间测量 – 高精度计时和时间同步
多处理器 – 并行计算和Job System
网络游戏 – 客户端预测、延迟补偿和确定性模拟

这些技术共同构成了现代游戏引擎的核心,通过合理的设计和实现,可以创建出流畅、响应迅速且可扩展的游戏系统。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容