Unity 通用UI界面逻辑总结

news2025/3/10 5:45:03

概述

在游戏开发中,常常会遇到一些通用的界面逻辑,它不论在什么类型的游戏中都会出现。为了避免重复造轮子,本文总结并提供了一些常用UI界面的实现逻辑。希望可以帮助大家快速开发通用界面模块,也可以在次基础上进行扩展修改,以适应你项目的需求。

工程链接:GitCode - 全球开发者的开源社区,开源代码托管平台

二次确认界面

using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public class ConfirmDialog : MonoBehaviour
{
    private Text txt_title;
    private Text txt_content;
    private Button btn_Yes;
    private Button btn_No;

    void Start()
    {
        var root = gameObject.transform;
        txt_title = root.Find("txt_Title").GetComponent<Text>();
        txt_content = root.Find("txt_Content").GetComponent<Text>();
        btn_Yes = root.Find("btn/btn_Yes").GetComponent<Button>();
        btn_No = root.Find("btn/btn_No").GetComponent<Button>();
        txt_title.text = "提示";
        
        //测试代码
        InitDialog("好好学习,天天向上!", 
            () => {Debug.Log("Yes"); },
            () => {Debug.Log("No"); });
    }

    /// <summary>
    /// 重载一:使用默认标题 “提示”
    /// </summary>
    /// <param name="content">需要确认的内容</param>
    /// <param name="yesAction">确认按钮回调</param>
    /// <param name="noAction">取消按钮回调</param>
    public void InitDialog(string content, UnityAction yesAction = null, UnityAction noAction = null)
    {
        txt_title.text = "提示";
        CoreLogic(content, yesAction, noAction);
    }

    /// <summary>
    /// 重载一:使用自定义标题
    /// </summary>
    /// <param name="title">自定义标题</param>
    /// <param name="content">需要确认的内容</param>
    /// <param name="yesAction">确认按钮回调</param>
    /// <param name="noAction">取消按钮回调</param>
    public void InitDialog(string title, string content, UnityAction yesAction = null, UnityAction noAction = null)
    {
        txt_title.text = title;
        CoreLogic(content, yesAction, noAction);
    }

    //公共逻辑提取
    private void CoreLogic(string content, UnityAction yesAction = null, UnityAction noAction = null)
    {
        txt_content.text = content;
        BindBtnLogic(btn_Yes, yesAction);
        BindBtnLogic(btn_No, noAction);
        btn_Yes.gameObject.SetActive(yesAction != null);
        btn_No.gameObject.SetActive(noAction != null);
    }

    //绑定按钮点击回调
    private void BindBtnLogic(Button btn, UnityAction action)
    {
        btn.onClick.RemoveAllListeners();
        if (action != null)
        {
            btn.onClick.AddListener(action);
        }
    }
}

切页标签

通过按钮来实现。虽然使用Toggle也可以实现,但是在实际开发中会发现使用toggle不好控制选中事件的触发和选中状态表现。通过按钮来自定义组件可以更好地控制逻辑的调用和标签的显示。

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

class TabNode
{ 
    public int index;
    public GameObject offBg;
    public GameObject onBg;
    public Text offTxt;
    public Text onTxt;
    public Button btn;
    public UnityAction callback;
}

public class SwitchPageTab : MonoBehaviour
{
    public Transform tabRoot;//标签组的父节点
    public GameObject tabObj;//标签页预制体模板
    private int _selectIndex;//选中的标签页索引

    private List<TabNode> _objList = new List<TabNode>();
    private Dictionary<int, UnityAction> _callbackDic = new Dictionary<int, UnityAction>();
    
    private void Start()
    {
        _selectIndex = -1;
        
        InitCount(4);
        BindSelectCallback(0, "背包", (() =>
        {
            Debug.Log("查看背包");
        }));
        BindSelectCallback(1, "英雄", (() =>
        {
            Debug.Log("查看英雄");
        }));
        BindSelectCallback(2, "商店", (() =>
        {
            Debug.Log("查看商店");
        }));
        BindSelectCallback(3, "活动", (() =>
        {
            Debug.Log("查看活动");
        }));
        
        
        OnSelectLogic(0);
    }

