位置: 编程技术 - 正文

Unity3D架构系列之- FSM有限状态机设计(六)(总结篇)(unity3d的)

编辑:rootadmin

推荐整理分享Unity3D架构系列之- FSM有限状态机设计(六)(总结篇)(unity3d的),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:unity3d官方,unity3d总结,unity3d官方案例,unity 3d介绍,unity 架构,unity3d的,unity3ds,unity3ds,内容如对您有帮助,希望把文章链接给更多的朋友!

由于最近一直赶项目进度,没时间写,昨晚终于项目终于完成了,空闲下来,做一个总结。在这一篇中主要是把前五章一起总结一下,以及通过举例演示如何使用?有限状态机在游戏中使用的地方非常多,比如我们界面之间的切换,角色的状态切换等等。所以非常&#;得大家去学习一下,接下来我们主要实现的功能,为了表达清楚,我通过图例给大家说明一下:

给大家解析一下,程序运行首先进入主菜单,里面有三个按钮,开始游戏,音量,退出游戏。先从第一个说起,如果是开始游戏,它会进入到下一个界面游戏界面,游戏界面有个返回主菜单功能。二者可以互相切换。接下来是音量按钮,整个按钮是调节音量的,调节好了后,点确认和取消都是返回主菜单。二者之间互相切换,最后一个是退出游戏,会进入是否退出界面,如果否,返回主界面,如果是真正的关闭游戏。我们就把这个简单的功能用我们的有限状态机实现一下:

首先我们声明两个对象:

public static EventSystem.Dispatcher Events = new EventSystem.Dispatcher(); public FiniteStateMachine FSM = new FiniteStateMachine();

events主要是创建一个全局的事件系统用于我们指定的UI。

FSM是作为一个状态机被驱动。

接下来我们注册几个状态用我们的状态机:

FSM.Register("MainMenu", new MainMenuUI()); FSM.Register("AudioMenu", new AudioMenuUI()); FSM.Register("MainGame", new MainGame(FSM)); FSM.Register("QuitGame", new QuitGameUI());

我们用EntryPoint告诉玩家我们第一个界面是主界面:

1FSM.EntryPoint("MainMenu");

我们为主界面定义几个actions,OPEN_AUDIO,PLAY_GAME, QUIT_GAME.其中OPEN_AUDIO和QUIT_GAME用于取代顶部栈的状态。PLAY_GAME用于增加状态栈新的item。代码如下:

FSM.State("MainMenu").On("OPEN_AUDIO").Enter("AudioMenu") .On("PLAY_GAME").Push("MainGame") .On("QUIT_GAME").Enter("QuitGame");

退出菜单响应PROCESS_QUIT action。代码如下:

FSM.State("QuitGame").On("PROCESS_QUIT", delegate(bool sure) { if (sure) { gameObject.GetComponent<TestUIState>().enabled = false; Camera.main.backgroundColor = Color.black; } else { FSM.Enter("MainMenu"); } });

上述代码主要实现的功能:如果确认游戏结束,否则返回主菜单。

游戏类是负责对于主菜单弹出栈顶元素的。

