1.下载
Mirror是一个简单高效的开源的unity多人游戏网络框架,Mirror在Unity商店中是免费的,因此直接加入自己的资源库并在导入即可。
官方API地址:https://mirror-networking.gitbook.io/docs
2.使用
1.创建场景的网络管理器
网络管理器是多人游戏的核心控制组件。网络管理器是多人游戏的核心控制组件。
在起始场景中创建一个空游戏对象,然后添加新创建的网络管理器组件。在起始场景中创建一个空游戏对象,然后添加新创建的网络管理器组件。
注:如果没有获取到kcp transport组件,手动添加。
2.创建一个玩家
建立一个cube作为玩家。
添加networkIdentity作为在网络同步的唯一标识。
只有挂载了networkIdentity,网络中枢才能识别到这个物件,并对之进行同步。接下来将Cube作为一个预制体保存,并在场景中删除,后拖拽预制体到网络中枢的Player Prefab插槽中,以后它的产生就完全依靠网络中枢在连接到主机后自动生成。
注:如果角色预制体托不进player prefab栏,可能是没有挂在network identity组件
添加Network Transform,同步网络中联网游戏对象的位置、旋转和缩放。
Mirror 目前提供2种Network Transform:
Reliable:低带宽,与Rpcs/Cmds/等相同的延迟。
Unreliable:高带宽,极低延迟
使用Reliable,除非需要超低延迟。
3.添加玩家初始生成位置
创建几个空物体作为玩家的初始生成位置,添加Network Start PositionNetwork,控制玩家的生成位置要控制玩家的生成位置。
根据Network Manager里面Player Spawn Method(玩家生成方法设置):
1.Random:生成为随机(可能相同的生成位置将被两个或更多玩家使用)
2.Round Robin:循环(使用每个可用位置,直到客户端数超过生成点数)。
4.玩家控制
网络同步需要注意的一些事情:
1.需要用到联网功能的脚本中都要添加using Mirror来使用相应API,并且继承NetworkBehaviour而不是MonoBehaviour。
2.涉及到玩家输入时,首先先要进行isLocalPlayer的判断
为控制游戏对象,添加一个脚本为PlayerControl.cs,继承NetworkBehaviour。
Start函数——>重写OnStartLocalPlayer函数。(OnStartLocalPlayer:仅在client执行,当脚本所在物体为玩家角色时调用,用来设置跟踪相机,角色初始化等)
public override void OnStartLocalPlayer()
{
//摄像机与角色绑定
Camera.main.transform.SetParent(transform);
Camera.main.transform.localPosition = Vector3.zero;
//player初始化
//player 名称的位置,大小
name.transform.localPosition = new Vector3(0, -0.3f, 0.6f);
name.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
//随机生成颜色和名字
ChangedColorAndName();
}
数据同步:
当服务器的场景中的一个SyncVar的值发生变化时,就同步给其它所有客户端。
//需要把name和颜色同步给其他玩家,添加同步变量的标记[SyncVar(hook=nameof(FunctionExecOnClient))]
[SyncVar(hook = nameof(OnPlayerNameChanged))]
private string playerName;
[SyncVar(hook = nameof(OnPlayerColorChanged))]
private Color playerColor;
//申明OnPlayerNameChanged和OnPlayerColorChanged这两个方法
//第一个变量(oldstr)是同步变量修改前的值,第二个(newstr)是同步变量修改后的值
private void OnPlayerNameChanged(string oldstr,string newstr)
{
nameText.text = newstr;
}
private void OnPlayerColorChanged(Color oldCor,Color newCor)
{
nameText.color = newCor;
playerMaterialClone = new Material(GetComponent<Renderer>().material);
playerMaterialClone.SetColor("_EmissonColir", newCor);
GetComponent<Renderer>().material = playerMaterialClone;
}
玩家名字、颜色的变化,以及远程控制:
/// <summary>
/// player 的随机名称和颜色
/// </summary>
private void ChangedColorAndName()
{
//随机名称和颜色
var tempName = $"Player{Random.Range(1, 999)}";
var tempColor = new Color(Random.Range(0, 1f), Random.Range(0, 1f), Random.Range(0, 1f), 1);
//同步变量进行修改
CmdSetupPlayer(tempName, tempColor);
}
//对于同步变量的修改,使用[Command]标记(针对方法的标记,方法名以Cmd开头)
//通过这个方法同时对name和颜色进行修改
[Command]
private void CmdSetupPlayer(string name,Color color)
{
playerName = name;
playerColor = color;
}
移动代码:
private void Update()
{
if (!isLocalPlayer)
{
name.transform.LookAt(Camera.main.transform);
return;
}
var movex = Input.GetAxis("Horizontal") * Time.deltaTime * 110f;
var movez = Input.GetAxis("Vertical") * Time.deltaTime * 4f;
transform.Rotate(0, movex, 0);
transform.Translate(0, 0, movez);
if (Input.GetKey(KeyCode.Space))
{
ChangedColorAndName();
}
}