Unity之NetCode多人网络游戏联机对战教程(6)--NetworkTransform组件

news2024/11/26 15:44:29

文章目录

    • 前言
    • NetworkTransform是什么
    • 玩家移动脚本
    • NetworkTransform字段讲解
      • Synchronizing ("Syncing")
      • Thresholds
      • Local space
      • Interpolation
      • Slerp Position
      • Use Quaternion Synchronization
      • Use Quaternion Compression
      • Use Half Float Precision
      • Authority modes
        • Server Authoritative Mode
        • Owner Authoritative Mode
      • Additional Virtual Methods of Interest
    • 后话
    • 官方链接

前言

这次教程主要是讲同步两个玩家的位置信息的一个非常重要的组件NetworkTransform,以及这个组件的作用与说明。


NetworkTransform是什么

同步物体的Transform是Netcode当今多人游戏中最常见的任务之一。这个概念似乎很简单:

  • 确定您要同步的变换轴。
  • 序列化这些值。
  • 将序列化的值作为消息发送给所有其他连接的客户端。
  • 处理消息并反序列化值。
  • 将这些值应用到适当的轴上。

乍一看,上面列出的任务似乎相对简单,但当您开始实现每个任务时,几乎任何经验丰富的Netcode软件工程师都会同意:这可能迅速变得复杂。

例如,上面列出的任务并没有考虑以下几点:

  • 谁控制同步(即每个客户端、服务器或者根据要同步的对象而定可能两者都控制)?
  • 以何种频率同步这些值,以及确定何时需要同步这些值的逻辑应该是什么?
  • 如果您有复杂的父子关系层次结构(父变换带有一个或多个子变换),是应该同步世界空间轴值还是本地空间轴值?
  • 如何优化每次变换更新的带宽成本?

幸运的是,Netcode for GameObjects (NGO) 提供了NetworkTransform组件的实现,它处理了一些变换同步的棘手方面,并可以通过在编辑器中的检视面板中访问的属性轻松配置。


玩家移动脚本

Package Manager --> 左上角+号旁边的包 选择Unity Registry, 搜索Cinemachine 下载并导入

PlayerMove移动到Scripts,在预制体Player上添加该脚本



NetworkTransform字段讲解

Synchronizing (“Syncing”)

这个是用来指定同步位置,旋转,缩放的,需要同步哪些值就勾选哪些

一般情况下,不需要同步GameObject的所有变换值。例如,如果GameObject的缩放从不改变,可以在面板中的Syncing Scale禁用。禁用同步可以节省CPU成本和网络带宽。

Thresholds

您可以使用阈值值来设置最小阈值。这可以用来通过只同步大于或等于阈值值的变化(低于阈值的变化不会同步)来降低同步更新的频率。例如:

如果NetworkTransform启用了插值(Interpolate),您可能会发现可以降低位置阈值的分辨率(增加位置阈值值),而不影响对象运动的"平滑度",同时还减少位置更新的频率(减少每个实例的带宽成本)。增加阈值分辨率(降低位置阈值值)会增加对象的位置同步的潜在频率(可能会增加每个实例的带宽成本)。

阈值值不会被同步,但可以在authoritative实例上进行更新。在使用所有者authoritative模式的实例时,应该牢记这一点,因为更改所有权将使用新所有者实例上当前设置的任何值。如果您计划在运行时更改阈值值并计划更改所有权,那么您可能需要同步阈值值。

Local space

默认情况下,NetworkTransform世界空间同步对象的变换。In Local Space配置选项允许您改为在本地空间中同步变换。子对象的本地空间轴值(主要是位置和旋转)始终是相对于父变换的偏移。而子对象的世界空间轴值包括父对象的轴值。

在具有父对象的NetworkTransform上使用本地空间可以改善在对象重新父对象化时的变换同步,因为重新父对象化不会改变对象的本地空间变换,但会改变世界空间位置。

authoritative实例确实会同步对LocalSpace属性的更改。因此,您可以在运行时在authoritative实例上调整此属性,而非authoritative实例将自动更新。

Interpolation

默认情况下启用了插值(·Interpolation·),如果您希望在非authoritative实例上的变换更新之间实现平滑的过渡,这是推荐的设置。插值会缓冲传入的状态更新,这可能会在authoritative实例和非authoritative实例之间引入轻微的延迟。当禁用插值属性时,变换的更改会立即应用到非authoritative实例上,这可能会导致视觉上的"抖动",或者在延迟较高时似乎会"跳跃"到新应用的状态更新。

