经过前几节的学习,估计大家对Procedure与Fsm已经有了一定的了解,下面我们对Procedure进行初步的深入(说的有点大,就是看源码)
首先有几个问题是我比较困惑的:
1. Game Framework -> Procedure ->Procedure Component 下的各个继承自ProcedureBase的子类,是如何生成的?
跟随镜头,首先参观一下ProcedureComponent,没错,这就是我们在IDE中看到的那个脚本
[SerializeField]
private string[] m_AvailableProcedureTypeNames = null;
[SerializeField]
private string m_EntranceProcedureTypeName = null;这两个参数,从字面意思就可以看出,m_AvailableProcedureTypeNames 为当前有效的Procedure,m_EntranceProcedureTypeName 也就是我们运行游戏第一个进入的Procedure。
然后本人看了一遍代码后,发现并没有实际能够取出所有Procedure的子类的东东,这是为何?最大函数也就是Start,这个我们后续再讲。(全局搜索吧!!m_AvailableProcedureTypeNames )
发现了ProcedureComponentInspector这个代码里竟然出现了!!(什么鬼?)
主意两个函数:
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{ m_AvailableProcedureTypeNames = serializedObject.FindProperty("m_AvailableProcedureTypeNames");
m_EntranceProcedureTypeName = serializedObject.FindProperty("m_EntranceProcedureTypeName");
RefreshTypeNames();}// 使用 serializedObject.FindProperty 方法 (这就能找到了?我不信,咋就那么智能了?)
// 获取 ProcedureComponent 中定义的 m_AvailableProcedureTypeNames
只通过这个方法还不足以,然后发现声明类的头部有一行代码:[CustomEditor(typeof(ProcedureComponent))]
这个就能找到 ProcedureComponent 中 对应的变量
继续看代码:
private void RefreshTypeNames()
{
m_ProcedureTypeNames = Type.GetTypeNames(typeof(ProcedureBase));
ReadAvailableProcedureTypeNames();
int oldCount = m_CurrentAvailableProcedureTypeNames.Count;
m_CurrentAvailableProcedureTypeNames = m_CurrentAvailableProcedureTypeNames.Where(x => m_ProcedureTypeNames.Contains(x)).ToList();
if (m_CurrentAvailableProcedureTypeNames.Count != oldCount)
{
WriteAvailableProcedureTypeNames();
}
else if (!string.IsNullOrEmpty(m_EntranceProcedureTypeName.stringValue))
{
m_EntranceProcedureIndex = m_CurrentAvailableProcedureTypeNames.IndexOf(m_EntranceProcedureTypeName.stringValue);
if (m_EntranceProcedureIndex < 0)
{
m_EntranceProcedureTypeName.stringValue = null;
}
}
serializedObject.ApplyModifiedProperties();
}通过 m_ProcedureTypeNames = Type.GetTypeNames(typeof(ProcedureBase)); 取出了所有继承自ProcedureBase的子类,也就是我们定义的那些进程。(原来在这里!对就在这里哇!)
2. 先执行那个Procedure,以及在执行过程中处理了哪些动动?
回到ProcedureComponent代码中,继续看Start (终于到这里了哇!!)
private IEnumerator Start()
{
ProcedureBase[] procedures = new ProcedureBase[m_AvailableProcedureTypeNames.Length];
for (int i = 0; i < m_AvailableProcedureTypeNames.Length; i++)
{
Type procedureType = Utility.Assembly.GetType(m_AvailableProcedureTypeNames[i]);
if (procedureType == null)
{
Log.Error("Can not find procedure type '{0}'.", m_AvailableProcedureTypeNames[i]);
yield break;
}
procedures[i] = (ProcedureBase)Activator.CreateInstance(procedureType);
if (procedures[i] == null)
{
Log.Error("Can not create procedure instance '{0}'.", m_AvailableProcedureTypeNames[i]);
yield break;
}
if (m_EntranceProcedureTypeName == m_AvailableProcedureTypeNames[i])
{
m_EntranceProcedure = procedures[i];
}
}
if (m_EntranceProcedure == null)
{
Log.Error("Entrance procedure is invalid.");
yield break;
}
m_ProcedureManager.Initialize(GameFrameworkEntry.GetModule<IFsmManager>(), procedures);
yield return new WaitForEndOfFrame();
m_ProcedureManager.StartProcedure(m_EntranceProcedure.GetType());
}话不多说,直接看最后三行代码:
发现了初始化的地方 m_ProcedureManager.Initialize 和 m_ProcedureManager.StartProcedure 执行进程的地方!
(终于找到你,还好我没放弃!!)
这就得看GameFrameWork的源码了(打开吧!骚年们!)
public void Initialize(IFsmManager fsmManager, params ProcedureBase[] procedures)
{
if (fsmManager == null)
{
throw new GameFrameworkException("FSM manager is invalid.");
}
m_FsmManager = fsmManager;
m_ProcedureFsm = m_FsmManager.CreateFsm(this, procedures);
}接着就是CreateFsm(终于创建状态机了哇)
public IFsm<T> CreateFsm<T>(string name, T owner, params FsmState<T>[] states) where T : class
{
if (HasFsm<T>(name))
{
throw new GameFrameworkException(string.Format("Already exist FSM '{0}'.", Utility.Text.GetFullName<T>(name)));
}
Fsm<T> fsm = new Fsm<T>(name, owner, states);
m_Fsms.Add(Utility.Text.GetFullName<T>(name), fsm);
return fsm;
}先到这吧!再往下降就涉及到了另外一个小的姿势点
接着的就是这个东东了:m_ProcedureManager.StartProcedure
public void StartProcedure(Type procedureType)
{
if (m_ProcedureFsm == null)
{
throw new GameFrameworkException("You must initialize procedure first.");
}
m_ProcedureFsm.Start(procedureType);
}继续看到了Fsm.cs文件
/// <summary>
/// 开始有限状态机。
/// </summary>
/// <typeparam name="TState">要开始的有限状态机状态类型。</typeparam>
public void Start<TState>() where TState : FsmState<T>
{
if (IsRunning)
{
throw new GameFrameworkException("FSM is running, can not start again.");
}
FsmState<T> state = GetState<TState>();
if (state == null)
{
throw new GameFrameworkException(string.Format("FSM '{0}' can not start state '{1}' which is not exist.", Utility.Text.GetFullName<T>(Name), typeof(TState).FullName));
}
m_CurrentStateTime = 0f;
m_CurrentState = state;
m_CurrentState.OnEnter(this);
}到此为止,就看到了状态机的是如何启动的了,现在是不是清楚一些了?
(先看这两个吧,能说清楚就不错了)
本文探讨了GameFramework中Procedure的实现原理,包括ProcedureComponent如何生成Procedure子类实例,以及执行流程。通过分析源码,揭示了m_AvailableProcedureTypeNames和m_EntranceProcedureTypeName的作用,并解释了如何获取所有继承自ProcedureBase的子类。同时,文章还介绍了Procedure的执行顺序,重点讲解了Start方法中m_ProcedureManager的Initialize和StartProcedure在启动状态机过程中的作用。
2003

被折叠的 条评论
为什么被折叠?



