U#中 RequestSerialization() OnDeserialization() 与 SendCustomNetworkEvent() 的区别

RequestSerialization()

  • 作用:请求同步 UdonSynced 变量的状态到所有客户端。
  • 调用时机:当一个客户端更改了带有 UdonSynced 属性的变量后,调用 RequestSerialization() 以确保这些变化被同步到所有其他客户端。
  • 执行顺序RequestSerialization() 会触发服务器在后台处理并将数据传播给其他客户端,但这是一个异步过程,调用后不会立即生效。

OnDeserialization()

  • 作用:当客户端接收到来自服务器的同步数据时自动调用。
  • 调用时机:当服务器将同步数据发送到客户端时,客户端接收到数据后,OnDeserialization() 会被自动调用,用于处理这些同步数据并进行相应的状态更新。
  • 执行顺序:在客户端接收到同步数据之后自动调用,不需要显式调用。

SendCustomNetworkEvent()

  • 作用:发送一个自定义网络事件,并在指定的目标客户端上调用特定的方法。
  • 调用时机:需要触发某个特定事件,并在所有或指定的客户端上执行相应的逻辑时使用。
  • 执行顺序:通常在同步变量之后调用,以确保事件处理时变量状态已同步。

关系及执行流程

  1. 更改同步变量并请求同步

    • 客户端 A 更改 UdonSynced 变量的值,并调用 RequestSerialization() 以请求服务器同步该变量。
    • RequestSerialization() 触发服务器处理同步请求,并在后台将数据传播给其他客户端。
  2. 客户端接收同步数据

    • 服务器将同步数据发送给所有客户端,包括客户端 A 自己。
    • 客户端 B 接收到同步数据后,自动调用 OnDeserialization() 方法。
  3. 执行网络事件

    • 在客户端 A 调用 RequestSerialization() 之后,可以调用 SendCustomNetworkEvent() 以通知所有客户端执行某些操作。
    • 这确保了当客户端接收到网络事件时,同步变量的最新状态已经生效。

代码示例及解析

using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
using TMPro;

public class EarthRotationController : UdonSharpBehaviour
{
    [UdonSynced(UdonSyncMode.None)]
    private bool isRotating = false; // 控制地球是否旋转的布尔变量

    public GameObject earth; // 地球模型
    public TextMeshPro statusText; // 显示地球旋转状态的文本
    public float rotationSpeed = 10f; // 控制地球旋转速度

    private void Start()
    {
        UpdateStatusText();
        UpdateButtonState();
    }

    private void Update()
    {
        if (isRotating)
        {
            // 绕自身的 Y 轴旋转
            earth.transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime, Space.Self);
        }
    }

    public override void Interact()
    {
        // 检查并请求对象的拥有权
        if (!Networking.IsOwner(gameObject))
        {
            Networking.SetOwner(Networking.LocalPlayer, gameObject);
        }

        // 切换地球旋转状态
        isRotating = !isRotating;

        // 请求同步变量 同步 isRotating 的值
        RequestSerialization();

        // 发送网络事件,通知所有客户端更新状态文本和按钮状态
        SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.All, "UpdateStatusText");
        SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.All, "UpdateButtonState");
    }

    private void UpdateButtonState()
    {
        if (!isRotating)
        {
            earth.transform.rotation = Quaternion.Euler(23.5f, earth.transform.rotation.eulerAngles.y, 0);
        }
    }

    public void UpdateStatusText()
    {
        if (isRotating)
        {
            statusText.text = "Earth is rotating";
        }
        else
        {
            statusText.text = "Earth is stopped";
        }
    }

    public override void OnDeserialization()
    {
        // 当同步变量更新时调用,确保状态同步
        UpdateStatusText();
        UpdateButtonState();
    }
}

代码解析

  1. 更改同步变量并请求同步

    • Interact() 方法中,当用户点击按钮时,切换 isRotating 变量的状态。
    • 调用 RequestSerialization() 请求同步 isRotating 变量的值。
  2. 发送网络事件

    • 调用 SendCustomNetworkEvent() 发送自定义网络事件,通知所有客户端调用 UpdateStatusText()UpdateButtonState() 方法。
    • 这些方法负责更新文本状态和地球的旋转状态。
  3. 处理同步数据

    • 当其他客户端接收到同步数据时,自动调用 OnDeserialization() 方法。
    • OnDeserialization() 方法中调用 UpdateStatusText()UpdateButtonState(),确保状态在所有客户端同步。

OnDeserialization() 下执行的方法和 SendCustomNetworkEvent()传递的方法是一样的,这是为什么?

OnDeserialization()
当同步变量更新时(例如通过 RequestSerialization() 请求后),OnDeserialization() 在所有客户端被调用。
我们在 OnDeserialization() 中调用 UpdateStatusText() 和 UpdateButtonState() 以确保所有客户端的状态一致。
SendCustomNetworkEvent()
当需要立即通知所有客户端执行某些逻辑时(例如在按钮点击事件中),使用 SendCustomNetworkEvent()。
即使客户端已经在 OnDeserialization() 中更新了状态,我们依然通过 SendCustomNetworkEvent() 确保所有客户端执行相应的更新逻辑,避免任何潜在的延迟或不同步问题。

  • 17
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值