    /// <summary>
    /// 初始化调用
    /// </summary>
    /// <param name="count">标签的数量</param>
    public void InitCount(int count)
    {
        _objList.Clear();
        ClearAllChild(tabRoot);
        for (var i = 0; i < count; i++)
        {
            var obj = Instantiate(tabObj, tabRoot);
            obj.SetActive(true);
            var trans = obj.transform;
            var node = new TabNode
            {
                offTxt = trans.Find("btn/offBg/offTxt").GetComponent<Text>(),
                onTxt = trans.Find("btn/onBg/onTxt").GetComponent<Text>(),
                onBg = trans.Find("btn/onBg").gameObject,
                offBg = trans.Find("btn/offBg").gameObject,
                btn = trans.Find("btn").GetComponent<Button>(),
            };
            var index = i;
            BindBtnLogic(node.btn, () =>
            {
                OnSelectLogic(index);
            });
            _objList.Add(node);
        }
    }
    
    /// <summary>
    /// 绑定指定页签索引的回调函数
    /// </summary>
    /// <param name="index">页签索引</param>
    /// <param name="txt">页签问本</param>
    /// <param name="callback">选中回调</param>
    public void BindSelectCallback(int index,string txt,UnityAction callback)
    {
        if (_callbackDic.ContainsKey(index))
        {
            Debug.LogError("已经注册过了!");
            return;
        }

        if (callback == null)
        {
            Debug.LogError("回调为空!");
            return;
        }

        if (index < 0 || index > _objList.Count)
        {
            Debug.LogError("索引越界!");
            return;
        }

        var node = _objList[index];
        node.onTxt.text = txt;
        node.offTxt.text = txt;
        _callbackDic.Add(index,callback);
    }
    
    /// <summary>
    /// 调用指定索引对应的回调函数
    /// </summary>
    /// <param name="index"></param>
    private void OnSelectLogic(int index)
    {
        if (index == _selectIndex)
        {
            return;
        }
        _selectIndex = index;
        
        var isExist = _callbackDic.TryGetValue(_selectIndex, out UnityAction callback);
        if (isExist)
        {
            callback?.Invoke();
            SetSelectStatus(index);
        }
    }
    
    /// <summary>
    /// 控制指定页签的UI表现
    /// </summary>
    /// <param name="index"></param>
    private void SetSelectStatus(int index)
    {
        var count = _objList.Count;
        for (var i = 0; i < count; i++)
        {
            var isActive = index == i;
            var node = _objList[i];
            node.onBg.SetActive(isActive);
            node.offBg.SetActive(!isActive);
        }
    }
    
    //清除指定父节点下的所有子物体
    private void ClearAllChild(Transform parentRoot)
    {
        var childCount = parentRoot.childCount;
        for (var i = childCount - 1; i >= 0; i--)
        {
            var child = parentRoot.GetChild(i);
            DestroyImmediate(child.gameObject);
        }
    }

    //绑定按钮点击回调
    private void BindBtnLogic(Button btn, UnityAction action)
    {
        btn.onClick.RemoveAllListeners();
        if (action != null)
        {
            btn.onClick.AddListener(action);
        }
    }
}

飘字提示

简易版本

using UnityEngine;
using UnityEngine.Pool;
using DG.Tweening;
using UnityEngine.UI;

public class SimpleTip : MonoBehaviour
{
    //提示栏预制体
    public GameObject tipObj;
    //提示栏显示的父节点
    public Transform tipRoot;
    //对象池
    private ObjectPool<GameObject> tipPool;
    //飞行高度
    private float flyHeight = 500;
    
