现在用FSM进行游戏场景管理还是比较多,主要是场景的进入退出处理任务和逻辑起比较清晰简单,当然现在一般xlua的hotfix来做热补丁的场景处理也多起来(以便于后期有副本的场景加载更新)。本篇(公司游戏没加场景动态更新前的)只介绍用c#处理的场景管理(后面有时间加一篇动态的更新的场景管理):
1.FSM场景管理 代码架构图:
2 代码块搭建说明:
(1)定义 接口Istate。
(2).定义所有场景状态机的父类ScenceState,并且继承接口Istate。
(3).定义条件转换类TransationPipe。
(4).定义录场景LoaginSatae,场景控制器LonginControll,场景显示接口LonginPresenter;主场景MainState......;战斗场景BattleState......。
(5).定义场景管理器SceneStateManger;并且创建登录场景LoaginSatae及相关转出条件;主场景MainState及相关转出条件;战斗场景BattleState及相关转出条件。
(6)定义游戏管理器GameManger,并且创建场景管理器SceneStateManger.调用场景入口。
3 具体代码
(1).接口Istate:
public interface IState
{
//场景进入调用方法
void OnEnter ();
//场景中轮询调用方法
void Tick ();
//场景退出调用方法
void OnExit();
}
(2).类ScenceState:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
public class SceneState :IState
{
/// <summary>
/// 这个状态的持有者
/// </summary>
protected SceneStateManager Owner;
/// <summary>
/// 这个状态的名字
/// </summary>
public string name;
private List<TransationPipe> pipelines = new List<TransationPipe>();
/// <summary>
/// 关闭无参数的构造函数
/// </summary>
private SceneState (){}
//设置状态的持有者(场景管理器)
public SceneState(string _name , SceneStateManager myOwner)
{
name = _name;
Owner = myOwner;
}
//场景进入调用方法
public virtual void OnEnter()
{
}
/// <summary>
/// 转移条件检测
/// </summary>
/// <returns>要跳转到哪里去.</returns>
public string CheckTransation()
{
for(int i = 0; i < pipelines.Count; i++)
{
if (pipelines [i].condition != null)
{
if (pipelines [i].condition ())
{
return pipelines [i].target;
}
}
}
return GameSceneNames.NO_OUPT;
}
public virtual void Tick()
{
}
public virtual void OnExit()
{
Debug.Log(this.name + " :场景退出了");
}
//添加转移条件
public void AddPipe(TransationPipe tp)
{
if (pipelines.Contains(tp)) Debug.Log("已经有了此条件");
else
pipelines.Add(tp);
}
}
(3).场景转移条件类TransationPipe:
public class TransationPipe
{
public delegate bool Check();
//获取转出条件的方法
public Check condition;
//场景转出目的场景的名字
public string target;
private TransationPipe(){}
public TransationPipe(string des , Check _condition)
{
target = des;
condition = _condition;
}
}
(4.1).登录场景状态机LonginState:
using UnityEngine;
using System.Collections;
public class LonginState : SceneState
{
public LonginState (string name, SceneStateManager manager) : base (name ,manager){ }
//场景需求的UI和模型对象引用(最好动态加载)
LoginPresenter presenter;
//场景进入调用
public override void OnEnter ()
{
//设置场景条件为退出状态
SceneCtrl.Instance.isSureExit = true;
presenter = GameObject.Find("Canvas").GetComponent<LoginPresenter>();
//登录场景中的场景控制器介入
LoginPanelController.Instance.Initalize (presenter);
//添加相关监听(是否获取地块信息成功)。(mvc)并且在LoginPanelController中处理相关获取的
信息并且调用Presenter显示
GameManager.Instance.gameEventDispatcher.AddEventListener(GameEventType.BlockInfoSuccess, LoginPanelController.Instance.OnGetBlockInfoSuccess);
//添加相关监听(是否获取地块信息失败)
GameManager.Instance.gameEventDispatcher.AddEventListener(GameEventType.BlockInfoFailure, LoginPanelController.Instance.OnGetBlockInfoFailure);
//添加相关监听(是否获取天气信息成功)
GameManager.Instance.gameEventDispatcher.AddEventListener(GameEventType.WeatherInfoSuccess, LoginPanelController.Instance.OnGetWetherInfoSuccess);
//添加相关监听(是否获取天气信息失败)
GameManager.Instance.gameEventDispatcher.AddEventListener(GameEventType.WeatherInfoFailure, LoginPanelController.Instance.OnGetWetherInfoFailure);
//添加相关监听(是否获取登录信息成功)登录
GameManager.Instance.gameEventDispatcher.AddEventListener(GameEventType.LoginSuccess, LoginPanelController.Instance.OnPlayerLoginSuccess);
GameManager.Instance.gameEventDispatcher.AddEventListener(GameEventType.LoginFailure, LoginPanelController.Instance.OnPlayerLoginFailure);
//开启音乐
AudioManager.Instance.PlayBGM("login");
//退出到主场景的条件开启可设置
SceneCtrl.Instance.isExitMainScene = false;
GameManager.Instance.socketManager.ExitConectAgin();
SceneCtrl.Instance.loginSuccess = false;
//登录场景通知按钮添加监听
presenter.noticeBtn.onClick.AddListener(LoginPanelController.Instance.OpenNotice);
GameManager.Instance.gameInstance.RandomEventContainer.Clear ();
}
public override void Tick ()
{
//计算时间
LoginPanelController.Instance.TimeTick();
}
//场景退出
public override void OnExit ()
{
//移除相关监听
GameManager.Instance.gameEventDispatcher.RemoveEventListener (GameEventType.LoginSuccess, LoginPanelController.Instance.OnPlayerLoginSuccess);
GameManager.Instance.gameEventDispatcher.RemoveEventListener (GameEventType.LoginFailure, LoginPanelController.Instance.OnPlayerLoginFailure);
GameManager.Instance.gameEventDispatcher.RemoveEventListener(GameEventTy