dedecms 网站地图 插件,长沙精品网站建设公司,哔哩哔哩推广平台,网站定制开发上海文章目录 前言添加相机玩家添加对应组件服务端权威#xff08;server authoritative#xff09;客户端权威#xff08;client authoritative#xff09;服务端同步位置阅读与理解PlayerTransformSync.csNetworkVariableUploadTransformSyncTransform 后话 前言
承接上篇server authoritative客户端权威client authoritative服务端同步位置阅读与理解PlayerTransformSync.csNetworkVariableUploadTransformSyncTransform 后话 前言
承接上篇在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).GetComponentCinemachineVirtualCamera().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 NetworkVariableVector3 _syncPos new();private NetworkVariableQuaternion _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 NetworkVariableVector3 _syncPos new();
private NetworkVariableQuaternion _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]之间的通信以后会经常用到后面博文会继续深入讲解。