在权威实例上在运行时更改插值属性将与所有非权威实例同步。

NetworkTransform组件仅在客户端上进行插值。为了在主机或服务器上实现更平滑的移动,用户可能还希望在服务器端实现插值。尽管服务器不会受到网络引起的抖动影响,但仍然可能会在本地出现一些卡顿(例如,在FixedUpdate中进行的低物理更新率的移动)。

Slerp Position

当设置了这个属性并且同时启用了插值(Interpolation),非authoritative实例将通过Slerp而不是Lerp朝着它们的目标位置插值。通常,这可以在对象遵循圆形和/或基于样条的运动路径时使用,以保留该路径的曲线性。由于在两点之间进行"lerp"插值会在两点之间的线上产生线性进展,因此在某些情况下,位置状态更新的频率可能会导致对象运动曲线的损失。

Use Quaternion Synchronization

默认情况下,使用欧拉角值来同步旋转增量。对于许多情况,使用欧拉角值可能就足够了。然而,有些情况下,同步欧拉角增量会产生不希望的结果。一个情况是当您有复杂的嵌套NetworkTransforms,其中父子变换之间的旋转不同。当您将插值结合在一起(记住插值是有缓冲的,在非权威的当前旋转和目标旋转之间存在固有的延迟时),立即发生在Quaternion中的调整会处理更复杂的变换相关问题(例如吉姆巴锁等)。

启用Quaternion同步时,权威实例仍然会根据欧拉轴值与阈值值进行比较,以确定是否需要更新变换的旋转,但是会更新整个Quaternion,而不仅仅是检测到变化的欧拉轴。这意味着可以确保正确的旋转将应用于非权威实例,并且已经考虑到了使用欧拉角时可能出现的更复杂问题。

Quaternion同步是有代价的。它会增加带宽成本,每个实例增加16字节,以处理更复杂的旋转问题,这种问题在使用嵌套的NetworkTransform(一个或多个父变换和一个或多个子变换)时更常见。但是,当您启用Use Quaternion Synchronization属性时,您会注意到在同步轴选择复选框和一个新的Use Quaternion Compression属性会出现:

当启用Use Quaternion Synchronization时,不再提供旋转同步轴复选框(因为同步变换的四元数将始终更新所有旋转轴),而Use Quaternion Compression成为可见选项。

Use Quaternion Compression

由于同步四元数可能会增加NetworkTransform旋转状态更新的带宽成本,因此有两种方法可以减小四元数同步的总体带宽成本:

  • 四元数压缩(Quaternion Compression):这提供了最高的压缩率(每次更新减少到4字节),但精度损失略高于半浮点精度。

  • 半浮点精度(Half Float Precision):当启用并且禁用四元数压缩时,这提供了中等级别的替代压缩(每次更新减少到8字节),比完全浮点值的精度低,但比四元数压缩的精度高。

四元数压缩是基于最小三算法的,当旋转精度不如带宽成本重要时,可以使用它。您可能有需要某种形式的旋转同步的附属对象/抛射物,但在项目的整体方案中不需要完美对齐。

如果带宽成本和精度都是问题,那么备选的推荐压缩方法是半浮点精度。此外,建议尝试不同的压缩选项,您可能会发现精度的部分损失对于项目的需求是完全可以接受的(并且可以减小所有实例的总体带宽成本,最多减少50%的带宽成本,而不使用完全精度时)。

此属性值可以在权威实例在运行时进行更新,并将同步到所有非权威实例。提醒:在authoritative实例上在运行时更新此值将导致NetworkTransform的完全同步,所有非authoritative实例的插值器将被重置。

Use Half Float Precision

启用此属性将会将任何变换轴值从4字节浮点数转换为2字节半浮点数,但会以精度损失为代价。启用此选项时,所有标记为同步的变换轴都将使用半浮点精度。然而,关于位置和旋转,半浮点精度有一些独特的方面。

