当前位置:   article > 正文

Unity中对话聊天界面_unity 聊天框

unity 聊天框

对话界面

前言

AI对话界面,一左一右显示,对方输入两种状态,1.输入中… 2.显示文本内容(文本内容做了打字机效果显示),因为我们数据是不需要做缓存的,做场景切换等操作是重置的,所以就没考虑数据存储 单纯展示。需求点:文本框自适应大小 有最大宽度没有高度限制,可以滑动查看,每次展示位置都保持在最新

最终效果展示

请添加图片描述

实现部分

因为不考虑数据存储,所以没有复用Item,就用就生成一个新的,收到消息就生成一个新的Item,区分是右侧还是左侧,整个布局用的unity自带的排版组件,在确定左右侧之后修改verticalLayout.childAlignment

 public void SetMessage(bool isSelf, string content)
    {
        var item = Instantiate(chatItemPre, itemContent);
        chatItem = item;
        itemObj.Add(item);

        var verticalLayout = chatItem.GetComponent<VerticalLayoutGroup>();
        if (isSelf)
        {
            leftOrRightContent = chatItem.transform.Find("Right");
            verticalLayout.childAlignment = TextAnchor.UpperRight;
            //请求数据
            cts = new CancellationTokenSource();
            voiceComponentAI.RequestAI(content, cts);
        }
        else
        {
            leftOrRightContent = chatItem.transform.Find("Left");
            verticalLayout.childAlignment = TextAnchor.UpperLeft;
        }

        leftOrRightContent.localScale = Vector3.zero;
        leftOrRightContent.gameObject.SetActive(true);
        chatMessage = leftOrRightContent.GetComponent<VociceChatMessage>();
        chatMessage.SetMessage(content, RefreshLayout, isSelf);
        ShowPhonyItem(isSelf);
    }
     public void RefreshLayout()
    {
        StartCoroutine(RefreshContentLayout());
    }
    
    IEnumerator RefreshContentLayout()
    {
        yield return new WaitForSeconds(0.1f);
        var content = chatItem.GetComponent<RectTransform>();
        LayoutRebuilder.ForceRebuildLayoutImmediate(content);
        leftOrRightContent.localScale = Vector3.one;
    }  
    
    IEnumerator SetScrollBarValue()
    {
        yield return new WaitForSeconds(0.1f);
        scrollbar.value = 0;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

Item内容赋值,自动换行,打字机实现,也是依靠Unity自己的控件 这样自己就不用在吧啦啦啦算吧

public class VociceChatMessage : MonoBehaviour
{
    public TMP_Text textComponent;
    public RectTransform contentRectTransform;
    public float maxWidth = 340f;
    public RectTransform bgRect;
    public Action onSucceed;

    private string fullText;
    private bool isRight;
    //是不是需要计算text
    private bool isShowText = false;
    //回答的内容是否逐字显示中
    private bool isIEnumeratorIng = false;
    
    
    public void SetMessage(string message,Action callBack,bool _isRight)
    {
        DOTween.KillAll();
        fullText = message;
        onSucceed = callBack;
        isRight = _isRight;
        isShowText = false;
        isIEnumeratorIng = false;
        if (isRight)//右侧内容
        {
            isShowText = true;
            textComponent.text = message;
        }
        else
        {
            StartCoroutine(ShowText());
        }
        
        RefreshLayout();
    }

    public void RefreshLayout()
    {
        StartCoroutine(RefreshContentLayout());
    }

    IEnumerator RefreshContentLayout()
    {
        yield return new WaitForSeconds(0.1f);
        LayoutRebuilder.ForceRebuildLayoutImmediate(contentRectTransform);
        onSucceed?.Invoke();
    }
  
    IEnumerator ShowText()
    {
        isShowText = true;
        isIEnumeratorIng = true;
        for (int i = 0; i <= fullText.Length; i++)
        {
            textComponent.text = fullText.Substring(0, i);
            yield return new WaitForSeconds(0.1f);
            if (i == fullText.Length)
            {
                isShowText = false;
                isIEnumeratorIng = false;
            }
        }
    }

    public void Update()
    {
        if (isShowText)
        {
            // 计算文本宽度
            float textWidth = textComponent.preferredWidth;
        
            // 如果文本宽度超过最大宽度,自动换行
            if (textWidth > maxWidth)
            {
                // Text控件的Content Size Fitter由水平Preferred Size改为垂直Preferred Size
                textComponent.GetComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
                textComponent.GetComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
                // 调整文本框的大小以容纳所有文本
                contentRectTransform.sizeDelta = new Vector2(maxWidth, contentRectTransform.sizeDelta.y);
                if(isRight == false)
                    bgRect.sizeDelta = new Vector2(maxWidth + 20, contentRectTransform.sizeDelta.y + 20);
                // int lineCount = Mathf.CeilToInt(textWidth / maxWidth);
                // float lineHeight = textComponent.preferredHeight / textComponent.textInfo.lineCount;
                // float newHeight = lineHeight * lineCount;

            }
            else
            {
                // Text控件的Content Size Fitter由水平Preferred Size改为垂直Preferred Size
                textComponent.GetComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
                textComponent.GetComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
                if(isRight == false)
                    bgRect.sizeDelta = new Vector2(contentRectTransform.sizeDelta.x + 20, contentRectTransform.sizeDelta.y + 20);
            }
            if(isIEnumeratorIng == false)
                isShowText = false;
        }
       
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101

最后要根据打字机显示的效果Item自动扩容

  private Vector2 lastSize;

    void Start()
    {
        lastSize = itemContent.GetComponent<RectTransform>().sizeDelta;
    }

    public void Update()
    {
        Vector2 currentSize = itemContent.GetComponent<RectTransform>().sizeDelta;
        if (currentSize != lastSize)
        {
            //Debug.Log("Content size changed!");
            // 在这里可以编写处理Content大小改变时的逻辑
            StartCoroutine(SetScrollBarValue());
            lastSize = currentSize;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

因为没收到消息时候要做一个假的输入中的效果,我就简单处理了,做一个假的item,然后再没收到消息的时候放在Scrollerview下面然后显示播放DOTween动画,收到消息之后 在移除Scrollerview隐藏不显示。有好多实现方式 我这种不精细 嘿嘿嘿~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/783223
推荐阅读
相关标签
  

闽ICP备14008679号