Unity 中使用状态机模式来管理UI

1. 清晰的状态管理

状态机模式允许你以结构化的方式管理不同的UI状态。每个状态(比如主菜单、设置菜单、游戏中界面等)都有其独立的行为和属性,这使得管理复杂UI逻辑变得更加清晰和可维护。

2. 简化的状态切换

状态机模式可以简化不同UI状态之间的切换逻辑。使用状态机,可以很容易地定义状态之间的转换规则,并确保状态切换时的逻辑是正确的和一致的。

3. 分离关注点

通过将UI逻辑分割到不同的状态类中,可以使每个状态类只关心自己的行为和属性。这有助于减少代码的耦合,提高代码的可读性和可维护性。

4. 更容易的扩展和维护

当需要添加新的UI状态或修改现有状态的行为时,状态机模式使得这种修改变得更简单。可以通过添加或修改单个状态类来实现,而不必修改整个UI管理系统。

5. 动画和过渡效果

使用状态机模式,可以轻松地管理UI状态的进入和退出动画。例如,可以在状态进入时播放淡入动画,在状态退出时播放淡出动画。状态机模式可以确保这些动画在状态切换时正确播放。

6. 统一的状态处理逻辑

状态机模式提供了一种统一的方式来处理UI状态的更新、渲染和事件处理。这有助于保持代码的一致性,并避免不同状态处理逻辑的重复代码。

状态接口

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public interface IState//interface 状态机接口
{void Enter();void Exit();void LogicUpdata();void PhysicUpdata();void AinamtionEvent();
}

状态机管理器

using System.Collections;
using System.Collections.Generic;
using UnityEngine;//用于管理状态机切换
public class StateMachina : MonoBehaviour
{IState currentState;private void Update(){currentState?.LogicUpdata();}private void FixedUpdate(){currentState?.PhysicUpdata();}public virtual void AnimationEvent(){currentState?.AinamtionEvent();}public virtual void SwitchState(IState newState){currentState?.Exit();currentState=newState;currentState.Enter();}}

基础状态类

using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
[RequireComponent(typeof(Canvas))]
[RequireComponent(typeof(CanvasGroup))]
[RequireComponent(typeof(RectTransform))]
public class UIState : MonoBehaviour,IState
{protected Canvas canvas;protected CanvasGroup canvasGroup;protected RectTransform rectTransform;//ui位置protected int initialSortingOrder;protected virtual void Awake(){canvas = GetComponent<Canvas>();canvasGroup = GetComponent<CanvasGroup>();rectTransform= GetComponent<RectTransform>();initialSortingOrder = canvas.sortingOrder;}public virtual void AinamtionEvent(){}public virtual void Enter(){canvas.enabled = true;}public virtual void Exit(){canvas.enabled = false;}public virtual void LogicUpdata(){}public virtual void PhysicUpdata(){}
}

具体的ui管理器负责ui的加载和切换状态,设置为单列模式,动态加载ui

using System.Collections.Generic;
using UnityEngine;public class UIManager : StateMachina
{public static UIManager Instance;string realPath = "Prefab/Panel/";private Dictionary<string, GameObject> prefabDict = new Dictionary<string, GameObject>();private IState currentState;private void Awake(){if (Instance == null){Instance = this;DontDestroyOnLoad(gameObject);SwitchPanel(My_UIConst.MainMenuPanel);}else{Destroy(gameObject);}}public GameObject CreatePanel(string name){if (prefabDict.ContainsKey(name)){return prefabDict[name];}GameObject panelPrefab = Resources.Load<GameObject>(realPath + name);if (panelPrefab == null){Debug.LogError($"Failed to load panel prefab: {realPath}{name}");return null;}GameObject panelObject = Instantiate(panelPrefab, gameObject.transform, false);prefabDict[name] = panelObject;return panelObject;}public void SwitchPanel(string name){UIState newState;if (prefabDict.ContainsKey(name)){newState = prefabDict[name].GetComponent<UIState>();}else{GameObject panelObject = CreatePanel(name);if (panelObject == null){Debug.LogError($"Failed to create panel: {name}");return;}newState = panelObject.GetComponent<UIState>();}SwitchState(newState);}
}

UIManager 挂载在canvas上

ui放在 Resources下面

ui的名称路径


public class My_UIConst 
{public const string MainMenuPanel = "Menu/MainMenuPanel";public const string UserPanel = "Menu/UserPanel";public const string SettingsPanel = "Menu/SettingsPanel";// 你可以根据需要添加更多的 UI 名称
}

具体的UI状态类 用dotweet来实现动画效果

