unity之network客户端向服务器发送消息【Command】方法详解

时间:2023-01-05 13:00:03


如果是纯粹是聊天室功能则可以使用NetworkView的方法来进行,简单实用。

如果不是聊天室功能而是要传递数据给服务器,同时为了以后更多功能的拓展性,还是应该用network manager来实现。

无论是哪种方式,unet里的的一个特点就是:服务器端是会包括客户端的。换言之客户端和服务器是在同一个场景里开发的。。。此处的包括二字何解?就是服务器端会自动生成一个player(之前很多文章都在讲unet的player与服务器同步的问题,那是入门级别的东西,多看看就知道是怎么回事)。这个player身上具备的属性就是客户端的玩家具备的属性。当然这个player只是代指客户端而已。实际可以理解为在networkmanager里自动生成一个客户端。

如果是做局域网的传输,在networkmanager里一定要注意不要勾选use websockets这一项。

unity之network客户端向服务器发送消息【Command】方法详解

本文案例为局域网,需求是客户端进行考核之后,客户端的系统逻辑会判断出分数,然后将分数传给服务器。而此处只说如何从客户端把分数传给服务器这一功能。

开始搞起:

新建一个场景,内容network(空物体)、client(红色的cube)、UI的Text显示文本(需要把客户端传来的值显示出来)。

unity之network客户端向服务器发送消息【Command】方法详解

然后在network物体上添加上networkmananger组件和managerHUD组件。不需要其他的另外的脚本了。

unity之network客户端向服务器发送消息【Command】方法详解

client这个物体添加network identity,和我写的Clientmanager脚本

unity之network客户端向服务器发送消息【Command】方法详解

然后看Clientmanager脚本的具体内容,如下:

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
using UnityEngine.UI;

public class clientmanager : NetworkBehaviour
{
private Text GetTexts;

//[SyncVar]/// 用来标记同步成员变量,可以是任何基本数据类型,但不能是类、列表或其他集合
private int scores = 95;
// Use this for initialization
void Start()
{
GetTexts = GameObject.Find("Canvas").gameObject.transform.FindChild("Text").gameObject.GetComponent<Text>();
}

// Update is called once per frame
void Update()
{
if (isLocalPlayer)
{
if (Input.GetMouseButtonDown(1))
{
Debug.Log("点击右键发送");
//为了测试每次点击让分数+2
scores += 2;
CmdSendMessage(scores);
}
}

}


///加了Command之后,该方法必须Cmd开头,方法虽然写在客户端的脚本里,但是是在服务器执行的,所以执行的效果也是只有服务器能看到。

[Command]
void CmdSendMessage(int i)
{
GetTexts.text += i.ToString() + "在服务器端执行\n";
}
}

 

这样打包来进行测试,打开两个,一个作为服务器,另一个打开的作为客户端。

当鼠标右键点击客户端的时候会看到,在服务器的Text显示列表中会不断的打印出东西,说明完成了客户端的数据上穿到服务器功能:

unity之network客户端向服务器发送消息【Command】方法详解

至此功能已经完成了。。。下面的文字用来解释原理。

 


然后说说原理吧,可以看到,服务端我们没有绑定自己写的任何脚本,同步功能用了系统 的networkmanager,在初始化的时候就会自动生成了客户端,UI用的是系统自带的network namager HUD来实现的,所以重点是在客户端了。

客户端的代码也非常简单,在Update里面确定了是isLocalPlayer也就是说只有本地客户端的时候就可以进行右键点击,当右键点击的时候就会给初始化的scores = 95这值加2,然后调用了CmdSendMessage(scores);这个方法,把分数的值作为参数传递。

重点说说[Command]这个玩意,虽然之前的文章中说过它的功能但此处还是再详细讲解下。如下述:

CmdSendMessage();这个方法是被 [Command]标记过的,所以是会在服务器端执行的,不会再本地执行。如果取消了[Command]的标志那就肯定只在本地执行了也就是完全的本地的方法啊和服务端没关系。。。所以如果没有[Command]的标志,上图中的那些值就会在本客户端显示出来而不会显示在服务器。

所以最后的总结就是:如果要从客户端把数据传到服务器,脚本绑定到客户端,并且需要在对应的方法前加上 [Command],这样这个方法虽然写在客户端但是实际运行会在服务端,运行的效果也只会呈现在服务端而不是客户端。