    void Start()
    {
        InitTipPool();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            ShowTip("货币不足!");
        }
    }

    void ShowTip(string tipStr)
    {
        var obj = tipPool.Get();
        var rectValue = obj.GetComponent<RectTransform>();
        var group = obj.GetComponent<CanvasGroup>();
        var txt = obj.transform.Find("txt").GetComponent<Text>();
        txt.text = tipStr;
        obj.SetActive(true);
        group.alpha = 1;
        ResetLocal(obj.transform);
        rectValue.DOAnchorPosY(flyHeight, 1f).OnComplete(() =>
        {
            group.DOFade(0, 0.1f).OnComplete(() =>
            {
                tipPool.Release(obj);
            });
        });
    }
    
    //初始化对象池
    void InitTipPool()
    {
        tipPool = new ObjectPool<GameObject>(() =>
        {
            //创建新对象调用
            var obj = Instantiate(tipObj, tipRoot);
            obj.SetActive(false);
            return obj;
        },
        (go) =>
        {
            //获取对象调用
            go.SetActive(true);
            ResetLocal(go.transform);
        },
        (go) =>
        {
            // 在对象放回池子时调用
            go.SetActive(false);
            ResetLocal(go.transform);
            go.transform.SetParent(tipRoot);
        },
        (go) =>
        {
            Destroy(go); 
        });
    }
    
    //重置本地信息
    void ResetLocal(Transform trans)
    {
        trans.localPosition = Vector3.zero;
        trans.localEulerAngles = Vector3.zero;
        trans.localScale = Vector3.one;
    }
}

升级版本

using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Pool;

public class GoodTip : MonoBehaviour
{
    //提示栏显示的父节点
    public Transform root;
    //提示栏模板预制体
    public GameObject tipObj;
    //对象池节点
    public Transform objectPool;
    
    //最多显示的提示栏数量,超过就隐藏
    private int limitCount = 5;
    //提示栏之间的偏移
    private float offset = 20;
    //提示飞行高度
    private float flyHeight = 100;
    //提示栏生成数量,只用于逻辑运算
    private int tipCount = 0;
    //提示栏高度
    private float tipHeight;
    private Queue<GameObject> visualTipQueue = new Queue<GameObject>();
    //是否可继续生成提示栏,防止频繁点击造成异常
    private bool isOk = true;
    private float timer = 0f;
    private bool startTimer = false;
    private float displayTime = 0.65f;//提示停留展示时间
    private ObjectPool<GameObject> tipPool;
    
    void Start()
    {
        var rect = tipObj.GetComponent<RectTransform>();
        tipHeight = rect.rect.height;
        
        InitTipPool();
    }

    private void Update()
    {
        if (startTimer)
        {
            //定时统一清理提示消息
            timer += Time.deltaTime;
            if (timer > displayTime)
            {
                ClearAllMsg();
                timer = 0f;
                startTimer = false;
            }
        }

        if (Input.GetKeyDown(KeyCode.Space))
        {
            ShowTip("货币不足!");
        }
    }
    
    public void ShowTip(string tip)
    {
        if (!isOk)
        {
            return;
        }
        startTimer = false;
        isOk = false;
        var obj = tipPool.Get();
        var rect1 = obj.GetComponent<RectTransform>();
        var group = obj.GetComponent<CanvasGroup>();
        
        var sequence = DOTween.Sequence();
        if (visualTipQueue.Count > 0)
        {
            sequence.AppendCallback(() =>
            {
                foreach (var item in visualTipQueue)
                {
                    var rectValue = item.GetComponent<RectTransform>();
                    rectValue.DOAnchorPosY(rectValue.anchoredPosition.y+tipHeight+offset, 0.2f);
                }
            });
            sequence.AppendInterval(0.2f);
        }
        sequence.AppendCallback(() =>
        {
            group.alpha = 1;
            obj.transform.SetParent(root);
            obj.transform.localScale = new Vector3(0, 0, 1);
            obj.SetActive(true);
            rect1.anchoredPosition = Vector2.zero;
            visualTipQueue.Enqueue(obj);
            
            tipCount++;
            var txt  = obj.transform.Find("txt").GetComponent<Text>();
            txt.text = tip;
            
            if (tipCount > limitCount)
            {
                var result = visualTipQueue.Dequeue();
                tipPool.Release(result);
                tipCount--;
            }
        });
        sequence.Append(obj.transform.DOScale(Vector3.one, 0.1f));
        sequence.AppendInterval(0.1f);
        sequence.OnComplete(() =>
        {
            timer = 0f;
            isOk = true;
            startTimer = true;
        });
    }
    
