unity 聊天界面

unity 聊天界面

结果展示:

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

界面搭建:

1.ChattingPanel(根据名字和后缀可以知道类型,无明确类型的,为空物体)

在这里插入图片描述
在这里插入图片描述


在这里插入图片描述

2.WorldMyChatItem(根据名字和后缀可以知道类型,无明确类型的,为空物体)

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

3.WorldOtherPeopleChatItem(根据名字和后缀可以知道类型,无明确类型的,为空物体)

在这里插入图片描述


在这里插入图片描述

代码:一共三个脚本

1.ChattingPanel.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


public class ChattingPanel : MonoBehaviour
{
    public GameObject chattingPanel_Go;
    Button m_OtherChat_Btn;
    Button m_MyChat_Btn;
    Button m_Close_Btn;
    GameObject m_World_Go;
    Button m_NewMessage_Btn;
    Text m_NewMessage_Txt;
    InputField m_Msg_InputField;
    GameObject m_WorldChatPanel_Go;
    Transform m_ChatContent_Ts;

    private string valueText;
    //输入框输入最大字节
    int MaxLimit = 80;
    //发送信息倒计时
    int countTimeNum = 10;
    //显示的最大聊天数量
    int showMaxNum = 200;
    //几条新消息
    int newMessageNum = 0;
    //所有的聊天(最大长度是展示的两倍)
    List<GameObject> allChatItemList = new List<GameObject>();
    //展示的聊天
    List<GameObject> chatItemShowList = new List<GameObject>();

    // Start is called before the first frame update
    void Start()
    {
        allChatItemList.Clear();
        chatItemShowList.Clear();
        FunFind();
        OnCloseNewMessage();
        this.AddUIListener();
    }

    void FunFind()
    {
        m_OtherChat_Btn = chattingPanel_Go.transform.Find("root/TopBtns/OtherChat_Btn").GetComponent<Button>();
        m_MyChat_Btn = chattingPanel_Go.transform.Find("root/TopBtns/MyChat_Btn").GetComponent<Button>();
        m_Close_Btn = chattingPanel_Go.transform.Find("root/Close_Btn").GetComponent<Button>();
        m_World_Go = chattingPanel_Go.transform.Find("root/World_Go").gameObject;
        m_NewMessage_Btn = chattingPanel_Go.transform.Find("root/World_Go/NewMessage_Btn").GetComponent<Button>();
        m_NewMessage_Txt = chattingPanel_Go.transform.Find("root/World_Go/NewMessage_Btn/NewMessage_Txt").GetComponent<Text>();
        m_Msg_InputField = chattingPanel_Go.transform.Find("root/World_Go/Msg_InputField").GetComponent<InputField>();
        m_WorldChatPanel_Go = chattingPanel_Go.transform.Find("root/World_Go/WorldChatPanel_Go").gameObject;
        m_ChatContent_Ts = chattingPanel_Go.transform.Find("root/World_Go/WorldChatPanel_Go/Viewport/ChatContent_Ts").GetComponent<Transform>();
    }

    void AddUIListener()
    {
        m_Close_Btn.onClick.AddListener(OnClose);
        m_OtherChat_Btn.onClick.AddListener(OnOtherInfo);
        m_MyChat_Btn.onClick.AddListener(OnSendMessage);
        m_NewMessage_Btn.onClick.AddListener(OnClickNewMessage);
        //用户输入文本时就会调用
        m_Msg_InputField.onValueChanged.AddListener(ChangedValue);

        m_WorldChatPanel_Go.GetComponent<ScrollRect>().onValueChanged.AddListener(FunScrollRectChangeValue);
    }