由于存在精度损失,位置状态更新仅提供相对于上一个已知完整位置的位置增量。NetworkDeltaPosition可序列化结构会跟踪上一个已知完整位置和当前与上一个已知完整位置的当前增量偏移之间的当前增量。此外,NetworkDeltaPosition会在发送更新时自动纠正精度损失。从先前更新的精度损失将包含在下一个位置更新中。换句话说,非authoritative实例可以在1个tick周期的持续时间内或直到接收到下一个变换状态更新之前,潜在地与authoritative实例具有来自每次应用的更新的分数增量。此外,NetworkDeltaPosition填补了半浮点值的最大值与Unity世界空间的最大边界(全局/项目缩放相关)之间的差距。

推荐的Unity世界空间单位每秒:
每个更新的最大增量不应超过64个Unity世界空间单位。如果您使用默认的tick(30),那么对象不应以等于或超过每秒1920个Unity世界空间单位的速度移动(即30 x 64)。作为参考,默认摄像机的远裁剪平面是1000个Unity世界空间单位,这意味着以1920个Unity世界空间单位的速度移动的物体可能不会在渲染视锥体中被视觉检测到,或者会以短暂的"闪烁"出现。

当启用Use Quaternion SynchronizationUse Half Float Precision并且禁用Use Quaternion Compression时,四元数值通过HalfVector4可序列化结构进行同步,其中每个轴值(x、y、z和w)都存储为半浮点值。这意味着每个旋转更新从完全精度的每次16字节减少到每次8字节。对于旋转,使用半浮点精度提供了比四元数压缩更好的精度,带宽成本是其两倍,但是只有完全精度的一半成本。

当启用Use Quaternion SynchronizationUse Half Float PrecisionUse Quaternion Compression时,四元数压缩将用于代替半浮点精度的旋转。

当在authoritative实例上进行更新时,所有这些属性都将同步到非authoritative实例。

Authority modes

Server Authoritative Mode

默认情况下,NetworkTransform在服务器authoritative模式下运行。这意味着服务器端检测到要同步的变换轴(标记为同步),并将其推送给连接的客户端。这也意味着对变换轴值的任何更改都将被authoritative状态(在这种情况下是服务器端的变换状态)覆盖。

还有一个关于轴同步与初始同步的变换值的概念需要牢记。未标记为同步的任何轴在NetworkObject被生成或客户端第一次同步时仍会被更新为authoritative的初始状态。

举个例子:
假设您只标记了位置和旋转轴来同步,但在NetworkTransform组件的网络预制上排除了所有缩放轴。当您生成网络预制的实例时,初始的权威方缩放值将在生成时同步。从那时起,非authoritative实例(在这种情况下是客户端实例)将保持相同的缩放轴值,即使它们不再更新。

Owner Authoritative Mode

(又名:ClientNetworkTransform)

服务器端权威的NetworkTransform在同步转换和在所有连接的客户端上应用更新之间提供了平衡。然而,有时您希望特定NetworkObject(通常是玩家)在客户端上立即更新位置。NetworkTransform的所有者权威由NetworkTransform.OnIsServerAuthoritative方法决定,该方法在首次初始化NetworkTransform组件时调用。如果该方法返回true(默认值),则它将初始化为服务器权威的NetworkTransform。如果返回false,则它将初始化为所有者authoritativeNetworkTransform(也称为ClientNetworkTransform)。这可以通过从NetworkTransform派生,覆写OnIsServerAuthoritative虚拟方法,并像下面的代码示例中一样返回false来实现:

using Unity.Netcode.Components;
using UnityEngine;

namespace Unity.Multiplayer.Samples.Utilities.ClientAuthority
{
    /// <summary>
    /// 用于同步客户端端的变换更改。这包括主机。不支持纯服务器作为所有者,请使用NetworkTransform。
    /// 用于那些始终由服务器拥有的Transform。
    /// </summary>
    [DisallowMultipleComponent]
    public class ClientNetworkTransform : NetworkTransform
    {
        /// <summary>
        /// Used to determine who can write to this transform. Owner client only.
        /// This imposes state to the server. This is putting trust on your clients. Make sure no security-sensitive features use this transform.
        /// </summary>
        protected override bool OnIsServerAuthoritative()
        {
            return false;
        }
    }
}

ClientNetworkTransform示例:

选择Window --> Package Manager来打开包管理器。

Add(+) --> 从git URL添加…

复制并粘贴以下Git URL:https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop.git?path=/Packages/com.unity.multiplayer.samples.coop#main

或者修改项目的manifest.json,添加