    //初始化对象池
    void InitTipPool()
    {
        tipPool = new ObjectPool<GameObject>(() =>
        {
            //创建新对象调用
            var obj = Instantiate(tipObj, objectPool);
            obj.SetActive(false);
            return obj;
        },
        (go) =>
        {
            //获取对象调用
            go.SetActive(true);
            ResetLocal(go.transform);
        },
        (go) =>
        {
            // 在对象放回池子时调用
            go.SetActive(false);
            ResetLocal(go.transform);
            go.transform.SetParent(objectPool);
        },
        (go) =>
        {
            Destroy(go); 
        });
    }
    
    //重置本地信息
    void ResetLocal(Transform trans)
    {
        trans.localPosition = Vector3.zero;
        trans.localEulerAngles = Vector3.zero;
        trans.localScale = Vector3.one;
    }
    
    //清空消息
    public void ClearAllMsg()
    {
        var childCount = root.childCount;
        for (var i = 0; i < childCount; i++)
        {
            var child = root.GetChild(i);
            var group = child.GetComponent<CanvasGroup>();
            var rectValue = child.GetComponent<RectTransform>();
            var sequence = DOTween.Sequence();
            sequence.AppendInterval(0.1f * i);
            sequence.Append(rectValue.DOAnchorPosY(rectValue.anchoredPosition.y + tipHeight+flyHeight, 0.2f));
            sequence.Append(group.DOFade(0, 0.1f).OnComplete(() =>
            {
                visualTipQueue.Dequeue();
                tipPool.Release(child.gameObject);
                tipCount--;
            }));
        }
    }
}

                                                                                      

左右切换按钮组

本组件一般出现在查看英雄界面,点击左右两个按钮切换查看按钮的详细信息。在英雄列表中,第一个英雄的左按钮不显示,最后一个英雄的右按钮不显示。

using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public class SwitchCheck : MonoBehaviour
{
    public Button btn_Left;
    public Button btn_Right;
    public Text txt_Check;

    private int sumCount;
    private int curIndex;
    private UnityAction<int> callback;//外部逻辑回调
    
    void Start()
    {
        curIndex = 0;
        InitGroup(10, (index) =>
        {
            txt_Check.text = $"{index}/{sumCount}";
        });
        CheckBtnActive();
        BindBtnLogic(btn_Left, () =>
        {
            var nextIndex = curIndex - 1;
            if (nextIndex < 0)
            {
                return;
            }
            curIndex = nextIndex;
            CheckBtnActive();
        });
        
        BindBtnLogic(btn_Right, () =>
        {
            var nextIndex = curIndex + 1;
            if (nextIndex >= sumCount)
            {
                return;
            }
            curIndex = nextIndex;
            CheckBtnActive();
        });
    }
    
    public void InitGroup(int _sumCount,UnityAction<int> _callback)
    {
        sumCount = _sumCount;
        callback = _callback;
    }
    
    //按钮显隐逻辑
    private void CheckBtnActive()
    {
        if (sumCount <= 1)
        {
            btn_Left.gameObject.SetActive(false);
            btn_Right.gameObject.SetActive(false);
        }
        else
        {
            btn_Left.gameObject.SetActive(curIndex >= 1);
            btn_Right.gameObject.SetActive(curIndex <= sumCount-2);
        }

        var showIndex = curIndex + 1;
        callback?.Invoke(showIndex);
    }
    
    //绑定按钮点击回调
    private void BindBtnLogic(Button btn, UnityAction action)
    {
        btn.onClick.RemoveAllListeners();
        if (action != null)
        {
            btn.onClick.AddListener(action);
        }
    }
}

帮助说明界面

using System.Text;
using UnityEngine;
using UnityEngine.UI;

