天天看點

Unity3D有限狀态機(FSM)學習筆記【7】使用執行個體

本系列筆記轉載自遊戲蠻牛專欄作家Jackel的論壇文章,詳細介紹了FSM的建立與使用,特與衆分享。連結:http://www.manew.com/thread-37136-1-1.html

一、執行個體圖例

Unity3D有限狀态機(FSM)學習筆記【7】使用執行個體

該執行個體主要是按鈕狀态的轉換。

給大家解析一下,程式運作首先進入主菜單,裡面有三個按鈕,開始遊戲,音量,退出遊戲。先從第一個說起,如果是開始遊戲,它會進入到下一個界面遊戲界面,遊戲界面有個傳回主菜單功能。二者可以互相切換。接下來是音量按鈕,整個按鈕是調節音量的,調節好了後,點确認和取消都是傳回主菜單。二者之間互相切換,最後一個是退出遊戲,會進入是否退出界面,如果否,傳回主界面,如果是真正的關閉遊戲。我們就把這個簡單的功能用我們的有限狀态機實作一下:

二、檔案結構

Unity3D有限狀态機(FSM)學習筆記【7】使用執行個體
Unity3D有限狀态機(FSM)學習筆記【7】使用執行個體

左圖是有限狀态機的代碼,共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

繼續閱讀