    private void OnClose()
    {
        chattingPanel_Go.SetActive(false);
    }
    //发送消息
    private void OnSendMessage()
    {
        if (string.IsNullOrEmpty(m_Msg_InputField.text))
        {
            Debug.Log("输入不可为空");
            return;
        }

        GameObject chatItem = null;
        if (chatItemShowList.Count <= showMaxNum)
        {
            chatItem = (GameObject)Instantiate(Resources.Load("WorldMyChatItem"));
        }
        else
        {
            bool isHave = false;
            for (int i = 0; i < allChatItemList.Count - showMaxNum; i++)
            {
                allChatItemList[i].SetActive(false);
            }
            for (int i = 0; i < allChatItemList.Count - showMaxNum; i++)
            {
                if (allChatItemList[i].name == "WorldMyChatItem")
                {
                    chatItem = allChatItemList[i];
                    allChatItemList.RemoveAt(i);
                    isHave = true;
                    break;
                }
            }

            if (!isHave)
            {
                chatItem = (GameObject)Instantiate(Resources.Load("WorldMyChatItem"));
            }
            chatItemShowList.RemoveAt(0);
            chatItem.SetActive(false);
        }
        WorldMyChatItem myChatItem = chatItem.transform.GetComponent<WorldMyChatItem>();

        myChatItem.Init(m_Msg_InputField.text);
        chatItem.name = "WorldMyChatItem";
        chatItem.transform.SetParent(m_ChatContent_Ts);
        chatItem.transform.localScale = Vector3.one;
        chatItem.transform.localPosition = Vector3.zero;
        chatItem.transform.SetAsLastSibling();
        chatItem.SetActive(true);
        this.chatItemShowList.Add(chatItem);
        this.allChatItemList.Add(chatItem);

        m_Msg_InputField.text = "";
        OnClickNewMessage();
    }
    //其他人消息
    private void OnOtherInfo()
    {
        if (string.IsNullOrEmpty(m_Msg_InputField.text))
        {
            Debug.Log("输入不可为空");
            return;
        }

        GameObject chatItem = null;
        if (chatItemShowList.Count <= showMaxNum)
        {
            chatItem = (GameObject)Instantiate(Resources.Load("WorldOtherPeopleChatItem"));
        }
        else
        {
            bool isHave = false;
            for (int i = 0; i < allChatItemList.Count - showMaxNum; i++)
            {
                allChatItemList[i].SetActive(false);
            }
            for (int i = 0; i < allChatItemList.Count - showMaxNum; i++)
            {
                if (allChatItemList[i].name == "WorldOtherPeopleChatItem")
                {
                    chatItem = allChatItemList[i];
                    allChatItemList.RemoveAt(i);
                    isHave = true;
                    break;
                }
            }

            if (!isHave)
            {
                chatItem = (GameObject)Instantiate(Resources.Load("WorldOtherPeopleChatItem"));
            }
            chatItemShowList.RemoveAt(0);
            chatItem.SetActive(false);
        }
        WorldOtherPeopleChatItem myChatItem = chatItem.transform.GetComponent<WorldOtherPeopleChatItem>();

        myChatItem.Init(m_Msg_InputField.text);
        chatItem.name = "WorldOtherPeopleChatItem";
        chatItem.transform.SetParent(m_ChatContent_Ts);
        chatItem.transform.localScale = Vector3.one;
        chatItem.transform.localPosition = Vector3.zero;
        chatItem.transform.SetAsLastSibling();
        chatItem.SetActive(true);
        this.chatItemShowList.Add(chatItem);
        this.allChatItemList.Add(chatItem);
        m_Msg_InputField.text = "";

        if (m_WorldChatPanel_Go.GetComponent<ScrollRect>().verticalNormalizedPosition <= 2f / this.chatItemShowList.Count)
        {
            StartCoroutine(SetScrollView());
        }
        else
        {
            newMessageNum++;
            if (newMessageNum >= 99)
            {
                newMessageNum = 99;
            }
            m_NewMessage_Btn.gameObject.SetActive(true);
            m_NewMessage_Txt.text = newMessageNum + "条新消息";
        }
    }
    IEnumerator SetScrollView()
    {
        yield return null;
        m_WorldChatPanel_Go.GetComponent<ScrollRect>().verticalNormalizedPosition = 0;
    }
    //点击新消息提示
    private void OnClickNewMessage()
    {
        StartCoroutine(SetScrollView());
        OnCloseNewMessage();
    }
    //关闭新消息提示
    void OnCloseNewMessage()
    {
        newMessageNum = 0;
        m_NewMessage_Btn.gameObject.SetActive(false);
    }