public class ComDesc : MonoBehaviour
{
    public Text txt_Title;
    public Text txt_Desc;
    public RectTransform content;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            SetDesc("帮助", "好好学习,天天向上");
        }
            
        if (Input.GetKeyDown(KeyCode.A))
        {
            var str = "好好学习,天天向上";
            StringBuilder sb = new StringBuilder();
            for (var i = 1; i < 100; i++)
            {
                sb.Append(str);
            }
            SetDesc("帮助", sb.ToString());
        }
    }

    /// <summary>
    /// 设置说明描述
    /// </summary>
    /// <param name="title">界面标题</param>
    /// <param name="desc">说明文本</param>
    public void SetDesc(string title,string desc)
    {
        txt_Title.text = title;
        txt_Desc.text = desc;
        LayoutRebuilder.ForceRebuildLayoutImmediate(content);
    }
}

跑马灯消息提示

有消息队列缓存,等待队列中所有消息播放完后,提示才消失。

using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
using TMPro;
using UnityEngine.Events;
using UnityEngine.UI;

public class Marquee : MonoBehaviour
{
    public TMP_Text tmpTxt;
    public RectTransform maskNode;
    public CanvasGroup canvasGroup;
    private float maskWidth;
    private float unitTime = 0.2f;//计算动画时间自定义标准
    private Queue<MsgNode> marqueeMsg = new Queue<MsgNode>();
    private List<int> idList = new List<int>();
    private bool isPlay;//是否正在播放消息
    
    private class MsgNode
    {
        public int id;
        public string msg;
        public int loopCount;
    }
    
    void Start()
    {
        maskWidth = maskNode.rect.width;
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            var id = Random.Range(1,100);
            var str = $"id:{id}好好学习,天天向上>>";
            AddMarqueeMsg(id,str,1);
        }
        
