You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity+Photon Fusion赛车游戏客户端Float变量同步问题求助

问题描述

我正在使用Photon Fusion开发Unity多人赛车游戏,需要同步一个随UI按钮输入变化的Float类型车速变量——车辆初始以固定速度前进,玩家输入会改变各自的车速。

最初尝试用[Networked]特性同步变量,但仅Host端变量能跨端同步,客户端修改的变量会瞬间跳回原值;之后改用RPC方法,虽能运行但偶尔会出现客户端车辆速度远超Host的情况,且官方文档不建议频繁使用RPC,希望找到完美的实现方案。

车辆GameObject包含EntityScript、ControllerScript等Fusion必备脚本:EntityScript负责UI及输入检测,ControllerScript控制物体位置,相关代码如下:

EntityScript.cs

public override void FixedUpdateNetwork()
{
    base.FixedUpdateNetwork();
    Debug.Log($"Applied Speed of {Car.name} : {AppliedSpeed}");
    transform.position += AppliedSpeed * transform.forward * Runner.DeltaTime;
}

ControllerScript.cs

private void SpeedApplied()
{
    if (Object.HasInputAuthority)
    {
        if (Hud.answer.text == answerValue.ToString())
        {
            Controller.AppliedSpeed += 10;
            Debug.Log($"CheckAnswer AppliedSpeed: {Controller.AppliedSpeed}");
        }
        else
        {
            Controller.AppliedSpeed = 15f;
        }
    }
}
解决方案

核心思路是利用Fusion的输入同步机制传递车速变更指令,这是Fusion针对玩家输入驱动状态变更设计的标准流程,既符合框架规范,又能避免RPC的频繁调用问题和[Networked]变量的权威覆盖问题。

具体实现步骤

  1. 定义输入结构体:在NetworkBehaviour脚本中定义包含车速变更指令的输入结构体,标记[NetworkInput]以启用Fusion的输入同步。
  2. 收集客户端输入:拥有输入权限的客户端(HasInputAuthority)在UI触发时,将车速变更指令填充到输入结构体,并通过SetInput提交。
  3. 权威端应用输入:Host端作为权威接收所有客户端的输入,校验后更新车速变量,再同步到所有客户端;所有端基于同步后的输入统一执行移动逻辑。

修改后的代码示例

1. 输入结构体定义(在EntityScript中添加)

// 定义用于同步车速变更的输入结构体
[NetworkInput]
public struct CarInput : INetworkInput
{
    // 标记是否触发了车速变更操作
    public bool IsSpeedChanged;
    // 目标车速(或操作类型,根据需求调整)
    public float TargetSpeed;
}

2. 修正EntityScript的FixedUpdateNetwork逻辑

public class EntityScript : NetworkBehaviour
{
    public float AppliedSpeed = 15f; // 初始固定车速
    private CarInput _currentInput;

    public override void FixedUpdateNetwork()
    {
        base.FixedUpdateNetwork();

        // 获取同步过来的输入指令
        if (GetInput(out _currentInput))
        {
            if (_currentInput.IsSpeedChanged)
            {
                // Host端可在此添加校验逻辑(如限制车速范围,防止作弊)
                AppliedSpeed = _currentInput.TargetSpeed;
            }
        }

        // 所有端统一执行移动逻辑
        transform.position += AppliedSpeed * transform.forward * Runner.DeltaTime;
        Debug.Log($"Applied Speed of {gameObject.name} : {AppliedSpeed}");
    }
}

3. 修正ControllerScript的SpeedApplied方法(提交输入而非直接改变量)

public class ControllerScript : NetworkBehaviour
{
    public EntityScript Controller;
    // 假设Hud和answerValue为已初始化的引用

    private void SpeedApplied()
    {
        if (Object.HasInputAuthority)
        {
            var input = new CarInput
            {
                IsSpeedChanged = true
            };

            if (Hud.answer.text == answerValue.ToString())
            {
                // 客户端仅提交加速请求的目标值,由Host统一处理
                input.TargetSpeed = Controller.AppliedSpeed + 10;
                Debug.Log($"Request speed up to {input.TargetSpeed}");
            }
            else
            {
                input.TargetSpeed = 15f;
                Debug.Log($"Request reset speed to 15");
            }

            // 将输入提交给Fusion,自动同步到Host
            SetInput(input);
        }
    }
}

额外优化建议

  • 防作弊处理:如果担心客户端篡改车速数值,不要直接传递目标车速,而是传递操作类型(如定义public enum CarAction { SpeedUp, Reset }),Host端收到操作后自行计算车速,彻底避免客户端作弊。
  • 输入重置:如果不需要每帧都传递输入,可在提交一次输入后重置IsSpeedChanged为false,减少不必要的网络同步开销。

内容的提问来源于stack exchange,提问作者JOYSON S T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 17:42:39