基于Socket,用UGUI实现游戏场景中玩家的聊天
如图,聊天UI分为两部分:对话框、输入框。 实现的功能如下
1.默认情况下,对话框不可见,按下回车键显示对话框和输入框,鼠标光标在输入框
2.再按一下回车键,输入框消失,再按回车键,输入框出现
3.当只有对话框没有输入框时,对话框持续显示4s,然后渐变消失
4.在输入框输入文本,按回车键后消息发送,在对话框显示,输入框消失,过4s文本框消失
5.自己发送的消息是浅蓝色的,对方发送的消息是红色的
首先非常感谢 @董董在这 ,参考了他的https://blog.csdn.net/sajiazaici/article/details/78312887制作UI的方法
通过该文章可以做好UI面板,即聊天框,至于代码部分,我这里有新的方法,由于我的Unity客户端程序用到了框架,其他部分以后再做介绍,网络部分,服务器和客户端均解决了粘包分包问题(这里不再细说,参考我的上一篇文章),客户端采用请求发送的方式向服务器发送一个聊天的请求,服务器解析映射处理方法,将当前客户端用户名与消息合并,然后将消息广播给所有的客户端。
这里重点讲客户端,给ChatRoom这个UI身上添加ChatPanel脚本,脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
public class ChatPanel : MonoBehaviour {
public InputField chatInput;
public Text chatText;
public ScrollRect scrollRect;
public string username;
public string msg;
public string totalMsg;
//画布群组件用来控制UI的显示和消失
private CanvasGroup canvasGroup;
//判断输入框是否按下以控制输入框的显示和消失
private bool isPress = false;
private ChatRequest chatRequest;
//得到当前用户信息
private UserData ud;
private bool isUpdate = false;
// Use this for initialization
void Start()
{
chatText.text = "";
canvasGroup = GetComponent
canvasGroup.alpha = 0;
chatRequest = GetComponent
ud = GameFacade.Instance.GetUserData();
}
// Update is called once per frame
void Update()
{
chatText.text = totalMsg;
//如果输入框失去焦点,此时按下Return键 (1.显示整个UI,2.输入框的显示和消失)
if (Input.GetKeyDown(KeyCode.Return) && !chatInput.isFocused)
{
canvasGroup.alpha = 1;
isPress = !isPress;
ReturnKeyShow();
}
//如果输入框的文本不为空,此时按下Return键发送消息
if (Input.GetKeyDown(KeyCode.Return) && chatInput.text != "")
{
SendMsg();
chatInput.text = "";
Canvas.ForceUpdateCanvases(); //控制可以滑动滑杆
scrollRect.verticalNormalizedPosition = 0f; //将该值设置为0,可以控制文本框过多时,当前文本不被遮挡
Canvas.ForceUpdateCanvases(); //控制可以滑动滑杆
isPress = false;
ReturnKeyShow();
}
if (isUpdate) {
canvasGroup.alpha = 1;
Invoke("ContinueFade", 4f);
isUpdate = false;
}
}
void ContinueFade() {
if (chatInput.gameObject.activeInHierarchy == false)
{
canvasGroup.DOFade(0, 0.5f);
}
}
void SendMsg()
{
string data = chatInput.text;
if (data == "") return;
chatRequest.SendRequest(data);
//msg += str + "\n";
}
public void OnResponseMsg() {
isUpdate = true;
if (ud.Username == username) {
username = "
}
else{
username = "
}
totalMsg += username + msg + "\n";
}
//该方法用来控制输入框的显示和消失
void ReturnKeyShow()
{
if (isPress)
{
chatInput.gameObject.SetActive(true);
chatInput.ActivateInputField();
}
else
{
chatInput.gameObject.SetActive(false);
canvasGroup.alpha = 1;
Invoke("ContinueFade", 4f);
}
}
}
然后给ChatRoom这个UI身上添加ChatRequest脚本,脚本内容如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Common;
public class ChatRequest : BaseRequest {
private ChatPanel chatPanel;
private bool isUpdate = false;
private string userName;
private string msg;
public override void Awake()
{
requestCode = RequestCode.Game;
actionCode = ActionCode.Chat;
chatPanel = GetComponent
base.Awake();
}
void Update() {
if (isUpdate) {
chatPanel.username = userName;
chatPanel.msg = msg;
chatPanel.OnResponseMsg();
isUpdate = false;
}
}
public void SendRequest(string data) {
base.SendRequest(data);
}
public override void OnResponse(string data)
{
Debug.Log("收到消息:" + data);
string[] strs = data.Split('^');
isUpdate = true;
userName = strs[0];
msg = strs[1];
isUpdate = true;
}
}
ChatRequest基础了BaseRequest,调用SendRequet方法后,会将输入框中的消息封装好,最终以字节数组的方式发送给服务器,服务器将消息广播给客户端,就会通过映射解析消息,最终会调用OnResponse方法,此时得到的是一个string类型的数据,该数据已经在客户端被解析好了,这时只需要将用户名(username)和实际消息(msg)拆开,然后将其传给ChatPanel脚本中的username和msg,然后就可以实现聊天的功能了。
值得注意的是,这里的文本框、输入框的显示和消失有点绕,我是通过几个布尔值来判断的,逻辑还需要反复推敲,欢迎探讨!