"com.unity.multiplayer.samples.coop": "https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop.git?path=/Packages/com.unity.multiplayer.samples.coop#main"

该Transform将所有者客户端的位置与服务器和所有其他客户端同步,从而实现客户端authoritative的游戏玩法。

Additional Virtual Methods of Interest

NetworkTransform.OnAuthorityPushTransformState: 此虚拟方法在权威实例正在将新的NetworkTransformState推送给非authoritative实例时调用。这可以用于更精确地确定用于预测相关任务的非authoritative实例的更新值。

NetworkTransform.OnNetworkTransformStateUpdated: 此虚拟方法在非权威实例接收来自authoritative实例的推送NetworkTransformState更新时调用。这可以用于更精确地确定用于预测相关任务的非authoritative实例的更新值。

NetworkTransform.Awake: 为了提供自定义初始化的能力,此方法已被设置为虚拟方法。如果您覆盖此方法,建议首先调用base.Awake()

NetworkTransform.OnInitialize: 此虚拟方法在相关的NetworkObject首次生成以及所有权更改时调用。

NetworkTransform.Update: 为了提供您对派生NetworkTransform类进行任何自定义的能力,此方法已被设置为虚拟方法。如果您覆盖此方法,要求所有非authoritative实例调用base.Update(),但对于authoritative实例则不是必须的。


后话

有了NetworkTransform这个组件可以为位置同步省了很多功夫,后面讲NetworkTransform的实战应用

官方链接

https://docs-multiplayer.unity3d.com/netcode/current/components/networktransform/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1177680.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

银河E8,吉利版Model 3:5米大车身、45寸大屏、首批8295座舱芯

作者 | Amy 编辑 | 德新 吉利银河E8在曝光后多次引爆热搜&#xff0c;李书福更是赞誉有加&#xff0c;称其为「买了就直接享受」。这款备受瞩目的车型于 10月30日晚首次亮相。 虽然新车外观在今年上海车展上早已曝光&#xff0c;但这次的发布会却带来了不少惊喜。新车架构以及…

pytorch安装1

用豆瓣源安装pytorch1.5.1&#xff08;速度很快&#xff09;-CSDN博客 详情请参考这位神仙的博客 我真的哭死&#xff0c;原来torch都安装好了&#xff0c;好不容易全部加载好了&#xff0c;但是&#xff0c;gpu配不上去&#xff0c;后来发现还是版本的问题版本不匹配具体版本…

Element对象_属性

Element对象对应网页的HTML元素。每一个HTML元素&#xff0c;在DOM树上都会转化成一个Element节点对象&#xff08;以下简称元素节点&#xff09; 1、Element.id Element.id属性返回指定元素的id属性&#xff0c;该属性可读写 2、Element.className className属性用来读写当前…

k8s 1.28安装

容器运行时&#xff0c;containerd 按照官方的指导&#xff0c;需要安装runc和cni插件&#xff0c;提示的安装方式&#xff0c;有三种&#xff1a; 二进制安装包源码apt-get 或 dnf安装 我们这里选用第三种&#xff0c;找到docker官方提供的安装方式 ubuntu-containerd # A…

rhcsa-文件内容显示

浏览普通文件内容 浏览文件的命令 命令常用选项说明cat -n 对输出内容中的所有行标注行号 -b 对输出内容中的非空行标注行号 查看文件的内容head-num 指定需要显示文件num行的内容默认查看文前十行的内容tail -num 指定需要显示文件num行的内容 -f 使tail不停的去读取显示文…

PHP保存时自动删除末尾的空格,phpstorm自动删除空白字符串

最近有个活儿&#xff0c;修改一个财务软件。 修改后给客户验收的过程中&#xff0c;客户反应有一个txt表格导出功能不能用了。之前是好的。 这次是新增&#xff0c;老的这个功能碰都没碰过&#xff0c;怎么能有问题呢&#xff1f;我心里OS 下班后我立马用系统导出TXT&#…

搜维尔科技:Movella Xsens和scalefit携手推进高精度人体工程学分析

Movella xsens是一家领先的传感器、软件和分析全栈提供商&#xff0c;致力于实现运动数字化和比例调整一家著名的人体工程学分析解决方案提供商&#xff0c;已联手重塑工作场所人体工程学。这项战略合作结合了先进技术和专业知识&#xff0c;以推进人体工程学评估并促进更健康、…

JavaScript_Element对象_获取元素位置

