0x00 介绍NetWorkManager
网络管理器,用来控制多人游戏项目的状态,包括游戏状态管理、生成管理、场景管理,匹配以及允许访问调试信息。可以参考下(网上参考)面两张图片:
第一个案例是官方案例
- 基础实现篇(1-2)
- 拓展细化篇 (3)
第二个案例是一个简易的聊天室(4)
最近项目测试用到的,记录一下 ,通过两个案例让大家充分了解unet,希望对大家有所帮助。最终效果如图所示(因测试需求需创建新玩家时修改不同标签等数据,所以图中是代码生成玩家,稍后都会写到):

0x00 简介
-
首先说一下Network Manager HUD组件(即连接方式的UI选择框):
- LAN Host:选择后就相当于主机,并且也代表第一个玩家,等待别的玩家连接。
- LAN Client: 客户端,输入要连接的服务器连接即可。
- LAN Server Only:仅当做服务器,等待其他玩家连接。
-
[Command] 表示客户端向服务端发送的命令,在服务端执行
-
[SyncVar]用于标识序列化变量,实现变量同步
-
[SyncEvent]用于标识序列化事件,实现事件同步
-
[Client]表示只能在客户端调用
-
[ClientCallback]表示客户端执行的回调
-
[ClientRpc]表示服务端向客户端发送的命令,在客户端执行
0x01 创建NetWorkManager
- 首先创建一个GameObject。(自己命名如:_NetWorKManager)
- 添加NetworkManager和NetworkManagerHUD这两个组件。
如下所示:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QPYM2uRa-1586240263004)(https://i.imgur.com/4fk2XiE.png)]](/https://i-blog.csdnimg.cn/blog_migrate/b73e1fb2549dbacabeac5fd28b854499.png#pic_center)
因需求我是自己创建一个脚本,然后继承的NetWorkManager,稍后会仔细说道。
0X02 创建玩家
- 首先在Hierarchy面板新建一个胶囊体Capsule(样式自定义即可)重命名为:Player
- 给玩家添加NetWorkIdentity组件,并且将Local Player Anthority勾选。
- 如需同步和自定义玩家位置需挂NetWorkTransform组件(细化里面详细讲解)如图所示:
- 最后把玩家拖制为预制体,然后把预制体拖到NetwoekManager下的Spawn Info 的 PlayerPrefab中,将Hierrarchy中的Player删除即可。
- 给玩家添加脚本,自定义命名即可(例子为:PlayerController)首先来制作玩家的移动。(即wasd移动,直接上代码)
#region 字段定义
private float horizontal;
private float vertical;
#endregion
void Update()
{
if (!isLocalPlayer)
{
return;
}
PlayerMove();
}
/// <summary>
/// 简单的人物移动
/// </summary>
private void PlayerMove()
{
horizontal = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
vertical = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;
transform.Rotate(0, horizontal, 0);
transform.Translate(0, 0, vertical);
}
- 现在已经可以运行程序(点击LAN Server即可出现)
- 因自带的NetworkTransform容易出现玩家之间卡顿同步移动现象(挂在该脚本目的是为了玩家之前能同步显示位置) 所以我重写了脚本如下所示:
/// <summary>
/// 修复networkTransform,优化卡顿,解决偶尔出现同时同时移动问题
/// </summary>
public class Player_SyncPosition : NetworkBehaviour
{
#region 字段
[SyncVar] private Vector3 _syncPos;
[SyncVar] private Quaternion _syncRot;
private Transform _myTransform;
[SerializeField] private float _lerpRate = 15;
#endregion
#region 系统方法
private void Start()
{
_myTransform = gameObject.transform;
}
void FixedUpdate()
{
TransformPosition();
LerpPosition();
}
#endregion
#region 系统方法
void LerpPosition()
{
if (!isLocalPlayer)
{
_myTransform.position = Vector3.Lerp(_myTransform.position, _syncPos, Time.deltaTime * _lerpRate);
_myTransform.rotation = Quaternion.Lerp(_myTransform.rotation, _syncRot, Time.deltaTime * _lerpRate);
}
}
[Command]
void CmdProvidePositionToServer(Vector3 pos, Quaternion rot)
{
_syncPos = pos;
_syncRot = rot;
}
[ClientCallback]
void TransformPosition()
{
if (isLocalPlayer)
{
CmdProvidePositionToServer(_myTransform.position, _myTransform.rotation);
}
}
#endregion
}
效果如图所示(因为大小限制所以看个大概吧):




&spm=1001.2101.3001.5002&articleId=105363505&d=1&t=3&u=adfe864e7fdd4986bef6a6ecf5496e03)
1736

被折叠的 条评论
为什么被折叠?



