首页 > 其他分享 >Unity之NetworkView聊天室功能

Unity之NetworkView聊天室功能

时间:2023-01-05 13:39:17浏览次数:33  
标签:聊天室 namesInfoDictionary text RPC private transform Unity GetComponent NetworkVie


  • NetworkView是Unity封装的一套快速实现多人联机游戏的功能。以此为基础,我们可以开发各种类型的多人游戏,可以开发过关游戏的双人联机,也可以开发类似于CS的射击游戏,以房间为单位。
  • 属性


    1.isMine : Network View 是否是由本机创建的。


    2.observed:指定被观察及同步的组件或者脚本。


    3.stateSynchronization:Network View的类型。OFF为没有数据将被同步,ReliableDeltaCompressed


     为当前数据发生变化时才发送,Unreliable为强制发送数据。


    4.viewID:NetworkViewID类型的ID。


  • 函数


    1.RPC(Remote Procedure Call,远程过程调用)。在Network系统中可以理解为向其他机器发送消息,如果


      有同名函数将被调用。


    2.networkView.RPC(string funName,RPCMode mode,params object[] args);参数funName为函数


     名,参数mode指定发送的范围,可选范围包括全部连接的机器包括本机,例如,All是发送给所有机器,


     Server是发送给服务器。args是传递的参数,可传可不传,支持类型包括int,float, string,   


     NetworkPlayer,NetworkViewID,Vector3,Quaternion,不支持List集合。


    3.只要有Network View,那么任何游戏对象上的脚本的函数体前用[RPC]标注,就可以通过RPC来通知调


     用,但是函数名必须是唯一的,否则其中只有一个会被调用。


  • 聊天室:要想达到信息共享,在有客户端加入时要清除所有用户(包括客服端与服务器)之前的数据,并在客户端与服务器端都要重新加载(使用Unity自带函数)。(比如需要记录每个进入聊天室人的姓名,当某个人退出时,删除他的名字,某个人进来时,记录他的名字,并将之前的已经进入的人的名字发送给这个人。这一系列操作只需通过服务器来实现,当客户端连接时,namesInfoDictionary添加信息并发送给所有客户端,客户端断开时,移除信息并发送给所有客户端。)

下面是制作过程:

本文做的只是一个简单的Demo,用来参考。。。一个简单的场景,场景里全部都是UI,demo里只有一个脚本名为mychat,没有其他了。具体如下:

新建场景,新建一些UI并命名如下(这些名字都可以在代码里找到,关键是代码)

Unity之NetworkView聊天室功能_服务器

然后在Canvas上绑定自己写的脚本mychat和network view组件,如下

Unity之NetworkView聊天室功能_服务器_02

 

重点是脚本,mychat的全部脚本如下:

using UnityEngine;
using UnityEngine.UI;
using Button = UnityEngine.UI.Button;
using System.Collections.Generic;
public class MyChat : MonoBehaviour
{
public Text showtestplayer;

private Text peopleCount;
private Text peopleNames;
private Text chatText;
private InputField inputField;
private Button senon;
private InputField myNameField;
private Button createServerButton;
private Text createServeText;
private Button connectServerButton;
private Text connectServerText;
private Text warn;
private string ip = "192.168.239.1";
private int port = 9001;
private bool hasConnectServer;
private bool hasCreateServer;
private string myName;
private Dictionary<string ,string> namesInfoDictionary=new Dictionary<string, string>();


// private Dictionary namesInfoDictionary = new Dictionary();
private NetworkView networkView;
private string namesStr;
void Start()
{
peopleCount = transform.Find("bg/count").GetComponent<Text>();
peopleNames = transform.Find("bg/name").GetComponent<Text>();
chatText = transform.Find("bg/Image/Scroll View/Viewport/Content/Text").GetComponent<Text>();
inputField = transform.Find("bg/InputField").GetComponent<InputField>();
senon = transform.Find("bg/sendBtn").GetComponent<Button>();
myNameField = transform.Find("myname").GetComponent<InputField>();
createServerButton = transform.Find("createBtn").GetComponent<Button>();
createServeText = createServerButton.transform.Find("Text").GetComponent<Text>();
connectServerButton = transform.Find("connectBtn").GetComponent<Button>();
connectServerText = connectServerButton.transform.Find("Text").GetComponent<Text>();
warn = transform.Find("warn").GetComponent<Text>();
peopleCount.text = "0";
peopleNames.text = "";
chatText.text = "";
createServeText.text = "CreateServer";
connectServerText.text = "ConnectServer";
warn.text = "请先创建自己的昵称,根据自己需要创建/连接服务器。";
networkView = transform.GetComponent<NetworkView>();
senon.onClick.AddListener(delegate
{
networkView.RPC("SendMsg", RPCMode.All, myName + ":" + inputField.text);
});

createServerButton.onClick.AddListener(delegate
{
if (!hasCreateServer)
{
if (myNameField.text != null)
{
NetworkConnectionError error = Network.InitializeServer(20, port, false);
if (error == NetworkConnectionError.NoError)
{

myName = myNameField.text;
hasCreateServer = true;
myNameField.text = "";
createServeText.text = "DestroyServer";
warn.text = "";
namesInfoDictionary.Add(Network.player.ToString(), myName);


StoreName(namesInfoDictionary);
networkView.RPC("GetNames", RPCMode.All, namesStr);
networkView.RPC("SendMsg", RPCMode.All, myName + "创建了聊天室");
}
}
else
{
warn.text = "请创建自己的名字";
}
}
else
{
Network.Disconnect();
hasCreateServer = false;
createServeText.text = "CreateServer";
}
});
connectServerButton.onClick.AddListener(delegate
{
if (!hasConnectServer)
{
if (myNameField.text != null)
{
NetworkConnectionError error = Network.Connect(ip, port);
if (error == NetworkConnectionError.NoError)
{
myName = myNameField.text;
hasConnectServer = true;
myNameField.text = "";
connectServerText.text = "DisConnect";
warn.text = "";
}
}
else
{
warn.text = "请创建自己的名字";
}
}
else
{
Network.Disconnect();
hasConnectServer = false;
connectServerText.text = "ConnectServer";
}
});
}
//---------------记录name列表,因为RPC不可以传入List集合,所以要把信息转为字符串------------
private void StoreName(Dictionary<string ,string> namesDictionary)
{
namesStr = "";
foreach (var VARIABLE in namesDictionary)
{
namesStr += VARIABLE.Value + ";";
}
}
//-------------------------------------聊天,发送信息---------------------------------------
[RPC]
private void SendMsg(string info)
{
if (info != "")
{
chatText.text += info + "\n";
inputField.text = "";
}
}
//----------------------客户端调用,通知服务器,更改namesInfoDictionary---------------------
void OnConnectedToServer()
{
networkView.RPC("PlayerJoin", RPCMode.Server, myName);
networkView.RPC("SendMsg", RPCMode.All, myName + "进入了聊天室");
}
//--------------------服务器调用,更改namesInfoDictionary,并共享name列表------------------
[RPC]
private void PlayerJoin(string name, NetworkMessageInfo info)
{
namesInfoDictionary.Add(info.sender.ToString(), name);

StoreName(namesInfoDictionary);
networkView.RPC("GetNames", RPCMode.All, namesStr);
}
//-------------------------------客户端断开连接,服务器调用----------------------------------
void OnPlayerDisconnected(NetworkPlayer player)
{

networkView.RPC("SendMsg", RPCMode.All, namesInfoDictionary[player.ToString()] + "离开了聊天室");
PlayerRemove(player.ToString());
}
//--------------不必使用RPC,因为更新namesInfoDictionary只需在服务器端进行。----------------
private void PlayerRemove(string nameID)
{
if (namesInfoDictionary.ContainsKey(nameID))
{
namesInfoDictionary.Remove(nameID);
}
StoreName(namesInfoDictionary);
networkView.RPC("GetNames", RPCMode.All, namesStr);
}
//---------------------------客户端与服务器更新名字列表,参数不能为List-------------------------
[RPC]
private void GetNames(string names)
{
namesStr = names;
peopleNames.text = "";
string[] str = namesStr.Split(';');
foreach (var VARIABLE in str)
{
if (VARIABLE != "")
peopleNames.text += VARIABLE + "\n";
}
peopleCount.text = (str.Length - 1).ToString();
}
}

