当前位置: 首页 > 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 重新学习下...

linux内核 - request_irq 介绍

一&#xff1a;概述GPU在执行任务时&#xff0c;本质上是一个异步设备&#xff0c;由CPU提交任务&#xff0c;GPU执行&#xff0c;那么GPU完成任务后&#xff0c;CPU怎么知道&#xff1f;答案是GPU触发 IRQ&#xff0c;让CPU收到中端信号。 另外有一个核心问题是&#xff0c;硬…...

RexUniNLU与VSCode插件开发:智能代码注释生成工具

RexUniNLU与VSCode插件开发&#xff1a;智能代码注释生成工具 1. 引言 作为一名每天要写几百行代码的程序员&#xff0c;你有没有这样的经历&#xff1a;写完一个复杂的函数后&#xff0c;盯着代码看了半天&#xff0c;却不知道该怎么写注释&#xff1f;或者更常见的是&#…...

如何快速提升中文文献管理效率:Jasminum插件3大核心功能完整指南

如何快速提升中文文献管理效率&#xff1a;Jasminum插件3大核心功能完整指南 【免费下载链接】jasminum A Zotero add-on to retrive CNKI meta data. 一个简单的Zotero 插件&#xff0c;用于识别中文元数据 项目地址: https://gitcode.com/gh_mirrors/ja/jasminum 还在…...

和AI一起搞事情#:边剥龙虾边做个中医技能来起号道

1. 核心概念 在 Antigravity 中&#xff0c;技能系统分为两层&#xff1a; Skills (全局库)&#xff1a;实际的代码、脚本和指南&#xff0c;存储在系统级目录&#xff08;如 ~/.gemini/antigravity/skills&#xff09;。它们是“能力”的本体。 Workflows (项目级)&#xff1a…...

13.3补充-层次风格-SOA

一、层次架构风格 &#xfeff;00:00 1. CS架构 &#xfeff;00:45 1&#xff09;两层C/S架构 基本结构&#xff1a;由表示层&#xff08;客户端&#xff09;和数据层&#xff08;服务器&#xff09;组成&#xff0c;两层都具备业务处理功能工作流程&#xff1a; 客户端接收用户…...

云原生环境中的大数据处理架构

云原生环境中的大数据处理架构 &#x1f525; 硬核开场 各位技术老铁&#xff0c;今天咱们聊聊云原生环境中的大数据处理架构。别跟我扯那些理论&#xff0c;直接上干货&#xff01;在大数据时代&#xff0c;如何高效处理和分析海量数据成为了一个挑战。不搞云原生大数据处理&a…...

从达克熊螺旋栈道看木质拼装玩具的魅力:为何老少皆宜的创意新宠?

开篇&#xff1a;一次愉快的拼装体验最近我入手了一款达克熊的螺旋栈道木质拼装玩具&#xff0c;原本只是抱着试试看的心态&#xff0c;没想到不仅家里小朋友爱不释手&#xff0c;连我这个"大朋友"也沉迷其中。这款玩具让我们全家度过了一个充满创意和欢笑的周末&…...

“人工智能+”政策给企业带来的机遇与JBoltAI的助力

企业引入AI项目与产品的显著优势 在“人工智能”政策的大背景下&#xff0c;企业引入AI项目与产品能够带来多方面的优势。首先&#xff0c;AI技术能够显著提升业务处理效率。例如&#xff0c;在金融行业&#xff0c;智能风控模型可以快速分析大量数据&#xff0c;精准识别潜在…...

开源大模型研报工具:Pixel Epic与Llama-Research在专业度上的横向评测

开源大模型研报工具&#xff1a;Pixel Epic与Llama-Research在专业度上的横向评测 1. 评测背景与工具介绍 在金融分析、市场研究和学术写作领域&#xff0c;高质量的研究报告生成工具正变得越来越重要。本次评测将对比两款基于开源大模型的研报生成工具&#xff1a;Pixel Epi…...

墨语灵犀保姆级教程:Windows/Mac/Linux三端镜像部署与使用详解

墨语灵犀保姆级教程&#xff1a;Windows/Mac/Linux三端镜像部署与使用详解 1. 开篇引言&#xff1a;当古典美学遇见AI翻译 你是否曾经遇到过这样的场景&#xff1a;需要阅读外文文献&#xff0c;但机器翻译的结果生硬冰冷&#xff0c;完全失去了原文的韵味&#xff1f;或者需…...