        if(marqueeMsg.Count > 0) {
            if (!isPlay)
            {
                isPlay = true;
                tmpTxt.rectTransform.anchoredPosition = Vector2.zero;
                var data = marqueeMsg.Peek();
                idList.Remove(data.id);
                DisplayMarqueeMsg(data.msg,data.loopCount, () =>
                {
                    marqueeMsg.Dequeue();
                    if (marqueeMsg.Count == 0)
                    {
                        canvasGroup.alpha = 0;
                    }
                    isPlay = false;
                });
            }
        }
    }

    /// <summary>
    /// 在跑马灯消息队列中添加消息
    /// </summary>
    /// <param name="msgId">消息记录的唯一id</param>
    /// <param name="msg">消息内容</param>
    /// <param name="loopCount">循环播放时间</param>
    public void AddMarqueeMsg(int msgId, string msg, int loopCount)
    {
        if (idList.Contains(msgId))
        {
            Debug.LogError("消息已在预播队列");
            return;
        }
        
        if (canvasGroup.alpha < 0.95f)
        {
            canvasGroup.alpha = 1;
        }
        
        idList.Add(msgId);
        marqueeMsg.Enqueue(new MsgNode
        {
            id = msgId,
            msg = msg,
            loopCount = loopCount
        });
    }
    
    /// <summary>
    /// 跑马灯消息播放
    /// </summary>
    /// <param name="msgId">消息记录的唯一id</param>
    /// <param name="msg">消息内容</param>
    /// <param name="loopCount">循环播放时间</param>
    public void DisplayMarqueeMsg(string msg,int loopCount,UnityAction callback)
    {
        tmpTxt.text = msg;
        LayoutRebuilder.ForceRebuildLayoutImmediate(tmpTxt.rectTransform);
        var width = tmpTxt.rectTransform.rect.width+maskWidth;
        var duration = GetDuration(width);
        tmpTxt.rectTransform.DOAnchorPosX(-width, duration)
            .SetEase(Ease.Linear)
            .SetLoops(loopCount, LoopType.Restart)
            .OnComplete(() =>
            {
                callback?.Invoke();
            });
    }

    //根据消息长度计算动画匀速运行时间
    private float GetDuration(float width)
    {
        var offset1 = (int)width / 100;
        var offset2 = width % 100 == 0 ?0:1;
        var offset = offset1 + offset2;
        return offset * unitTime;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2312511.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Navigation的进阶知识与拦截器配置

Navigation的进阶知识与拦截器配置 写的不是很详细&#xff0c;后续有时间会补充&#xff0c;建议参考官方文档食用 1.如何配置路由信息 1.1 创建工程结构 src/main/ets ├── pages │ └── navigation │ ├── views │ │ ├── Mine.ets //…

Java数据结构第二十一期:解构排序算法的艺术与科学(三)

专栏&#xff1a;Java数据结构秘籍 个人主页&#xff1a;手握风云 目录 一、常见排序算法的实现 1.1. 归并排序 二、排序算法复杂度及稳定性分析 一、常见排序算法的实现 1.1. 归并排序 归并排序是建⽴在归并操作上的⼀种有效的排序算法,该算法是采⽤分治法的一个⾮常典型的…

go切片定义和初始化

1.简介 切片是数组的一个引用&#xff0c;因此切片是引用类型&#xff0c;在进行传递时&#xff0c;遵守引用传递的机制。切片的使用和数组类似&#xff0c;遍历切片、访问切片的元素和切片的长度都一样。。切片的长度是可以变化的&#xff0c;因此切片是一个可以动态变化的数…

【NLP 39、激活函数 ⑤ Swish激活函数】

我的孤独原本是座荒岛&#xff0c;直到你称成潮汐&#xff0c;原来爱是让个体失序的永恒运动 ——25.2.25 Swish激活函数是一种近年来在深度学习中广泛应用的激活函数&#xff0c;由Google Brain团队在2017年提出。其核心设计结合了Sigmoid门控机制和线性输入的乘积&#xff0c…

南开提出1Prompt1Story,无需训练,可通过单个连接提示实现一致的文本到图像生成。

&#xff08;1Prompt1Story&#xff09;是一种无训练的文本到图像生成方法&#xff0c;通过整合多个提示为一个长句子&#xff0c;并结合奇异值重加权&#xff08;SVR&#xff09;和身份保持交叉注意力&#xff08;IPCA&#xff09;技术&#xff0c;解决了生成图像中身份不一致…

STM32驱动OLED屏幕全解析:从原理到温度显示实战(上) | 零基础入门STM32第五十三步

主题内容教学目的/扩展视频OLED显示屏重点课程电路原理&#xff0c;手册分析&#xff0c;驱动程序。初始化&#xff0c;清屏&#xff0c;ASCII字库&#xff0c;显示分区。调用显示函数。做带有加入图形和汉字显示的RTC时钟界面。讲字库的设计原理。 师从洋桃电子&#xff0c;杜…

MySQL语法总结

本篇博客说明&#xff1a; &#xff01;&#xff01;&#xff01;.注意此系列都用的是MySQL语句&#xff0c;和SQLServer&#xff0c;PostgreSQL有些细节上的差别&#xff01;&#xff01;&#xff01; 1.每个操作都是先展示出语法格式 2.然后是具体例子 3.本篇注脚与文本顺讯息…

从预测到控制:电力RK3568边缘计算机在电网调度中的全面应用

在智能电网的快速发展中&#xff0c;电力Ubuntu工控机&#xff08;简称“电力工控机”&#xff09;作为核心设备&#xff0c;扮演着不可或缺的角色。特别是在智能电网调度场景中&#xff0c;电力工控机的高效、稳定和智能化特性&#xff0c;为电网的稳定运行和高效管理提供了强…

day-106 统计放置房子的方式数

思路 动态规划&#xff1a;因为中间有街道隔开&#xff0c;所以只需计算一边街道的排列方式&#xff0c;最后计算平方即可 解题过程 动态转换方程&#xff1a;f[i]f[i-1]f[i-2] Code class Solution {int num 1000000007;public int countHousePlacements(int n) {int arr[…

PostgreSQL安装和mcp PostgreSQL

文章目录 一. 安装之后修改权限并登录1. 确保当前用户具有sudo权限2. 修改/etc/postgresql/<版本号>/main/pg_hba.conf配置文件为trust&#xff0c;可以免密登录3. 进行免密登录4. 添加root用户和修改postgres用户密码1. postgres用户密码2. 添加root用户3. 为root用户设…

LPZero: Language Model Zero-cost Proxy Search from Zero(未更新完预览版本)

LPZero代码 摘要 神经架构搜索 (NAS) 有助于自动执行有效的神经网络搜索&#xff0c;同时需要大量的计算资源&#xff0c;尤其是对于语言模型。零样本 NAS 利用零成本 (ZC) 代理来估计模型性能&#xff0c;从而显着降低计算需求。然而&#xff0c;现有的 ZC 代理严重依赖于深…

字典树运用

字典树运用 字典树LC208 创建字典树0-1字典树 字典树 字典树又叫 前缀树&#xff0c; 是一种树形数据结构&#xff0c;用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景&#xff0c;例如自动补全和拼写检查。 LC208 创建字典树 这是一个字符串字典树…

RReadWriteLock读写锁应用场景

背景 操作涉及一批数据&#xff0c;如订单&#xff0c;可能存在多个场景下操作&#xff0c;先使用读锁&#xff0c;从redis缓存中获取操作中数据 比如 关闭账单&#xff0c; 发起调账&#xff0c; 线下结算&#xff0c; 合并支付 先判断当前操作的数据&#xff0c;是否在…

0087.springboot325基于Java的企业OA管理系统的设计与实现+论文

一、系统说明 基于springbootvue的企业OA管理系统,系统功能齐全, 代码简洁易懂&#xff0c;适合小白学编程。 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数…

Spring Boot 3 整合 MinIO 实现分布式文件存储

引言 文件存储已成为一个做任何应用都不可回避的需求。传统的单机文件存储方案在面对大规模数据和高并发访问时往往力不从心&#xff0c;而分布式文件存储系统则提供了更好的解决方案。本篇文章我将基于Spring Boot 3 为大家讲解如何基于MinIO来实现分布式文件存储。 分布式存…

Redis|集群 Cluster

文章目录 是什么能干嘛集群算法-分片-槽位slotredis集群的槽位slotredis集群的分片分片槽位的优势slot槽位映射——业界的3种解决方案小厂&#xff1a;哈希取余分区中厂&#xff1a;一致性哈希算法分区大厂&#xff1a;哈希槽分区 面试题&#xff1a;为什么 Redis 集群的最大槽…

【定制开发】碰一碰发视频系统定制开发,支持OEM

在短视频营销爆发的2025年&#xff0c;"碰一碰发视频"技术已成为实体商家引流标配。某连锁餐饮品牌通过定制化开发&#xff0c;单月视频发布量突破10万条&#xff0c;获客成本降低80%&#xff01;本文将深入解析该系统的技术架构与开发要点&#xff0c;助你快速搭建高…

Linux上位机开发(开篇)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 传统的上位机开发&#xff0c;一般都是默认pc软件开发。既然是pc软件&#xff0c;一般来说都是基于windows平台开发。开放的框架&#xff0c;无非是…

算法005——有效三角形个数

力扣——有效三角形个数点击链接跳转 判断三条边是否能组成三角形&#xff0c;大家第一时间想到的就是两边之和大于第三边 但是运用这个方法&#xff0c;我们需要判断三次&#xff0c;有一个更简单的方法&#xff0c;只需要判断一次 因为 C 已经是三边之中最大的了&#xff…

【STM32】江科大STM32学习笔记汇总(已完结)

00. 目录 文章目录 00. 目录01. STM32学习笔记汇总02. 相关资料下载03. 打赏04. 附录 01. STM32学习笔记汇总 【STM32】STM32学习笔记-课程简介(01) 【STM32】STM32学习笔记-STM32简介(02) 【STM32】STM32学习笔记-软件安装(03) 【STM32】STM32学习笔记-新建工程(04) 【ST…