Unity 通用UI界面逻辑总结
概述
在游戏开发中,常常会遇到一些通用的界面逻辑,它不论在什么类型的游戏中都会出现。为了避免重复造轮子,本文总结并提供了一些常用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 framevoid 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;}
}
相关文章:
Unity 通用UI界面逻辑总结
概述 在游戏开发中,常常会遇到一些通用的界面逻辑,它不论在什么类型的游戏中都会出现。为了避免重复造轮子,本文总结并提供了一些常用UI界面的实现逻辑。希望可以帮助大家快速开发通用界面模块,也可以在次基础上进行扩展修改&…...
入门到入土,Java学习day15(常用API下)
group存数据 public String[] matches(String regex)判断字符串是否满足正则表达式的规则 public String replaceAll(String regex,String newStr)按照正则表达式的规则进行替换 public String[] split(String regex)按照正则表达式的规则切割字符串 通常是创建网页对象&am…...
Navigation的进阶知识与拦截器配置
Navigation的进阶知识与拦截器配置 写的不是很详细,后续有时间会补充,建议参考官方文档食用 1.如何配置路由信息 1.1 创建工程结构 src/main/ets ├── pages │ └── navigation │ ├── views │ │ ├── Mine.ets //…...
基于大模型的小脑扁桃体下疝畸形全流程预测与诊疗方案研究报告
目录 一、引言 1.1 研究背景与目的 1.2 研究意义 二、小脑扁桃体下疝畸形概述 2.1 定义与分类 2.2 发病机制与病因 2.3 临床表现 2.4 诊断方法 三、大模型在小脑扁桃体下疝畸形预测中的应用 3.1 大模型介绍 3.2 数据收集与处理 3.3 模型训练与验证 四、术前预测与…...
Java数据结构第二十一期:解构排序算法的艺术与科学(三)
专栏:Java数据结构秘籍 个人主页:手握风云 目录 一、常见排序算法的实现 1.1. 归并排序 二、排序算法复杂度及稳定性分析 一、常见排序算法的实现 1.1. 归并排序 归并排序是建⽴在归并操作上的⼀种有效的排序算法,该算法是采⽤分治法的一个⾮常典型的…...
go切片定义和初始化
1.简介 切片是数组的一个引用,因此切片是引用类型,在进行传递时,遵守引用传递的机制。切片的使用和数组类似,遍历切片、访问切片的元素和切片的长度都一样。。切片的长度是可以变化的,因此切片是一个可以动态变化的数…...
使用 Docker 部署 Nginx,配置后端 API 轮询与多个子域名前端应用
使用 Docker 部署 Nginx,配置后端 API 轮询与多个子域名前端应用 在这篇博客中,我们将介绍如何通过 Docker 部署 Nginx 服务器,并配置 多个后端 API 的轮询负载均衡,同时通过 子域名 部署多个不同的前端应用。Nginx 将作为反向代…...
【NLP 39、激活函数 ⑤ Swish激活函数】
我的孤独原本是座荒岛,直到你称成潮汐,原来爱是让个体失序的永恒运动 ——25.2.25 Swish激活函数是一种近年来在深度学习中广泛应用的激活函数,由Google Brain团队在2017年提出。其核心设计结合了Sigmoid门控机制和线性输入的乘积,…...
C语言经典案例-菜鸟经典案例
1.输入某年某月某日,判断这一天是这一年的第几天? //输入某年某月某日,判断这一天是这一年的第几天? #include <stdio.h>int isLeapYear(int year) {// 闰年的判断规则:能被4整除且(不能被100整除或…...
南开提出1Prompt1Story,无需训练,可通过单个连接提示实现一致的文本到图像生成。
(1Prompt1Story)是一种无训练的文本到图像生成方法,通过整合多个提示为一个长句子,并结合奇异值重加权(SVR)和身份保持交叉注意力(IPCA)技术,解决了生成图像中身份不一致…...
STM32驱动OLED屏幕全解析:从原理到温度显示实战(上) | 零基础入门STM32第五十三步
主题内容教学目的/扩展视频OLED显示屏重点课程电路原理,手册分析,驱动程序。初始化,清屏,ASCII字库,显示分区。调用显示函数。做带有加入图形和汉字显示的RTC时钟界面。讲字库的设计原理。 师从洋桃电子,杜…...
MySQL语法总结
本篇博客说明: !!!.注意此系列都用的是MySQL语句,和SQLServer,PostgreSQL有些细节上的差别!!! 1.每个操作都是先展示出语法格式 2.然后是具体例子 3.本篇注脚与文本顺讯息…...
从预测到控制:电力RK3568边缘计算机在电网调度中的全面应用
在智能电网的快速发展中,电力Ubuntu工控机(简称“电力工控机”)作为核心设备,扮演着不可或缺的角色。特别是在智能电网调度场景中,电力工控机的高效、稳定和智能化特性,为电网的稳定运行和高效管理提供了强…...
Spring Batch 概览
Spring Batch 是什么? Spring Batch 是 Spring 生态系统中的一个轻量级批处理框架,专门用于处理大规模数据任务。它特别适合企业级应用中需要批量处理数据的场景,比如数据迁移、报表生成、ETL(Extract-Transform-Load)…...
day-106 统计放置房子的方式数
思路 动态规划:因为中间有街道隔开,所以只需计算一边街道的排列方式,最后计算平方即可 解题过程 动态转换方程: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,可以免密登录3. 进行免密登录4. 添加root用户和修改postgres用户密码1. postgres用户密码2. 添加root用户3. 为root用户设…...
解决电脑问题(10)——桌面问题
电脑桌面出现问题的情况多样,以下是一些常见问题及解决方法: 桌面图标问题 图标显示异常:如果图标模糊、失真或显示为未知图标,可能是图标缓存出现问题。在 Windows 系统中,可通过在任务管理器中重启 “Windows 资源管…...
LPZero: Language Model Zero-cost Proxy Search from Zero(未更新完预览版本)
LPZero代码 摘要 神经架构搜索 (NAS) 有助于自动执行有效的神经网络搜索,同时需要大量的计算资源,尤其是对于语言模型。零样本 NAS 利用零成本 (ZC) 代理来估计模型性能,从而显着降低计算需求。然而,现有的 ZC 代理严重依赖于深…...
字典树运用
字典树运用 字典树LC208 创建字典树0-1字典树 字典树 字典树又叫 前缀树, 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补全和拼写检查。 LC208 创建字典树 这是一个字符串字典树…...
RReadWriteLock读写锁应用场景
背景 操作涉及一批数据,如订单,可能存在多个场景下操作,先使用读锁,从redis缓存中获取操作中数据 比如 关闭账单, 发起调账, 线下结算, 合并支付 先判断当前操作的数据,是否在…...
26.卷1的答案
1.已知2010年小明的生日在8月28日——周六 ,从2011到2020,有几次生日在周末? 做法:一个一个算下去,注意,平年365天,闰年366天,一共2次。 2.前序:ABDGKEHCFIJ,中序&…...
0087.springboot325基于Java的企业OA管理系统的设计与实现+论文
一、系统说明 基于springbootvue的企业OA管理系统,系统功能齐全, 代码简洁易懂,适合小白学编程。 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数…...
Spring Boot 3 整合 MinIO 实现分布式文件存储
引言 文件存储已成为一个做任何应用都不可回避的需求。传统的单机文件存储方案在面对大规模数据和高并发访问时往往力不从心,而分布式文件存储系统则提供了更好的解决方案。本篇文章我将基于Spring Boot 3 为大家讲解如何基于MinIO来实现分布式文件存储。 分布式存…...
Redis|集群 Cluster
文章目录 是什么能干嘛集群算法-分片-槽位slotredis集群的槽位slotredis集群的分片分片槽位的优势slot槽位映射——业界的3种解决方案小厂:哈希取余分区中厂:一致性哈希算法分区大厂:哈希槽分区 面试题:为什么 Redis 集群的最大槽…...
【定制开发】碰一碰发视频系统定制开发,支持OEM
在短视频营销爆发的2025年,"碰一碰发视频"技术已成为实体商家引流标配。某连锁餐饮品牌通过定制化开发,单月视频发布量突破10万条,获客成本降低80%!本文将深入解析该系统的技术架构与开发要点,助你快速搭建高…...
【redis】布隆过滤器的Java实现
在Java中,要实现布隆过滤器(Bloom Filter)的方式有很多种,除了上一节中通过jedis包调用安装了布隆过滤器的redis外,还有以下几种常见的实现方式: 手写布隆过滤器 基于guava包实现 通过redis的bitmaps实现…...
【JAVA架构师成长之路】【电商系统实战】第12集:秒杀系统性能优化实战(CAN + Nginx + Sentinel)
30分钟课程:秒杀系统性能优化实战(CDN Nginx Sentinel) 课程目标 掌握静态资源 CDN 加速的配置与优化策略。通过 Nginx 实现负载均衡,提升系统横向扩展能力。使用 Sentinel 实现服务降级,保障核心链路稳定性。 课程…...
MySQL安装过程,创建数据库
window操作系统安装 存在两种安装方式: 1.安装包方式 2.压缩包方式 安装包方式 下载安装包 官网下载对应的安装包,根据需要下载对应的版本即可: 8.0:https://cdn.mysql.com//Downloads/MySQLInstaller/mysql-installer-comm…...
Linux上位机开发(开篇)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 传统的上位机开发,一般都是默认pc软件开发。既然是pc软件,一般来说都是基于windows平台开发。开放的框架,无非是…...
算法005——有效三角形个数
力扣——有效三角形个数点击链接跳转 判断三条边是否能组成三角形,大家第一时间想到的就是两边之和大于第三边 但是运用这个方法,我们需要判断三次,有一个更简单的方法,只需要判断一次 因为 C 已经是三边之中最大的了ÿ…...
