Unity之NetCode多人网络游戏联机对战教程(8)--玩家位置同步
文章目录
- 前言
- 添加相机
- 玩家添加对应组件
- 服务端权威(server authoritative)
- 客户端权威(client authoritative)
- 服务端同步位置
- 阅读与理解`PlayerTransformSync.cs`
- NetworkVariable
- UploadTransform
- SyncTransform
- 后话
前言
承接上篇,在Player上添加了移动脚本之后,还得同步每个玩家的位置。
添加相机
- 在
Main Camera
上添加一个CinemachineBrain
组件 - 新建一个空物体
Camera
,添加CinemachineVirtualCamera
与CinemachineCollider
这两个组件
先不手动绑定玩家,等后面在脚本控制摄像机的跟随对象。
玩家添加对应组件
- 确保玩家的预制体添加了
碰撞体
与其他两个Network
组件
在NetworkTransform
组件上选择要同步的轴,这里我只选择同步Position
与Rotation
的XYZ轴
服务端权威(server authoritative)
到目前位置,玩家位置已经是确实同步到了,但是还有一点是你移动的时候会把全部带有PlayerMove
脚本的角色都移动,下面要针对自己的角色才移动。所以得修改一下PlayerMove.cs
这个脚本
using System;
using Cinemachine;
using Cinemachine.Utility;
using UnityEngine;
using Unity.Netcode;public class PlayerMove : NetworkBehaviour
{public float Speed;public float VelocityDamping;public float JumpTime;public enum ForwardMode{Camera,Player,World};public ForwardMode InputForward;public bool RotatePlayer = true;public Action SpaceAction;public Action EnterAction;Vector3 m_currentVleocity;float m_currentJumpSpeed;float m_restY;private void Start(){if (IsOwner){GameObject.Find("===Camera===/Camera").GetComponent<CinemachineVirtualCamera>().Follow = transform;}}private void Reset(){Speed = 5;InputForward = ForwardMode.Camera;RotatePlayer = true;VelocityDamping = 0.5f;m_currentVleocity = Vector3.zero;JumpTime = 1;m_currentJumpSpeed = 0;}private void OnEnable(){m_currentJumpSpeed = 0;m_restY = transform.position.y;SpaceAction -= Jump;SpaceAction += Jump;}void Update(){if (!IsOwner) return;
#if ENABLE_LEGACY_INPUT_MANAGERVector3 fwd;switch (InputForward){case ForwardMode.Camera:fwd = Camera.main.transform.forward;break;case ForwardMode.Player:fwd = transform.forward;break;case ForwardMode.World:default:fwd = Vector3.forward;break;}fwd.y = 0;fwd = fwd.normalized;if (fwd.sqrMagnitude < 0.01f)return;Quaternion inputFrame = Quaternion.LookRotation(fwd, Vector3.up);Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));input = inputFrame * input;var dt = Time.deltaTime;var desiredVelocity = input * Speed;var deltaVel = desiredVelocity - m_currentVleocity;m_currentVleocity += Damper.Damp(deltaVel, VelocityDamping, dt);transform.position += m_currentVleocity * dt;if (RotatePlayer && m_currentVleocity.sqrMagnitude > 0.01f){var qA = transform.rotation;var qB = Quaternion.LookRotation((InputForward == ForwardMode.Player && Vector3.Dot(fwd, m_currentVleocity) < 0)? -m_currentVleocity: m_currentVleocity);transform.rotation = Quaternion.Slerp(qA, qB, Damper.Damp(1, VelocityDamping, dt));}// Process jumpif (m_currentJumpSpeed != 0)m_currentJumpSpeed -= 10 * dt;var p = transform.position;p.y += m_currentJumpSpeed * dt;if (p.y < m_restY){p.y = m_restY;m_currentJumpSpeed = 0;}transform.position = p;if (Input.GetKeyDown(KeyCode.Space) && SpaceAction != null)SpaceAction();if (Input.GetKeyDown(KeyCode.Return) && EnterAction != null)EnterAction();
#elseInputSystemHelper.EnableBackendsWarningMessage();
#endif}public void Jump(){m_currentJumpSpeed += 10 * JumpTime * 0.5f;}
}
编译构建之后发现可以正常使用,但是还有一个问题就是,只能是Server
端可以移动,Client
端没办法移动,这是一个BUG吗?显然不是。
客户端权威(client authoritative)
因为NetworkTransform
默认是服务端的权威验证,客户端没办法更新自己的位置,只能通过告知服务器我的位置更新了,然后服务器在告诉别人他的位置更新了。
如果想用客户端权威
就需要添加ClientNetworkTransform
来代替NetworkTransform
这个组件
去包管理器添加Git URL
包,https://github.com/Unity-Technologies/com.unity.multiplayer.samples.coop.git?path=/Packages/com.unity.multiplayer.samples.coop#main
在Player
上添加ClientNetworkTransform
,删除NetworkTransform
其他保持不变,编译运行就可以实现客户端移动了。
服务端同步位置
新建个脚本PlayerTransformSync.cs
,挂载到Player
上。移除ClientNetworkTransform
PlayerTransformSync.cs
:
using Unity.Netcode;
using UnityEngine;public class PlayerTransformSync : NetworkBehaviour
{private NetworkVariable<Vector3> _syncPos = new();private NetworkVariable<Quaternion> _syncRota = new();private void Update(){if (IsLocalPlayer){UploadTransform();}}private void FixedUpdate(){if (!IsLocalPlayer){SyncTransform();}}private void SyncTransform(){transform.position = _syncPos.Value;transform.rotation = _syncRota.Value;}private void UploadTransform(){if (IsServer){_syncPos.Value = transform.position;_syncRota.Value = transform.rotation;}else{UploadTransformServerRpc(transform.position, transform.rotation);}}[ServerRpc]private void UploadTransformServerRpc(Vector3 position, Quaternion rotation){_syncPos.Value = position;_syncRota.Value = rotation;}
}
一般情况下,都是用的服务器权威这种方式做位置同步。
阅读与理解PlayerTransformSync.cs
该脚本可分为四部分去理解:
- 创建网络同步字段
- 如果是主机就不需要向
Server
发送信息可直接同步 - 如果是客户则需要向
Server
发送信息请求同步 - 同步其他人的位置信息
NetworkVariable
通过NetworkVariable
创建两个网络同步的字段,一个同步position
,另一个同步rotation
private NetworkVariable<Vector3> _syncPos = new();
private NetworkVariable<Quaternion> _syncRota = new();
然后本地玩家通过UploadTransform
方法,上传自己的位置信息,这里又有两种情况
- 为主机时
- 为客户时
UploadTransform
为主机时,直接同步Transform
即可
为客户时,向服务器发送信息,请求同步Transform
private void UploadTransform()
{if (IsServer){_syncPos.Value = transform.position;_syncRota.Value = transform.rotation;}else{UploadTransformServerRpc(transform.position, transform.rotation);}
}[ServerRpc]
private void UploadTransformServerRpc(Vector3 position, Quaternion rotation)
{_syncPos.Value = position;_syncRota.Value = rotation;
}
SyncTransform
我自己上传位置就是在同步,别人就把位置信息同步到transform。
在Update()
与FixedUpdate()
可以确保优先级,先同步自己的,在同步他人的。
private void Update()
{if (IsLocalPlayer){UploadTransform();}
}private void FixedUpdate()
{if (!IsLocalPlayer){SyncTransform();}
}private void SyncTransform()
{transform.position = _syncPos.Value;transform.rotation = _syncRota.Value;
}
后话
这次的位置同步教程是服务端
与客户端
直接的基础通信,需要知道用法,还有搞清楚服务端与客户端之间的逻辑才是本次教程最大的重点。
NetworkVariable
这个用于字段网络同步有很大帮助,[ServerRpc]
与[ClientRpc]
之间的通信以后会经常用到,后面博文会继续深入讲解。
相关文章:

Unity之NetCode多人网络游戏联机对战教程(8)--玩家位置同步
文章目录 前言添加相机玩家添加对应组件服务端权威(server authoritative)客户端权威(client authoritative)服务端同步位置阅读与理解PlayerTransformSync.csNetworkVariableUploadTransformSyncTransform 后话 前言 承接上篇&a…...

spring boot 中@Value读取中文配置时乱码
1.spring boot 读取application.properties 该文件是iso8859编码 如果是直接写中文 读取时会乱码 显示成?? 必须得转ascii码才能正常显示 其他方法测试也不行 Value("${apig.order.tiaokong.qianzi}") private String apigOrderTiaokongQianzi;...
选择.NET 还是 Java?
1、.NET Framework的演变: .NET Framework: 最初由Microsoft引入,是一个Windows上的全功能框架。它包含了ASP.NET、Windows Presentation Foundation(WPF)、Windows Communication Foundation(WCFÿ…...
vue 高阶组件;高阶组件
vue 高阶组件;高阶组件 文章目录 vue 高阶组件;高阶组件1. 什么是高阶组件2. 高阶组件的作用3. 高阶组件的使用 例子1:创建一个简单的高阶组件例子2:使用element-ui的高阶组件 1. 什么是高阶组件 高阶组件是一个函数,传给它一个组件…...

数据结构:树的基本概念(二叉树,定义性质,存储结构)
目录 1.树1.基本概念1.空树2.非空树 2.基本术语1.结点之间的关系描述2.结点、树的属性描述3.有序树、无序树4.森林 3.树的常考性质 2.二叉树1.基本概念2.特殊二叉树1.满二叉树2.完全二叉树3.二叉排序树4.平衡二叉树 3.常考性质4.二叉树的存储结构1.顺序存储2.链式存储 1.树 1.…...
【Qt之QStandardItemModel类】介绍
描述 QStandardItemModel类提供了一个通用的模型,用于存储自定义数据。QStandardItemModel可以用作Qt标准数据类型的存储库。它是 Model/View类 之一,是 Qt的model/view框架 的一部分。 QStandardItemModel提 供了一种基于项目的传统方法来处理模型。 Q…...

01-Spring中的工厂模式
工厂模式 工厂模式的三种形态: 工厂模式是解决对象创建问题的属于创建型设计模式,Spring框架底层使用了大量的工厂模式 第一种:简单工厂模式是工厂方法模式的一种特殊实现,简单工厂模式又叫静态工厂方法模式不属于23种设计模式之一第二种:工厂方法模式…...

Linux是什么,Linux系统介绍
很多小伙伴都不是那么了解和知道Linux,到底Linux是什么? 像大家用到的安卓手机,生活中用到的各种智能设备,比如路由器,光猫,智能家具等,很多都是在Linux操作系统上。 Linux是什么?Li…...
爬虫项目(11):使用多线程对36手机高清壁纸批量抓取
文章目录 书籍推荐目标网址单线程实现多线程实现爬取结果书籍推荐 如果你对Python网络爬虫感兴趣,强烈推荐你阅读《Python网络爬虫入门到实战》。这本书详细介绍了Python网络爬虫的基础知识和高级技巧,是每位爬虫开发者的必读之作。详细介绍见👉: 《Python网络爬虫入门到…...

JavaScript_动态表格_删除功能
1、动态表格_删除功能 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>动态表格_添加和删除功能</title><style>table{border: 1px solid;margin: auto;width: 100%;}td,th{text-align: …...
一步一步开发微信小程序(Django+Mysql)
前提:假设你已经安装好Anaconda,微信开发者工具,MySQL数据库,IDE等工具 工具下载地址: Anaconda:https://www.anaconda.com/download MySQL:https://dev.mysql.com/downloads/mysql/ 微信开…...

mysql 讲解(1)
文章目录 前言一、基本的命令行操作二、操作数据库语句2.1、创建数据库2.2、删除数据库2.3、使用数据库2.4 查看所有数据库 三、列的数据类型3.1 字符串3.2 数值3.3 时间日期3.4 空3.5 int 和 varchar问题总结: 四、字段属性4.1 UnSigned4.2 ZEROFILL4.3 Auto_InCre…...
k8s关于metadata、spec.containers、spec.volumes的属性介绍(yaml格式)
目录 一.metadata常用属性 二.spec.containers子属性介绍 explain pod.spec.containers给出的参考 1.command示例演示 2.env和envFrom示例演示 3.ports部分详解 4.resources部分详解 5.startupProbe格式演示 6.terminationMessagePath和terminationMessagePolicy格式演…...

腾讯域名优惠卷领取
腾讯域名到到期了,听说申请此计划,可获得优惠卷,看到网上5年域名只需要10元,姑且试试看。 我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?in…...

elastic-job 完结篇
一 elastic-job 1.1 案例场景分析 1.设置4个分片,10秒执行一次。 分片弹性扩容缩容机制测试: 测试1:测试窗口1不关闭,再次运行main方法查看控制台日志,注意修改application.properties中的 server.port…...

基于 Gin 的 HTTP 代理 demo
上次用 TCP 模拟了一个 HTTP 代理之后,感觉那样还是太简陋了,想着是不是可以用框架来做一个有点实际用处的东西。所以,就思索如何用 golang 的 Gin 框架来实现一个?嗯,对的你没有听错,是 gin 框架。你可能会…...

【ATTCK】MITRE Caldera - 测试数据泄露技巧
CALDERA是一个由python语言编写的红蓝对抗工具(攻击模拟工具)。它是MITRE公司发起的一个研究项目,该工具的攻击流程是建立在ATT&CK攻击行为模型和知识库之上的,能够较真实地APT攻击行为模式。 通过CALDERA工具,安全…...

【数据结构】树与二叉树(十二):二叉树的递归创建(算法CBT)
文章目录 5.2.1 二叉树二叉树性质引理5.1:二叉树中层数为i的结点至多有 2 i 2^i 2i个,其中 i ≥ 0 i \geq 0 i≥0。引理5.2:高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点,其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…...
Qt绘制网格和曲线
绘制网格: void Widget::drawGrid(QPainter &p, QRect &windRect) {QRect rect(windRect.left()m_margins.left(),windRect.top()m_margins.top(),windRect.width()-m_margins.left()-m_margins.right(),windRect.height()-m_margins.top()-m_margins.bo…...
2023-11-12
今日比较摆烂, 但是把自写管道的原理搞懂了, 主要是把 exp 完完全全看懂了, 还不错. 然后就没干啥了. 明日计划: 学校的作业. AFL 源码. 我真是服了我自己了, AFL 源码搁多久了, 操操操 然后把 seccomp 重新学习下...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...