    //用户输入时的变化
    private void ChangedValue(string value)
    {
        if (System.Text.Encoding.UTF8.GetBytes(value).Length > MaxLimit)
        {
            m_Msg_InputField.text = valueText;
            return;
        }
        valueText = value;//将用户输入的值赋值给内部的空字符串,我们可以将其来进行后续的操作
        m_Msg_InputField.text = value;
    }
    //ScrollRect滚动监听,判断是否移动到了下面
    void FunScrollRectChangeValue(Vector2  vector2)
    {
        if (m_WorldChatPanel_Go.GetComponent<ScrollRect>().verticalNormalizedPosition <= 2f / this.chatItemShowList.Count)
        {
            m_NewMessage_Btn.gameObject.SetActive(false);
        }
    }
}

2.WorldMyChatItem.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class WorldMyChatItem : MonoBehaviour
{
    public Text m_PlayerName_Txt;
    public Image m_HeadIcon_Img;
    public Image m_HeadIconEdge_Img;
    public Image m_DialogBg_Img;
    public Text m_Msg_Txt;

    public TextGenerator textGenerator;
    TextGenerationSettings settings;

    float width;//气泡的宽度
    bool isShow = false;
    // Start is called before the first frame update
    void Awake()
    {
        m_PlayerName_Txt = this.gameObject.transform.Find("PlayerName_Txt").GetComponent<Text>();
        m_HeadIcon_Img = this.gameObject.transform.Find("HeadIcon_Img").GetComponent<Image>();
        m_HeadIconEdge_Img = this.gameObject.transform.Find("HeadIconEdge_Img").GetComponent<Image>();
        m_DialogBg_Img = this.gameObject.transform.Find("DialogBg_Img").GetComponent<Image>();
        m_Msg_Txt = this.gameObject.transform.Find("DialogBg_Img/Msg_Txt").GetComponent<Text>();
    }

    public void Init(string str)
    {
        gameObject.SetActive(true);
        m_Msg_Txt.text = str;
        width = m_DialogBg_Img.GetComponent<RectTransform>().rect.width;
        textGenerator = m_Msg_Txt.cachedTextGeneratorForLayout;

        //显示省略号,与OnText()二选一
        //SetTextWithEllipsis();
        OnText();
    }

    void OnText()
    {
        settings = m_Msg_Txt.GetGenerationSettings(Vector2.zero);
        Canvas.ForceUpdateCanvases();
        //获取显示文本的长和宽
        float textHeight = m_Msg_Txt.GetComponent<RectTransform>().rect.height;
        float textWidth = textGenerator.GetPreferredWidth(m_Msg_Txt.text, settings) / m_Msg_Txt.pixelsPerUnit;
        //修改聊天背景框的大小
        if (textWidth <= width)
        {
            m_DialogBg_Img.GetComponent<RectTransform>().sizeDelta = new Vector2(textWidth + 70, textHeight + 30);
            m_DialogBg_Img.GetComponent<RectTransform>().anchoredPosition = new Vector2((textWidth / 2 * -1) - 210, -60);
        }
        else
        {
            m_DialogBg_Img.GetComponent<RectTransform>().sizeDelta = new Vector2(width + 70, textHeight + 30);
            m_DialogBg_Img.GetComponent<RectTransform>().anchoredPosition = new Vector2((width / 2 * -1) - 210, -60);
        }
        isShow = true;
    }
    void LateUpdate()
    {
        if (isShow)
        {
            //修改item的大小,排列使用
            //放在LateUpdate,延迟渲染
            gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(gameObject.GetComponent<RectTransform>().rect.width, m_Msg_Txt.GetComponent<RectTransform>().rect.height + 100);
            isShow = false;
        }
    }
    /// <summary>
    /// 文本超出部分省略号
    /// </summary>
    /// <param name="textTemp">目标文本框</param>
    /// <param name="value">文本</param>
    private void SetTextWithEllipsis(Text textTemp, string value)
    {
        var generator = new TextGenerator();
        var rectTransform = textTemp.GetComponent<RectTransform>();
        //设置文本绘制范围
        Vector2 vector2 = new Vector2(m_Msg_Txt.GetComponent<RectTransform>().rect.width, 100);
        var settings = textTemp.GetGenerationSettings(vector2);
        generator.Populate(value, settings);

        //设置可见的字符数
        var characterVisibleCount = generator.characterCountVisible;
        var updateText = value;

        //超出部分以省略号显示
        if (value.Length > characterVisibleCount)
        {
            updateText = value.Substring(0, characterVisibleCount - 1);
            updateText += "...";
        }

        textTemp.text = updateText;
    }

}