using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class My_MainMenu : UIState
{public Button userButton;public Image bg;private void Start(){userButton.onClick.AddListener(() =>{Debug.Log("主菜单按钮点击 切换用户界面");UIManager.Instance.SwitchPanel(My_UIConst.UserPanel);});}public override void Enter(){Debug.Log("进入主菜单");DOTween.To(() => canvasGroup.alpha=0, x => canvasGroup.alpha=x, 1, 1);// 生成一个随机颜色Color randomColor = new Color(Random.value, Random.value, Random.value);bg.DOColor(randomColor, 1f); // 渐变到随机颜色base.Enter();}public override void Exit(){Color randomColor = new Color(Random.value, Random.value, Random.value);bg.DOColor(randomColor, 1f); // 渐变到随机颜色}}
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;  // 引入 DOTween 命名空间
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;public class My_UserPanel : UIState
{public Button mainMenuButton;private void Start(){mainMenuButton.onClick.AddListener(() =>{Debug.Log("用户按钮点击 切换主界面");UIManager.Instance.SwitchPanel(My_UIConst.SettingsPanel);});}public override void Enter(){Debug.Log("进入用户界面");// 设置初始位置canvas.transform.localPosition = new Vector3(-Screen.width, 0, 0);rectTransform.SetAsLastSibling();//将渲染等级移动到最后面 显示在最前面// 使用 DOTween 平移动画将面板移到屏幕中心canvas.transform.DOLocalMoveX(0, 1f).SetEase(Ease.OutQuad);base.Enter();}public override void Exit(){rectTransform.SetAsLastSibling();//将渲染等级移动到最后面 显示在最前面// 在退出时添加平移动画canvas.transform.DOLocalMoveX(-Screen.width, 1f).SetEase(Ease.OutQuad).OnComplete(() =>{base.Exit();});}
}

using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class My_SettingPanel : UIState
{public Button mainMenuButton;private void Start(){mainMenuButton.onClick.AddListener(() =>{Debug.Log("用户按钮点击 切换主界面");UIManager.Instance.SwitchPanel(My_UIConst.MainMenuPanel);});}public override void Enter(){Debug.Log("进入用户界面");// 设置初始位置canvas.transform.localPosition = new Vector3(Screen.width, 0, 0);rectTransform.SetAsLastSibling();//将渲染等级移动到最后面 显示在最前面// 使用 DOTween 平移动画将面板移到屏幕中心canvas.transform.DOLocalMoveX(0, 1f).SetEase(Ease.OutQuad);base.Enter();}public override void Exit(){rectTransform.SetAsLastSibling();//将渲染等级移动到最后面 显示在最前面// 在退出时添加平移动画canvas.transform.DOLocalMoveX(-Screen.width, 1f).SetEase(Ease.OutQuad).OnComplete(() =>{base.Exit();});}}

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

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

相关文章

报表控件DevExpress Reporting中文教程 - 如何创建穿透钻取报表?

DevExpress Reporting是.NET Framework下功能完善的报表平台&#xff0c;它附带了易于使用的Visual Studio报表设计器和丰富的报表控件集&#xff0c;包括数据透视表、图表&#xff0c;因此您可以构建无与伦比、信息清晰的报表。 钻取报表允许用户通过单击主/活动报表文档中的…

Android的dtbo文件介绍

文章目录 设备树&#xff08;Device Tree&#xff09;设备树覆盖&#xff08;Device Tree Overlay, DTO&#xff09;dtbo文件的作用使用流程示例 dtbo 文件是 Android 设备中的设备树覆盖文件&#xff08;Device Tree Blob Overlay&#xff09;。它用于动态地修改设备树配置&am…

智能酒精壁炉与会所会客厅的氛围搭配

智能酒精壁炉与会所会客厅的氛围搭配可以创造出现代、高雅且舒适的环境&#xff0c;提升客人的整体体验。以下是如何将智能酒精壁炉与会所会客厅氛围相协调的几点建议&#xff1a; 现代化与高品位感&#xff1a; 智能酒精壁炉展现出现代化的设计和高科技特点&#xff0c;与会所…

应急响应-战后溯源反制社会工程学

&#x1f3bc;个人主页&#xff1a;金灰 &#x1f60e;作者简介:一名简单的大一学生;易编橙终身成长社群的嘉宾.✨ 专注网络空间安全服务,期待与您的交流分享~ 感谢您的点赞、关注、评论、收藏、是对我最大的认可和支持&#xff01;❤️ &#x1f34a;易编橙终身成长社群&#…

开源的混合AI搜索引擎;定制 Claude 3 Haiku 模型; 和gpt-4o同样Transformer架构的开源视觉语言模型;离线自动转录工具

✨ 1: MemFree MemFree是一款开源的混合AI搜索引擎&#xff0c;可搜索个人知识库和互联网。 MemFree 是一个开源的混合AI搜索引擎&#xff0c;可以同时在你的个人知识库&#xff08;如书签、笔记、文档等&#xff09;和互联网中进行搜索。这款搜索引擎的主要特点包括&#xf…

嵌入式智能手表项目实现分享

简介 这是一个基于STM32F411CUE6和FreeRTOS和LVGL的低成本的超多功能的STM32智能手表~ 推荐 如果觉得这个手表的硬件难做,又想学习相关的东西,可以试下这个新出的开发板,功能和例程demo更多!FriPi炸鸡派STM32F411开发板: 【STM32开发板】 FryPi炸鸡派 - 嘉立创EDA开源硬件平…

使用mediapip 检测pose 并作为一个服务

代码 import uvicorn from fastapi import FastAPI, HTTPException import cv2 import mediapipe as mp from pydantic import BaseModelapp FastAPI()# 创建一个模型来序列化姿态数据 class PoseData(BaseModel):landmarks: list# 初始化MediaPipe的姿态估计模型 mp_pose m…

GD32MCU最小系统构成条件

大家是否有这个疑惑&#xff1a;大学课程学习51的时候&#xff0c;老师告诉我们51的最小系统构成&#xff1f;那么进入32位单片机时代&#xff0c;gd32最小系统构成又是怎么样的呢&#xff1f; 1.供电电路 需要确保供电的电压电流稳定&#xff0c;以东方红开发版为例&#xff…

Qt WARNING: Failure to find: xxxxxx.h

重新规划了自定义文件夹后&#xff0c;编译出现错误&#xff0c;如 Qmake WARNING: Failure to find: xxxxxx.h 或者 error: XXXX.h: No such file or directory 如果文件是在windows下直接重新放置新的目录&#xff0c;那么需要修改.pro文件 老文件的可能没有注释或删除&am…

ABAQUS广东正版代理商:亿达四方——达索官方授权

在粤港澳大湾区建设的浪潮中&#xff0c;广东作为中国改革开放的前沿阵地&#xff0c;始终走在科技创新的最前线。亿达四方&#xff0c;作为国际领先的仿真软件ABAQUS在广东地区的官方授权代理商&#xff0c;正以先进的技术和服务&#xff0c;推动着广东地区制造业向智能化、高…

【Tomcat目录详解】关于Tomcat你还需要了解的详细内容

希望文章能给到你启发和灵感&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏 支持一下博主吧&#xff5e; 阅读指南 开篇说明一、基础环境说明1.1 硬件环境1.2 软件环境 二、Tomcat的文件结构2.1 bin目录2.1.1 startup和shutdown2.1.2 Catalina2.1.3 serv…

深入解析EtherCAT `CheckProductCode` 属性:确保系统一致性与安全性

在工业自动化领域&#xff0c;EtherCAT&#xff08;Ethernet for Control Automation Technology&#xff09;已成为一种广泛应用的实时以太网协议。它的高性能、灵活性和可靠性使其成为复杂自动化任务的理想选择。然而&#xff0c;确保系统的正确配置和安全运行是使用EtherCAT…

【43页PPT】企业数据架构数据治理设计规划咨询项目建议

本项目聚焦于企业数据资产的深度挖掘与价值最大化&#xff0c;旨在通过一系列定制化策略与架构设计&#xff0c;重塑企业的数据生态体系。我们的核心任务包括&#xff1a; 企业现状深度剖析&#xff1a;全面审视企业当前的数据环境、业务流程及战略方向&#xff0c;精准把握数…

Opencv中的直方图

cv2.calcHist() 直方图是图像中像素强度分布的图形表达方式&#xff0c;统计了每一个强度值所具有的像素个数。并可以计算图像中的一个或多个通道的直方图。 dst cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])images&#xff1a;源图像&am…

Docker 基本管理及部署

目录 1.Docker概述 1.1 Docker是什么&#xff1f; 1.2 Docker的宗旨 1.3 容器的优点 1.4 Docker与虚拟机的区别 1.5 容器在内核中支持的两种技术 1.6 namespace的六大类型 2.Docker核心概念 2.1 镜像 2.2 容器 2.3 仓库 3.安装Docker 3.1 查看 docker 版本信息 4.…

Java程序打印日志

一、maven依赖 POM文件中添加以下依赖&#xff0c;maven依赖的jar包版本可以在maven central repository 查看 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.34</version><…

【C语言】《回调函数》详细解析

目录 1. 什么是回调函数&#xff1f;2. 回调函数的用途3. 回调函数的基本实现3.1 定义回调函数类型3.2 注册回调函数3.3 使用回调函数 4. 示例与输出5. 注意事项6. 参考文献7. 结束语 回调函数&#xff08;Callback Function&#xff09;在C语言中是一种非常重要且常用的编程技…

CentOS7将yum源更换为国内源保姆级教程(含一键脚本)

在 CentOS 7 中更换 YUM (Yellowdog Updater Modified) 源到国内镜像可以显著提升软件包的下载速度。以下是一种常见的方法来更换为国内源&#xff0c;例如阿里云镜像&#xff1a; 备份原有源配置文件&#xff1a; sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d…

Apple trackpad 一代在win10下使用

鼠标点的食指有的累&#xff0c;翻出来一个旧的Apple trackpad一代&#xff0c;经典的电池仓和蓝牙配置。 支持手势操作&#xff0c;双指滑动可以滚动滚动条。 使用官方 Boot Camp 驱动程序。 有个AppleWirelessTrackpad64.exe安装就可以。

FPGA上板项目(一)——点灯熟悉完整开发流程、ILA在线调试

目录 创建工程创建 HDL 代码仿真添加管脚约束添加时序约束生成 bit 文件下载ILA 在线调试 创建工程 型号选择&#xff1a;以 AXU9EG 开发板为例&#xff0c;芯片选择 xczu9eg-ffvb1156-2-i 创建 HDL 代码 注意&#xff1a;由于输入时钟为 200MHz 的差分时钟&#xff0c;因此…