Unity3D有限状态机(FSM)学习笔记【7】使用实例

本系列笔记转载自游戏蛮牛专栏作家Jackel的论坛文章,详细介绍了FSM的创建与使用,特与众分享。链接:http://www.manew.com/thread-37136-1-1.html

一、实例图例


该实例主要是按钮状态的转换。

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

二、文件结构


左图是有限状态机的代码,共5个,右侧是实例的代码,共6个。下面给出有图的6个文件源码:

一、代码

1、AudioMenuUI

using System.Collections;

public class AudioMenuUI : MenuUI, IState
{
	public void OnEnter( string nextState )
	{
		
	}
	
	public void OnExit( string nextState )
	{
		
	}
	
	public void OnUpdate()
	{
		
	}
	
	public override void DoGUI()
	{
		if( GUILayout.Button( "Back to menu", GUILayout.Width( Screen.width ), GUILayout.Height( Screen.height / 2 )))	
		{
			TestUIState.Events.Trigger( "BackToMenu" );
		}
		
//		if( GUILayout.Button( "CloseAudio", GUILayout.Width( Screen.width ), GUILayout.Height( Screen.height / 2 )))	
//		{
//			TestUIState.Events.Trigger( "CancelQuit" );	
//		}
	}
}

2、MainGame

using UnityEngine;
using System.Collections;

public class MainGame : MenuUI, IState
{
	protected FiniteStateMachine FSM;
	
	protected float Score = 0f;
	
	public MainGame( FiniteStateMachine parentMachine )
	{
		FSM = parentMachine;	
	}
	
	public void OnEnter( string prevState )
	{
		Score = 0f;	
	}
	
	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( 25 );
		GUILayout.Label( "The waiting game!" );
		GUILayout.Space( 25 );
		GUILayout.Label( "CurrentScore: " + System.Convert.ToInt32( Score ));
		Score += Time.deltaTime;
	}	
}

3、MainMenuUI

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" );
		}
	}	
}

4、MenuUI

using UnityEngine;
using System.Collections;

public class MenuUI
{
	public virtual void DoGUI()
	{
		
	}	
}

5、QuitGameUI

using UnityEngine;
using System.Collections;

public 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();
	}
}

6、TestUIState

using UnityEngine;
using System.Collections;

public class TestUIState : MonoBehaviour 
{
	public static EventSystem.Dispatcher Events = new EventSystem.Dispatcher();
	public FiniteStateMachine FSM = new FiniteStateMachine();
	
	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 );
		});
	}
	
	void Update()
	{
		FSM.Update();	
	}
	
	void OnGUI()
	{
		if( FSM.CurrentState == null )
		{
			return;	
		}
		MenuUI ui = (MenuUI)FSM.CurrentState.StateObject;
		ui.DoGUI();
	}
}

二、使用

只需把TestUIState挂在场景的一个对象中即可。

代码:http://pan.baidu.com/s/1c0x1dMK

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值