1、Element.clientHeight&#xff0c;Element.clientWidth&#xff08;常用&#xff09; Element.clientHeight属性返回一个整数值&#xff0c;表示元素节点的CSS高度&#xff08;单位像素&#xff09;&#xff0c;只对块级元素生效&#xff0c;对于行内元素返回0。如果块级元…

【Web】在前端中,HTML<meta>标签

<meta>实例 <head><meta name"description" content"免费在线教程"><meta name"keywords" content"HTML,CSS,XML,JAVASCRIPT"><meta name"author" content"runoob"><meta char…

three.js 航拍全景图(+陀螺仪)

右上角陀螺仪也可点击,需要https的环境,手动下载DeviceOrientationControls.js文件 后台包含打点功能 <template><div id"quanjing" style"width: 100vw; height: 100vh; overflow: hidden"><spanid"tip"style"position: ab…

骨骼动画详解

【物体怎么样是在动】 当物体的位置、朝向、大小即Transform有任意一者发生变化时&#xff0c;物体在动。 但变化要达到一定的幅度时&#xff0c;我们会看到物体在动&#xff0c;幅度是多少却决于我们看这个物体的距离、方向&#xff0c;物体的朝向等因素。 这里说的幅度是指…

【Windows】解决电脑可以正常使用微信,但是打不开网页

问题 啊哈 如题&#xff0c;在安装软件的过程中突然就发现浏览器不能用了&#xff0c;但是微信可以正常接发消息。 记录一下解决过程。 解决 1、自动DNS 打开控制面板->网络和Internet->网络和共享中心&#xff0c;点击以太网&#xff0c;找到属性Internet协议4(TCP/…

手机怎么打包?三个方法随心选!

有的时候&#xff0c;电脑不在身边&#xff0c;只有随身携带的手机&#xff0c;这个时候又急需把文件打包发送给同事或者同学&#xff0c;如何利用手机操作呢&#xff1f;下面介绍了具体的操作步骤。 一、通过手机文件管理自带压缩功能打包 1、如果是iOS系统&#xff0c;就在手…

猫头虎分享从Python到JavaScript传参数:多面手的数据传递术

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

dell r720

dell r720的idrac的地址默认是192.168.1.110&#xff0c;root 默认密码calvin fatal Error! All channnels have been disabled due to all DIMMs failed the Memoey 是什么意思 Dell PowerEdge T320服务器 开机显示 Fatal Errort!all channells have been disabled due to …

【鹰王系统】又一个干净纯净的window系统下载站点,值得推荐!

今天给大家分享一个高质量的window系统下载站点【鹰王系统】&#xff0c;此站长自己制作了winxp、win7、win10、win11等各种版本系统&#xff0c;都是非常不错的系统镜像&#xff0c;都是免费下载没有任何捆绑信息&#xff0c;值得推荐。 网站首页截图 系统下载截图&#xff1a…

Java 高效生成按指定间隔连续递增的列表(int,double)

简介 Java 按照指定间隔生成连续递增的List 列表&#xff08;引入Stream 类和流操作来提高效率&#xff09;&#xff1a; 1. 生成递增的List< Integer> Testpublic void test009(){int start 1;int interval 2;int count 10;List<Integer> list IntStream.ite…

集群外访问计算节点gpu上的web链接

情况描述 现在有一个程序&#xff0c;通过提交作业的方式在集群的计算节点C上运行&#xff0c;运行后给了一个web的地址,如下图所示 然而&#xff0c;在自己电脑A上只能访问集群的管理节点B&#xff0c;无法直接访问计算节点。管理节点可以访问计算节点&#xff0c;计算节点无…

Git extension 中合并工具kdiff3乱码问题

打开kdiff3合并工具&#xff0c;setting->region settings 设置下面的编码格式为utf-8就可以啦&#xff01; 注意&#xff1a;需要在合并工具中设置编码格式&#xff0c; 在git 中配置编码格式没有效果

Keep-Alive中通过component多次加载同样的动态组件无法保持状态的解决办法

Keep-Alive中通过component多次加载同样的动态组件无法保持状态的解决办法 Keep-Alive中通过component多次加载同样的动态组件无法保持状态的解决办法 | 软件开发服务商 (yidianhulian.com)https://yidianhulian.com/?p12263 问题描述 项目功能上有需要动态添加组件的需求&…