3.WorldOtherPeopleChatItem.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class WorldOtherPeopleChatItem : MonoBehaviour
{
    public Text m_PlayerName_Txt;
    public Image m_HeadIcon_Img;
    public Image m_HeadIconEdge_Img;
    public Button m_HeadIcon_Btn;
    public Image m_DialogBg_Img;
    public Text m_Msg_Txt;

    public TextGenerator textGenerator;
    TextGenerationSettings settings;
    object m_Info;
    float width;//气泡的宽度
    bool isShow = false;
    // Start is called before the first frame update
    void Awake()
    {
        m_PlayerName_Txt = this.gameObject.transform.Find("PlayerName_Txt").GetComponent<Text>();
        m_HeadIcon_Img = this.gameObject.transform.Find("HeadIcon_Img").GetComponent<Image>();
        m_HeadIconEdge_Img = this.gameObject.transform.Find("HeadIconEdge_Img").GetComponent<Image>();
        m_HeadIcon_Btn = this.gameObject.transform.Find("HeadIcon_Btn").GetComponent<Button>();
        m_DialogBg_Img = this.gameObject.transform.Find("DialogBg_Img").GetComponent<Image>();
        m_Msg_Txt = this.gameObject.transform.Find("DialogBg_Img/Msg_Txt").GetComponent<Text>();
    }
    public void Init(string str)
    {
        gameObject.SetActive(true);
        m_Msg_Txt.text = str;
        width = m_DialogBg_Img.GetComponent<RectTransform>().rect.width;
        textGenerator = m_Msg_Txt.cachedTextGeneratorForLayout;
        OnText();
    }
    void OnText()
    {
        settings = m_Msg_Txt.GetGenerationSettings(Vector2.zero);
        Canvas.ForceUpdateCanvases();

        float textHeight = m_Msg_Txt.GetComponent<RectTransform>().rect.height;
        float textWidth = textGenerator.GetPreferredWidth(m_Msg_Txt.text, settings) / m_Msg_Txt.pixelsPerUnit;
        if (textWidth <= width)
        {
            m_DialogBg_Img.GetComponent<RectTransform>().sizeDelta = new Vector2(textWidth + 80, textHeight + 30);
            m_DialogBg_Img.GetComponent<RectTransform>().anchoredPosition = new Vector2((textWidth / 2) + 200, -60);
        }
        else
        {
            m_DialogBg_Img.GetComponent<RectTransform>().sizeDelta = new Vector2(width + 80, textHeight + 30);
            m_DialogBg_Img.GetComponent<RectTransform>().anchoredPosition = new Vector2((width / 2) + 200, -60);
        }
        isShow = true;
    }
    public void LateUpdate()
    {
        if (isShow)
        {
            gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(gameObject.GetComponent<RectTransform>().rect.width, m_Msg_Txt.GetComponent<RectTransform>().rect.height + 100);
            isShow = false;
        }
    }
}

提示:如果这还不懂,就去下载项目看看吧