这样就可以了。

打包开始测试:

打开exe后进入,看到如下画面:此处我用箭头标注了一下每个UI的作用。

Unity之NetworkView聊天室功能_RPC_03

之后填写上用户名,然后点击场景server进行创建服务器。

再启动一个exe,输入用户名然后点击连接服务器,之后就输入内容点击button发送聊天消息了。如下:

Unity之NetworkView聊天室功能_RPC_04

 

本文参考网上一篇文章进行了整理,并非原创,找不到原文链接了,如有用到可以参考研究。

标签:聊天室,namesInfoDictionary,text,RPC,private,transform,Unity,GetComponent,NetworkVie
From: https://blog.51cto.com/u_8378185/5990802

相关文章

  • unity之粒子碰撞触发方法
    需求是用水灭掉火焰。所以水的粒子要与火焰的粒子发生碰撞时执行灭火事件。效果如图: 首先从火焰角度思考:火焰的粒子要监测是否被撞到,所以要给它加上碰撞体。同时勾选collis......
  • Unity制作聊天室功能
    用untiy作客户端、用VS的控制台程序来做服务器。首先是服务器端的代码,分两个类一个Program,一个ForClient类。分别如下:usingSystem.Net.Sockets;usingSystem.Collections.......
  • unity的UI Event事件(Event Trigger和EventSystem对比)
    首先看Unity中UIEvent事件介绍上图中出现的组件在场景里都是unity里的事件相关的组件。例如:场景里EventSystem里默认就有Standaloneinputmodule这个组件(当然也可以随便加......
  • Unity3D之数据持久化储存
        首先我们来看两段Unity3D中实现数据读写的简单代码吧://保存数据PlayerPrefs.SetString("Name",mName);PlayerPrefs.SetInt("Age",mAge);PlayerPref......
  • Unity计时器功能
    在程序开发中很多地方会用到计时器进行倒计时的功能。下面我就写一个非常实用的倒计时功能。首先在场景中建一个Text用来显示倒计时的数值,然后给它加上倒计时的脚本Timer。......
  • Unity3D常用函数说明
    Unity3D中所有控制脚本的基类MonoBehaviour有一些虚函数用于绘制中事件的回调,也可以直接理解为事件函数,例如大家都很清楚的Start,Update等函数,以下做个总结。 Awake当前控......
  • Unity跳转场景报空指针解决
    当跳转场景时,有时候会出现空指针问题。解决办法:将即将跳转到的scene添加到BuildSettings里面。举个例子:例如从某个场景要跳转到network这个场景中,那么BuildSettings里面必......
  • Unity利用协同实现场景异步加载
    1.usingUnityEngine;2.usingSystem.Collections;3.4.publicclassFightTriggle:MonoBehaviour{5.privateAsyncOperationasync;6.i=0;7.......
  • Unity3D中Resources动态加载NGUI图片
    在NGUI中有些图片我需要动态进行变更或者加载,怎么办?首先在项目中创建一个Resources目录,接着把需要的图片放在这里面,可以有子文件夹么?当然可以,文件结构很重要哦~NGUI加载图片......
  • Unity和Easy AR制作一个AR的APP
    这个不是什么正规的项目。。。就是觉得AR好玩,研究了一下,很早之前就玩过了,现在再做的时候竟然忘记了。看来还是要记录一下的。。。功能就是:用手机扫描一个图片,然后会出现一个......