unity制作一个可以自由滑动收缩的历史记录功能。

公司在做一款模拟经营类的卖车游戏,需要一个简单的历史记录功能,放在左上角,记录最近20条的收入/支出记录。超过2秒不动则收起。收起时展示最近的一个消息记录。
用到的组件是ScrollView,使用方法可以参考我写过的一篇博客。ScrollView踩坑记录
要求:
1、像正常的聊天框那样,消息从上向下展示,界面最多展示五条,如果用户当前看的是最底部的消息,那么有新的收入/支出消息的时候,需要将最新一条添加到底部,并将其他消息向上移动一格。如果用户正在查询历史记录,那么正常添加即可。不需要添加到底部。
2、当用户两秒内对历史记录无任何操作时,收起历史记录,并展示最新一条消息,此后如果有最新记录,展示最新的记录。

先实现最简单的功能。
1、正常的添加历史记录。
在这里插入图片描述
先看下最简单的功能,可以正常添加,但是最新一条聊天记录并不会将其他消息顶上去。
如果想顶上去,需要加上几行代码

        Canvas.ForceUpdateCanvases();
        scrollRect.verticalNormalizedPosition = 0f;
        Canvas.ForceUpdateCanvases();

这个代码是强制刷新画布(不刷新会有延迟,出现错误的效果,此处为了简略就不掩饰了),并且将滑动条的垂直变量变成0(即到达底部)。
图2
如上图所示,现在虽然沉底了,但是当用户查询历史记录的时候,此时如果新加入一条记录,就会出现用户正翻着记录,却被沉底的情况,这种情况不符合要求,需要改。
此时可以加个判断,判断verticalNormalizedPosition 的值,注意不能和0对比,滑动后的verticalNormalizedPosition 会有一定的误差,可能是0.0000000几。
我这里觉得这样判断比较麻烦,没有深入研究。使用的是另一种方法。

第二种方法:
更改自身的中心点(pivot)。
当自身pivot点在中心时,自身变大,是向四周扩大,如果在上面,则向下面扩大,如果是在下面,那么则向上面扩大。
那么解决方法就出来了,当历史记录少于五条时,我们让他正常的向下增长。
当历史记录少于五条时,中心点在上方,当中心点大于等于五条时,中心点在上方,此时后续新增的历史记录需要调用SetAsLastSibling()方法,将最新的消息置于底部。
在这里插入图片描述
效果如上图所示。此处有一个注意点,当通过代码更改物体的中心点时,物体会发生抽搐,算是unity的一个BUG把,需要手动的给物的位置赋值。
完整代码:

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

public class HistoryView : MonoBehaviour
{
    
    
    /// <summary>
    /// 历史记录
    /// </summary>
    public List<string> historyStringList = new List<string>();

    public Button getButton1;

    public Button costButton1;

    public Button getButton2;

    public Button costButton2;

    /// <summary>
    /// 子类的父物体
    /// </summary>
    public Transform parentTransform;

    /// <summary>
    /// 预制体
    /// </summary>
    public GameObject historyItemPrefab;

    /// <summary>
    /// 滑动框
    /// </summary>
    public ScrollRect scrollRect;
    private void Awake()
    {
    
    
        getButton1.onClick.AddListener(() =>
        {
    
    
            AddHistory("+100");
        });
        getButton2.onClick.AddListener(() =>
        {
    
    
            AddHistory("+200");
        });
        costButton1.onClick.AddListener(() =>
        {
    
    
            AddHistory("-100");
        });
        costButton2.onClick.AddListener(() =>
        {
    
    
            AddHistory("-200");
        });
    }

    void AddHistory(string historyString)
    {
    
    
        historyStringList.Add(historyString);
        if (historyStringList.Count < 5)
        {
    
    
            scrollRect.content.pivot = new Vector2(0, 1);
        }
        else if (historyStringList.Count == 5)
        {
    
    
            scrollRect.content.pivot = new Vector2(0, 0);
            Canvas.ForceUpdateCanvases();
            scrollRect.verticalNormalizedPosition = 0f;
            Canvas.ForceUpdateCanvases();
        }
        else
        {
    
    
            scrollRect.content.pivot = new Vector2(0, 0);
        }
        GameObject go = Instantiate(historyItemPrefab, parentTransform);
        go.transform.SetAsLastSibling();
        var historyItem = go.GetComponent<HistoryItem>();
        historyItem.contentText.text = historyString;

    }
}

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


public class HistoryItem : MonoBehaviour
{
    
    
    public Text contentText;
}

隐藏功能:将Content的锚点改为下方,这样我们只需要改动ViewReport的下面大小,Content的坐标就会跟着改动。
在这里插入图片描述
隐藏的时候将scrollRect.verticalNormalizedPosition = 0f;然后根据实际情况调整ViewPort的大小就行,这里就偷个懒不做演示了。
至于显示,可以用一个透明的button贴在最上面,检测玩家是否按下,按下则改变大小,也可以通过Unity ScrollRect提供的onValueChanged去监听,这就看个人习惯了。
ps:onValueChanged在有新物体创建的时候有时会导致value改变,有时不会,是个小bug。
Demo

猜你喜欢

转载自blog.csdn.net/qq_40629631/article/details/121927764