【技术博客】Unity多人在线同步 | week9

Unity单机场景快速转换多人联机教程

简介

本教程基于Mirror实现:

Unity AssetStore链接:https://assetstore.unity.com/packages/tools/network/mirror-129321

官网:https://mirror-networking.com/

文档:https://mirror-networking.gitbook.io/docs/

场景的创建

首先我们需要一个已经实现好的单机场景,这个场景在后续将被用作多人场景,现在按CTRL+D复制一份它,重命名为GamePlay。之后我们再创建一个场景Offline和一个场景Online,分别表示大厅(此时还未连接至服务器)和房间(连接至服务器但未开始游戏)。具体来说,运行机制是首先玩家进入Offline等待,选择服务器后跳转至Online,最后开始游戏则在GamePlay中。

网络控制器

下面我们在Offline中创建一个空物体名为NetworkManager。创建一个脚本为MyNetworkManager.cs,注意创建时通过Mirror创建NetworkManager,如下图。

image-20220501160615067

之后再将其挂载在之前创建的空物体上即可。此外还需要加上下面两个,其中NetworkManagerHUD是可视化UI,可先用其简单快速上手控制服务器的连接,后期可删除,将功能通过代码写在NetworkManager中。下面的Transport是传输协议,可选KCP(使用UDP)或Telepathy(使用TCP)。

image-20220501160828106

网络控制器暂时先这样就完成了。

游戏玩家与物体

在游戏中所有游戏物体均要有NetworkIdentity,因此先把之前的所有物体(如玩家、子弹等需要同步的)制作为新的预制体,并加上下面这个。

image-20220501161349143

之后加上同步位置和动画的脚本即可,如下(当然没动画的话可以只同步位置)

image-20220501161614361

最后将我们的场景、玩家预制体、游戏物体等等放入之前做的网络控制器即可。

image-20220501160738501

进阶

同步变量

如果有一个变量是需要同步至所有客户端的,那么这个变量是一个同步变量,同步变量只能通过服务器来修改。下面以同步自己的名字为例讲解。

首先设置该变量为同步变量,加上[SyncVar]注解即可:

[SyncVar(hook =nameof(NameChanged))]
public string playerNameStr;

其中的hook是指当该变量改变时,本地客户端需要运行的函数

private void NameChanged(string oldStr, string newStr)
{
	nameText.text = newStr;
}

比如名字需要在被服务器修改后,将头上的Text设置为修改后的值。

下面是如何让服务器修改这个值,在函数前加上[Command]注解:

[Command]
private void CmdChangeName(string name)
{
	playerNameStr = name;
}

在我们需要改这个值的时候调这个函数即可命令服务器修改这个值,修改之后所有的客户端会自动调用NameChanged,修改玩家头上的Text。

public override void OnStartLocalPlayer()
{
	if (!isLocalPlayer)
	{
		return;
	}
	CmdChangeName(UserInforManager.username);
}

比如我这里是在玩家初始化的时候将名字修改为了用户名。

服务器的构建与部署

从上面来看,我们并不需要额外写服务器的代码,因为实际上服务器需要所有客户端的资源,否则无法完成沟通。但是我们也不可能手动去控制服务器,因此我们可以通过在网络控制器上加上一个脚本来控制自动开始:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
namespace Networks
{
    public class AppControl : MonoBehaviour
    {
        public bool isServer;
        void Start()
        {
            if(isServer)
            {
                GetComponent<MyMultiNetworkManager>().StartServer();
            }
            else
            {
                GetComponent<MyMultiNetworkManager>().StartClient();
            }
        }

    }
}

在build服务器时,我们可以勾上isServer,在buildSettings里也勾上ServerBuild(这个会把渲染关闭,减小服务器的运行消耗),build后服务器便会自动开启server服务了。

其他

建议直接看Mirror中的示例,里面有几个比较简单的样例,如如何生成一个物体(炮弹之类的),计分的同步等等。

posted @ 2022-05-05 23:34  头发茂盛队  阅读(939)  评论(0编辑  收藏  举报