using UnityEngine;using System.Collections; class MainGame : MenuUI, IState { protected FiniteStateMachine FSM; protected float Score = 0; public MainGame(FiniteStateMachine parentMachine) { FSM = parentMachine; } public void OnEnter(string prevState) { Score = 0; } public void OnExit(string nextState) { } public void OnUpdate() { } public override void DoGUI() { if (GUILayout.Button("Quit / Back To Menu", GUILayout.Width(Screen.width))) { FSM.Pop(); } GUILayout.Space(); GUILayout.Label("The waiting game!"); GUILayout.Space(); GUILayout.Label("CurrentScore: " &#; System.Convert.ToInt(Score)); Score &#;= Time.deltaTime; }}

Unity3D架构系列之- FSM有限状态机设计(六)(总结篇)(unity3d的)

声音菜单保留它自己的状态,处理音量逻辑。代码如下:

1SM.State("AudioMenu").On("BACK_TO_MENU").Enter("MainMenu");

最后将每一个事件系统挂到状态机的actions里面,代码如下:

Events.On("OpenMainGame", delegate() { FSM.CurrentState.Trigger("PLAY_GAME"); }); Events.On("OpenAudioMenu", delegate() { FSM.CurrentState.Trigger("OPEN_AUDIO"); }); Events.On("QuitGame", delegate() { FSM.CurrentState.Trigger("QUIT_GAME"); }); Events.On("ConfirmQuit", delegate() { FSM.CurrentState.Trigger("PROCESS_QUIT", true); }); Events.On("CancelQuit", delegate() { FSM.CurrentState.Trigger("PROCESS_QUIT", false); }); Events.On("BackToMenu", delegate() { FSM.CurrentState.Trigger("BACK_TO_MENU", false); });

大家可能会问,状态机是如何切换的,我们将在Update里面实现,代码很简单:

public void Update() { FSM.Update(); }

这样就可以每一帧都可以进行检测push还是top状态机了。

为了响应主界面我们定义了一个OnGUI函数:

void OnGUI() { if (FSM.CurrentState == null) return; MenuUI ui = (MenuUI)FSM.CurrentState.StateObject; ui.DoGUI(); }

最后因为我们涉及到主界面各个操作,所以它们都有自己的类。

我将它们都拿出来给大家分享:

主菜单中声音菜单的逻辑代码如下:

using UnityEngine; using System.Collections;class AudioMenuUI : MenuUI, IState { float volume = 0.5f; float backupVolume = 0.0f; public void OnEnter(string prevState) { backupVolume = volume; } public void OnExit(string nextState) { } public void OnUpdate() { } public override void DoGUI() { GUILayout.Space(.0f); volume = GUILayout.HorizontalSlider(volume, 0.0f, 1.0f, GUILayout.Width(Screen.width)); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); GUILayout.Label("Volume: " &#; System.Convert.ToInt(volume * .0f) &#; " %"); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Cancel", GUILayout.Height(.0f))) { volume = backupVolume; TestUIState.Events.Trigger("BackToMenu"); } if (GUILayout.Button("Confirm", GUILayout.Height(.0f))) { TestUIState.Events.Trigger("BackToMenu"); } GUILayout.EndHorizontal(); } }

主菜单类逻辑代码如下:

using UnityEngine; using System.Collections;public class MainMenuUI : MenuUI, IState { public void OnEnter(string prevState) { } public void OnExit(string nextState) { } public void OnUpdate() { } public override void DoGUI() { if (GUILayout.Button("Play Game", GUILayout.Width(Screen.width), GUILayout.Height(Screen.height / 3))) { TestUIState.Events.Trigger("OpenMainGame"); } if (GUILayout.Button("Audio Menu", GUILayout.Width(Screen.width), GUILayout.Height(Screen.height / 3))) { TestUIState.Events.Trigger("OpenAudioMenu"); } if (GUILayout.Button("Quit Game", GUILayout.Width(Screen.width), GUILayout.Height(Screen.height / 3))) { TestUIState.Events.Trigger("QuitGame"); } } }

我们定义了一个菜单操作的抽象类用于继承:

using UnityEngine; using System.Collections;public class MenuUI { public virtual void DoGUI() {} }

游戏退出类代码如下:

using UnityEngine; using System.Collections;class QuitGameUI : MenuUI, IState { public void OnEnter(string prevState) { } public void OnExit(string nextState) { } public void OnUpdate() { } public override void DoGUI() { GUILayout.BeginHorizontal(); if (GUILayout.Button("Confirm", GUILayout.Width(Screen.width / 2), GUILayout.Height(Screen.height))) { TestUIState.Events.Trigger("ConfirmQuit"); } if (GUILayout.Button("Cancel", GUILayout.Width(Screen.width / 2), GUILayout.Height(Screen.height))) { TestUIState.Events.Trigger("CancelQuit"); } GUILayout.EndHorizontal(); } }

最后只要将下面的脚本挂到对象上就可以了:

using UnityEngine; using System.Collections;public class TestUIState : MonoBehaviour { public static EventSystem.Dispatcher Events = new EventSystem.Dispatcher(); public FiniteStateMachine FSM = new FiniteStateMachine();public void Awake() { FSM.Register("MainMenu", new MainMenuUI()); FSM.Register("AudioMenu", new AudioMenuUI()); FSM.Register("MainGame", new MainGame(FSM)); FSM.Register("QuitGame", new QuitGameUI()); FSM.EntryPoint("MainMenu"); FSM.State("MainMenu").On("OPEN_AUDIO").Enter("AudioMenu") .On("PLAY_GAME").Push("MainGame") .On("QUIT_GAME").Enter("QuitGame"); FSM.State("QuitGame").On("PROCESS_QUIT", delegate(bool sure) { if (sure) { gameObject.GetComponent<TestUIState>().enabled = false; Camera.main.backgroundColor = Color.black; } else { FSM.Enter("MainMenu"); } }); FSM.State("AudioMenu").On("BACK_TO_MENU").Enter("MainMenu"); Events.On("OpenMainGame", delegate() { FSM.CurrentState.Trigger("PLAY_GAME"); }); Events.On("OpenAudioMenu", delegate() { FSM.CurrentState.Trigger("OPEN_AUDIO"); }); Events.On("QuitGame", delegate() { FSM.CurrentState.Trigger("QUIT_GAME"); }); Events.On("ConfirmQuit", delegate() { FSM.CurrentState.Trigger("PROCESS_QUIT", true); }); Events.On("CancelQuit", delegate() { FSM.CurrentState.Trigger("PROCESS_QUIT", false); }); Events.On("BackToMenu", delegate() { FSM.CurrentState.Trigger("BACK_TO_MENU", false); }); }public void Update() { FSM.Update(); }void OnGUI() { if (FSM.CurrentState == null) return; MenuUI ui = (MenuUI)FSM.CurrentState.StateObject; ui.DoGUI(); } }

测试用的代码一共有AudioMenUI.cs MainGame.cs MainMenuUI.cs MenuUI.cs QuitGameUI.cs TestUIState.cs.大家只要将TestUIStat.cs挂到对象上就可以运行了。在使用的过程中可以先调试一下,前五章是给大家封装的,可以直接将其运用到项目中。这里的类只是跟大家分享一下如何去运用。

有限状态机到这里就全部结束了。有什么问题欢迎一起讨论。接下来我会给大家分享其他技术点。。。。。

转自:

unity3d在2d游戏中同时拖动多个collider 最近,又在弄unity3d,因为unity3d提供了官方的2d游戏设计工具,用下来还不错。就比较而言,unity3d和国内比较流行的cocos2d比较而言,unity3d的商城更好用

Shader Forge可视化Unity3D Shader编辑器一-简介 ShaderForge可视化Unity3DShader编辑器一-简介一、简介1.ShaderForge是一个基于节点的可视化shader编辑器2.ShaderForge的目标是提升Unity的视觉效果到一个新的高度3.

C#程序员整理的Unity 3D笔记(十三):Unity 3D基于组件的思想 如果你接触过《设计模式》、软件架构的编程思想,就会知道优秀的设计准则:组合优于继承的。这句话很简短,但开始学习OOP的时候,真切的是—-不

标签: unity3d的

本文链接地址:https://www.jiuchutong.com/biancheng/377286.html 转载请保留说明!

上一篇:unity3D+opencv环境配置(unity openvr)

下一篇:unity3d在2d游戏中同时拖动多个collider(unity2d的小游戏)

  • 小规模纳税人增值税减免账务处理
  • 城镇土地使用税的计税依据
  • 收入与支出怎么算利润率
  • 专票 附加费
  • 股权出让需要交税吗
  • 土地转让如何缴纳增值税
  • 取得划拨或赠与资产需要缴企业所得税吗?
  • 小规模建筑公司预缴增值税
  • 接受土地使用权作为投资属于什么凭证
  • 公司借款给个人超过一年未还
  • 累计折旧借贷方向分录
  • 公司注销后应收款能打到法人账户吗
  • 堤围防护费什么时候停止征收
  • 公司商务卡可以日常消费
  • 公司在原有生产领域内充分利用
  • 住宿发票的税率0
  • 水利建设专项收入
  • 新办企业需要做什么
  • 工会经费 管理费用
  • 本期增加固定资产原值
  • 个体工商户出售住房增值税
  • 如何升级mac系统到10.12
  • 什么叫盘活存量股票
  • 企业应纳税所得额计算公式
  • 如何设置win10电脑开机不黑屏
  • js图片放大代码
  • 增值税普通发票怎么开
  • 甘油三血脂高怎么办
  • thinkphp 多数据库
  • 深度学习第一步——Pytorch-Gpu环境配置:Win11/Win10+Cuda10.2+cuDNN8.5.0+Pytorch1.8.0(步步巨细,少走十年弯路)
  • vue3中props
  • 如何设置长期有效的群二维码安卓手机
  • 配置nginx支持php
  • 分包缴纳的个税怎么算
  • 公司基本户可以收款吗
  • 收到待报解预算收入怎么做账
  • vueity
  • 斯坦福大学起源
  • 简易计税结转账务处理
  • 个体生产经营所得优惠政策
  • 增值税申报表销项税额怎么算?
  • 如果已经结帐,发现凭证有误,应该如何处理
  • 增值税普通发票查询
  • python replace 多个
  • 织梦网站老是被挂马
  • 详解MySQL中EXPLAIN解释命令及用法讲解
  • mongodb主从复制和副本集架构有什么联系和区别
  • 怎么把python代码发给别人运行
  • 期末应交增值税的会计科目怎么做
  • 管理费用的范畴
  • 当月开的票必须开发票吗
  • 厂部管理人员的工资属于制造费用吗
  • 跨月的普通发票怎么开红字发票
  • 长期股权投资应计提减值准备的金额
  • 工程增值税抵扣比例
  • 主播收钱违法吗
  • 建筑企业怎么结算成本
  • 2020年账簿印花税减免政策
  • 研发费用加计扣除比例及计算方法
  • 其他收益和其他综合收益属于什么科目
  • 企业注销预付账款怎么做
  • 企业建账涉及哪些内容
  • 向sql server数据库中导入
  • linux下mysql的root密码忘记的解决方法
  • Win10 Mobile/PC RS2快速预览版14926同步推送
  • sdis.exe
  • xp无法访问win7电脑
  • win7系统如何
  • linux查看命令帮助信息的方式
  • linux k
  • json解析 java
  • meta 标签
  • opengl光照算法
  • js 验证数字
  • 用批处理结束进程
  • jQuery ztree实现动态树形多选菜单
  • unity meshcollider
  • 怎么在电脑上下载浙政钉
  • 湖南城乡居民医疗保险咨询电话
  • 机票电子发票怎么作废
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设