当前位置: 首页 > news >正文

Unity之NetCode多人网络游戏联机对战教程(8)--玩家位置同步

文章目录

    • 前言
    • 添加相机
    • 玩家添加对应组件
    • 服务端权威(server authoritative)
    • 客户端权威(client authoritative)
    • 服务端同步位置
    • 阅读与理解`PlayerTransformSync.cs`
      • NetworkVariable
      • UploadTransform
      • SyncTransform
    • 后话

前言

承接上篇,在Player上添加了移动脚本之后,还得同步每个玩家的位置。


添加相机

  • Main Camera上添加一个CinemachineBrain组件
  • 新建一个空物体Camera,添加CinemachineVirtualCameraCinemachineCollider这两个组件

先不手动绑定玩家,等后面在脚本控制摄像机的跟随对象。


玩家添加对应组件

  • 确保玩家的预制体添加了碰撞体与其他两个Network组件

NetworkTransform组件上选择要同步的轴,这里我只选择同步PositionRotationXYZ


服务端权威(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)--玩家位置同步

文章目录 前言添加相机玩家添加对应组件服务端权威&#xff08;server authoritative&#xff09;客户端权威&#xff08;client authoritative&#xff09;服务端同步位置阅读与理解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的演变&#xff1a; .NET Framework&#xff1a; 最初由Microsoft引入&#xff0c;是一个Windows上的全功能框架。它包含了ASP.NET、Windows Presentation Foundation&#xff08;WPF&#xff09;、Windows Communication Foundation&#xff08;WCF&#xff…...

vue 高阶组件;高阶组件

vue 高阶组件;高阶组件 文章目录 vue 高阶组件;高阶组件1. 什么是高阶组件2. 高阶组件的作用3. 高阶组件的使用 例子1&#xff1a;创建一个简单的高阶组件例子2&#xff1a;使用element-ui的高阶组件 1. 什么是高阶组件 高阶组件是一个函数&#xff0c;传给它一个组件&#xf…...

数据结构:树的基本概念(二叉树,定义性质,存储结构)

目录 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类提供了一个通用的模型&#xff0c;用于存储自定义数据。QStandardItemModel可以用作Qt标准数据类型的存储库。它是 Model/View类 之一&#xff0c;是 Qt的model/view框架 的一部分。 QStandardItemModel提 供了一种基于项目的传统方法来处理模型。 Q…...

01-Spring中的工厂模式

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

Linux是什么,Linux系统介绍

很多小伙伴都不是那么了解和知道Linux&#xff0c;到底Linux是什么&#xff1f; 像大家用到的安卓手机&#xff0c;生活中用到的各种智能设备&#xff0c;比如路由器&#xff0c;光猫&#xff0c;智能家具等&#xff0c;很多都是在Linux操作系统上。 Linux是什么&#xff1f;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)

前提&#xff1a;假设你已经安装好Anaconda&#xff0c;微信开发者工具&#xff0c;MySQL数据库&#xff0c;IDE等工具 工具下载地址&#xff1a; Anaconda&#xff1a;https://www.anaconda.com/download MySQL&#xff1a;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问题总结&#xff1a; 四、字段属性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格式演…...

腾讯域名优惠卷领取

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

elastic-job 完结篇

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

基于 Gin 的 HTTP 代理 demo

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

【ATTCK】MITRE Caldera - 测试数据泄露技巧

CALDERA是一个由python语言编写的红蓝对抗工具&#xff08;攻击模拟工具&#xff09;。它是MITRE公司发起的一个研究项目&#xff0c;该工具的攻击流程是建立在ATT&CK攻击行为模型和知识库之上的&#xff0c;能够较真实地APT攻击行为模式。 通过CALDERA工具&#xff0c;安全…...

【数据结构】树与二叉树(十二):二叉树的递归创建(算法CBT)

文章目录 5.2.1 二叉树二叉树性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点&#xff0c;其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…...

Qt绘制网格和曲线

绘制网格&#xff1a; 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 重新学习下...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

毫米波雷达基础理论(3D+4D)

3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...

DAY 26 函数专题1

函数定义与参数知识点回顾&#xff1a;1. 函数的定义2. 变量作用域&#xff1a;局部变量和全局变量3. 函数的参数类型&#xff1a;位置参数、默认参数、不定参数4. 传递参数的手段&#xff1a;关键词参数5 题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一…...

echarts使用graphic强行给图增加一个边框(边框根据自己的图形大小设置)- 适用于无法使用dom的样式

pdf-lib https://blog.csdn.net/Shi_haoliu/article/details/148157624?spm1001.2014.3001.5501 为了完成在pdf中导出echarts图&#xff0c;如果边框加在dom上面&#xff0c;pdf-lib导出svg的时候并不会导出边框&#xff0c;所以只能在echarts图上面加边框 grid的边框是在图里…...