-AUTEUR(S): Spedy
-DESCRIPTION : Une des questions que l'on se pose au début d'un projet est son architecture ! En me baladant sur le site d'un autre utilisateur du forum ZeroKcm je suis tombé sur un de ces tuto http://www.zerokcm.fr/wp/question-darchitecture/ ( oui oui il y en a qui clique sur les liens des signatures. Sa vision ce rapprochant un peut de ce que j'utilise en As3 j'ai voulu en donné ma vision.
Il s'agit donc d'un stateManager.
Chaque state est définie pas un ensemble de Script ( Monobehaviour ).
En demandant au manager d'aller à une state celui si détruit les Scripts de la state précédente et instancie ceux de la nouvelle state.
Si un script de la state précédente ce trouve aussi dans la nouvelle state, il n'est pas touché par le script.
On peut ainsi avoir des states comme ceci :
State Menu ( ScriptMenu, ScriptFooter )
State Jeu ( ScriptJeu, ScriptFooter )
State Pause ( ScriptJeu, ScriptPause, ScriptFooter )
State Score ( ScriptScore, ScriptFooter )
Je poste donc ce script pour vous donnez ma vision, mais aussi connaitre votre avis sur ce type d'architecture et bien-sur sur ma façon de la mettre en place.
-UTILISATION :
Il suffi de mettre le script StateManager sur la scène.
Dans celui si les states sont défini dans la fonction init().
Code : Tout sélectionner
var sEnd : List.<System.Type> = new List.<System.Type>( );
sEnd.Add( StateEnd );
sEnd.Add( StateFooter );
registerState( State.MENU, sMenu );
StateProcess ( classe Abstrait pour les State )
Code : Tout sélectionner
using UnityEngine;
using System.Collections;
public abstract class StateProcess : MonoBehaviour
{
public virtual void Exit() {}
}
Code : Tout sélectionner
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class StateManager : MonoBehaviour {
public enum State
{
NULL,
MENU,
GAME,
END
}
public static StateManager instance;
public State defaultState;
protected State _state;
protected State _prevState;
protected Hashtable _hStates = new Hashtable();
// Use this for initialization ( this is a singleton )
void Awake() {
if( instance == null )
instance = this;
else
Debug.LogError( "Cannot instantiate StateManager twice !" );
init( );
}
/**
* Initialisation of states
*
* @param
* @return
*/
public void init( ){
List<System.Type> sMenu = new List<System.Type>( );
sMenu.Add( typeof( StateMenu ) );
sMenu.Add( typeof( StateFooter ) );
List<System.Type> sGame = new List<System.Type>( );
sGame.Add( typeof( StateGame ) );
List<System.Type> sEnd = new List<System.Type>( );
sEnd.Add( typeof( StateEnd ) );
sEnd.Add( typeof( StateFooter ) );
registerState( State.MENU, sMenu );
registerState( State.GAME, sGame );
registerState( State.END, sEnd );
state = defaultState;
}
/**
* Register a state
*
* @public
* @param eName : State cade name ( enum State )
* @param lProcess : List of process ( List<System.Type> )
* @return true if success ( bool )
*/
public bool registerState( State eName, List<System.Type> lProcess ){
if( _hStates.ContainsKey( eName ) )
Debug.LogError( "registerState ::: A State with the name " + eName + "is already registered" );
_hStates.Add( eName, lProcess );
return true;
}
/**
* function registerState
*
* @public
* @param eName : State cade name ( enum State )
* @return list of process ( List<System.Type> )
*/
public List<System.Type> getStateContent( State eName ) {
return ( List<System.Type> ) _hStates[ eName ];
}
/**
* UnRegister a state
*
* @param eName : State cade name ( enum State )
* @return true if success ( bool )
*/
public bool unRegisterStater( State eName ){
if( !_hStates.ContainsKey( eName ) )
Debug.LogError( "getStateContent ::: The State " + eName + " is not registered" );
_hStates.Remove( eName );
return true;
}
public State state
{
get
{
return _state;
}
set
{
if( !_hStates.ContainsKey( value ) )
Debug.LogError( "The state " + value + " is unkown" );
if( _state == value )
Debug.LogError( "The state " + value + " is already the current state" );
_execState( value );
}
}
//----------o Private
/**
* Store the last state before drawing the new state
*
* @param eName : State to draw ( enum State )
* @return
*/
private void _execState( State eName ){
_prevState = _state;
_state = eName;
_drawState( );
}
/**
* Drawning the DisplayList of the current state
*
* @param
* @return
*/
private void _drawState(){
List<System.Type> v = ( List<System.Type> ) _hStates[ _state ];
int i;
StateProcess comp;
List<System.Type> vTmp = ( List<System.Type> ) _hStates[ _prevState ];
if( vTmp != null )
{
i = vTmp.Count;
while( --i >= 0 )
{
if( v.Contains( vTmp[ i ] ) )
continue;
comp = ( StateProcess ) GetComponent( vTmp[ i ] );
comp.Exit( );
Destroy( comp );
}
}
i = v.Count;
while( --i >= 0 )
{
comp = ( StateProcess ) GetComponent( v[ i ] );
if( comp == null )
gameObject.AddComponent( v[ i ] );
}
}
}
- StateEnd
Code : Tout sélectionner
using UnityEngine;
using System.Collections;
public class StateEnd : StateProcess {
void OnGUI()
{
if (GUI.Button(new Rect(50, 50, 200, 80), "MENU"))
{
StateManager.instance.state = StateManager.State.MENU;
}
}
}
Code : Tout sélectionner
using UnityEngine;
using System.Collections;
public class StateGame : StateProcess {
void OnGUI()
{
if (GUI.Button(new Rect(50, 50, 200, 80), "END"))
{
StateManager.instance.state = StateManager.State.END;
}
}
}
Code : Tout sélectionner
using UnityEngine;
using System.Collections;
public class StateMenu : StateProcess {
void OnGUI()
{
if (GUI.Button(new Rect(50, 50, 200, 80), "Play"))
{
StateManager.instance.state = StateManager.State.GAME;
}
if (GUI.Button(new Rect(50, 150, 200, 80), "Quit"))
{
StateManager.instance.state = StateManager.State.END;
}
}
}
Code : Tout sélectionner
using UnityEngine;
using System.Collections;
public class StateFooter : StateProcess {
void OnGUI()
{
if (GUI.Button(new Rect(50, 500, 200, 80), "FOOTER"))
{
print( "footer" );
}
}
}