目录
工程资源
https://github.com/AMikeW/BStandShaderResources
*** 资源使用注意事项 ***
一个是场景,一个是Log日志类所需的脚本定义标记启动才能看到打印日志。当然你用UnityEngine.Debug是没有问题的。
一、加载Excel配置表的txt文件(读写)
直接另存为.txt文本文件,或者直接改后缀为.txt 转为文本文件
放置到Unity的目录下,不一定是要在Resources特殊目录,这里只是测试随便放的。
using GameFramework.DataTable;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityGameFramework.Runtime;
public class TestConfig : IDataRow
{
public int Id { get; protected set; }
public string Name { get; protected set; }
public int Atk { get; protected set; }
public bool ParseDataRow(string dataRowString, object userData)
{
try
{
string[] text = dataRowString.Split('\t');
int index = 0;
index++;
Id = int.Parse(text[index++]);
Name = text[index++];
Atk = int.Parse(text[index++]);
}
catch (Exception e)
{
Log.Error("TestConfig ParseDataRow Error:" + e.ToString());
return false;
}
return true;
}
public bool ParseDataRow(byte[] dataRowBytes, int startIndex, int length, object userData)
{
throw new System.NotImplementedException();
}
public override string ToString()
{
return string.Format("Id:{0},Name:{1},Atk:{2}", Id, Name, Atk);
}
}
private void StartLoadConfig()
{
//监听加载配置表成功事件
EventComponent Event = GameEntry.GetComponent<EventComponent>();
Event.Subscribe(LoadDataTableSuccessEventArgs.EventId, OnDataLoadedSuccess);
// 获取框架数据表组件
DataTableComponent dataTableComponent
= UnityGameFramework.Runtime.GameEntry.GetComponent<DataTableComponent>();
IDataTable<TestConfig> dataTable = dataTableComponent.CreateDataTable<TestConfig>();
DataTableBase dataTableBase = dataTable as DataTableBase;
dataTableBase.ReadData("Assets/AssetBundles/Resources/Test.txt");
}
private void OnDataLoadedSuccess(object sender, GameEventArgs e)
{
Log.Error("加载成功:");
DataTableComponent dataTableComponent = GameEntry.GetComponent<DataTableComponent>();
IDataTable<TestConfig> dtScene = dataTableComponent.GetDataTable<TestConfig>();
TestConfig[] allTestConfigs = dtScene.GetAllDataRows();// 所有的行获取为数组
Log.Debug("allTestConfig : " + allTestConfigs.Length);
TestConfig first = dtScene.GetDataRow(1); //获取的是ID为1的TestConfig
if (first != null)
{
Log.Debug("first id = 1:" + first.ToString());
}
else
{
}
//获取所有满足条件的行
TestConfig[] testConfigsIdGreater0s = dtScene.GetDataRows((x) => { return x.Id > 0; });
foreach (var v in testConfigsIdGreater0s)
{
Log.Debug("testConfigsIdGreater0 :" + v.ToString());
}
//获取第一次满足条件的行 返回它
TestConfig testConfigsNameEqualCondition = dtScene.GetDataRow((x) => { return x.Name == "mutou"; });
Log.Debug("testConfigsNameEqualCondition:" + testConfigsNameEqualCondition.ToString());
}
坑点&提示:
①、注意这里的加载路径必须是Assets开头的相对路径。
②、旧版本加载配置表方法是 DataTableComponent.LoadDataTable<T>(string)
二、GameFramework之Procedure流程
如上图所示,进入流程为ProcedureLaunch流程,它是一个继承于ProcedureBase的C#脚本 ,如下:
using GameFramework.Procedure;
using UnityGameFramework.Runtime;
using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;
public class ProcedureLaunch : ProcedureBase
{
protected override void OnEnter(ProcedureOwner procedureOwner)
{
base.OnEnter(procedureOwner);
Log.Debug("初始化!");
SceneComponent scene = UnityGameFramework.Runtime.GameEntry.GetComponent<SceneComponent>();
scene.LoadScene("Assets/Scenes/Menu.unity", this);
ChangeState<ProcedureMenu>(procedureOwner);
}
}
当游戏运行时,会进入初始流程的OnEnter方法,若需要转换到其他Procedure流程,则使用ProcedureBase类的方法ChangeState<T>(ProcedureOwner)进行转到下一个流程,不难发现它就是个状态机而已。有OnEnter自然有OnExit方法,还有其他方法请自行测试。上面方法,还使用到了SceneComponent类对象进行加载场景,它是同步追加加载,即现有场景不会销毁的,加载后如下图所示。SceneComponent类是GameFramework物体下的子物体Scene的脚本Scene(留坑①)。
进入Menu场景并切换到ProcedureMenu流程后(此时并不清楚具体是否加载完毕场景后才进入ProcedureMenu流程,留坑②),进入Menu流程后我打算加载一个面板,并在面板上设置一个按钮用于进入Game场景,并且切换到ProcedureGame流程。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GameFramework;
using GameFramework.Procedure;
using UnityGameFramework.Runtime;
using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;
using GameFramework.Fsm;
using GameFramework.UI;
using GameFramework.Event;
public class ProcedureMenu : ProcedureBase
{
ProcedureOwner procedureOwner;
protected override void OnEnter(ProcedureOwner procedureOwner)
{
base.OnEnter(procedureOwner);
Log.Debug("菜单场景 加载UI");
//GameFramework框架的事件系统
EventComponent Event = GameEntry.GetComponent<EventComponent>();
//EventName是一个枚举,它是用户自定义的枚举,代表事件ID(必须唯一)
Event.Subscribe((int)EventName.GameStart, OnGameStart);
//加载UI并显示UI
UIComponent UI = GameEntry.GetComponent<UIComponent>();
//(按顺序进行出现) 第三个参数优先级priority暂时未发现用途
int id = UI.OpenUIForm("Assets/AssetBundles/Prefab/UIMenu.prefab", "NormalGroup");
this.procedureOwner = procedureOwner;
}
/// <summary>
/// 触发EventName.GameStart事件时的回调方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnGameStart(object sender, GameEventArgs e)
{
ChangeState<ProcedureGame>(procedureOwner);
}
}
UIMenu.prefab挂载一个继承于UIFormLogic的脚本,实现了它自带的一些生命周期方法如OnInit OnOpen等,在按钮按下时会销毁当前Menu场景,同步追加Game场景,并发送ProcedureMenu流程监听的事件类对象(其id为EventName.GameStart),并调用UIComponent的关闭UI方法,进行关闭当前UI。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityGameFramework.Runtime;
public class UIMenu : UIFormLogic
{
private Button button;
private void Awake()
{
}
protected override void OnInit(object userData)
{
base.OnInit(userData);
button = transform.Find("EnterGameBtn").GetComponent<Button>();
}
protected override void OnOpen(object userData)
{
base.OnOpen(userData);
button.onClick.AddListener(EnterGame);
}
protected override void OnClose(bool isShutdown, object userData)
{
base.OnClose(isShutdown, userData);
button.onClick.RemoveAllListeners();
}
protected override void OnRecycle()
{
base.OnRecycle();
button = null;
}
public void EnterGame()
{
SceneComponent scene = GameEntry.GetComponent<SceneComponent>();
卸载所有场景
//string[] loadedSceneAssetNames = scene.GetLoadedSceneAssetNames();
//for (int i = 0; i < loadedSceneAssetNames.Length; i++)
//{
// scene.UnloadScene(loadedSceneAssetNames[i]);
//}
scene.UnloadScene("Assets/Scenes/Menu.unity", this);
scene.LoadScene("Assets/Scenes/Game.unity", this);
EventComponent Event = GameEntry.GetComponent<EventComponent>();
Event.Fire(this, new CommonGameEventArgs((int)EventName.GameStart));
UIComponent UI = GameEntry.GetComponent<UIComponent>();
UI.CloseUIForm(UIForm);//关闭自身
}
}
其中CommonGameEventArgs是一个自定义的事件参数类,取名为公共游戏事件参数类,它允许传入事件ID动态设置自身ID,而不是固定ID,但这也带来了坏处,则是不能够写入太多非公共的方法处理数据等情况。(此例仅做参考,实战还是单独一个ID一个类比较好,模仿GameFramework内置的一些事件参数类即可)
using GameFramework.Event;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CommonGameEventArgs : GameEventArgs
{
private int m_Id;
public override int Id => m_Id;
public CommonGameEventArgs(int id)
{
m_Id = id;
}
public override void Clear()
{
}
}
当点击进入游戏按钮,派发事件后会触发ProcedureMenu类的OnGameStart方法执行跳转到ProcedureGame流程。
ProcedureGame流程进行了加载配置表,并监听内置的加载配置成功事件LoadDataTableSuccessEventArgs.EventId。
using GameFramework.Procedure;
using UnityGameFramework.Runtime;
using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;
using GameFramework.Event;
using GameFramework.DataTable;
public class ProcedureGame : ProcedureBase
{
protected override void OnEnter(ProcedureOwner procedureOwner)
{
base.OnEnter(procedureOwner);
Log.Debug("ProcedureGame 状态进入!");
EventComponent Event = GameEntry.GetComponent<EventComponent>();
Event.Subscribe(LoadDataTableSuccessEventArgs.EventId, OnDataLoadedSuccess);
// 获取框架数据表组件
DataTableComponent dataTableComponent
= UnityGameFramework.Runtime.GameEntry.GetComponent<DataTableComponent>();
IDataTable<TestConfig> dataTable = dataTableComponent.CreateDataTable<TestConfig>();
DataTableBase dataTableBase = dataTable as DataTableBase;
dataTableBase.ReadData("Assets/AssetBundles/Resources/Test.txt");
}
private void OnDataLoadedSuccess(object sender, GameEventArgs e)
{
UIComponent UI = GameEntry.GetComponent<UIComponent>();
int id = UI.OpenUIForm("Assets/AssetBundles/Prefab/UIGame.prefab", "NormalGroup", this);
}
}
UIGame类是一个测试加载出的配置表内容的UI类,如下所示:
using GameFramework.DataTable;
using GameFramework.Event;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityGameFramework.Runtime;
public class UIGame : UIFormLogic
{
Button button;
protected override void OnInit(object userData)
{
base.OnInit(userData);
button = transform.Find("Button").GetComponent<Button>();
}
protected override void OnOpen(object userData)
{
base.OnOpen(userData);
button.onClick.AddListener(OnClick);
}
protected override void OnClose(bool isShutdown, object userData)
{
base.OnClose(isShutdown, userData);
button.onClick.RemoveAllListeners();
}
private void OnClick()
{
//获取配置表TestConfig表
DataTableComponent dataTableComponent = GameEntry.GetComponent<DataTableComponent>();
IDataTable<TestConfig> dtScene = dataTableComponent.GetDataTable<TestConfig>();
TestConfig[] allTestConfigs = dtScene.GetAllDataRows();// 所有的行获取为数组
//注意:Config必须要有一个int名为id的字段
TestConfig first = dtScene.GetDataRow(1); //获取的是ID为1的TestConfig
if (first != null)
{
Log.Debug("first id = 1:" + first.ToString());
}
else
{
}
//获取所有满足条件的行
TestConfig[] testConfigsIdGreater0s = dtScene.GetDataRows((x) => { return x.Id > 0; });
foreach (var v in testConfigsIdGreater0s)
{
Log.Debug("testConfigsIdGreater0 :" + v.ToString());
}
//获取第一次满足条件的行 返回它
TestConfig testConfigsNameEqualCondition = dtScene.GetDataRow((x) => { return x.Name == "mutou"; });
Log.Debug("testConfigsNameEqualCondition:" + testConfigsNameEqualCondition.ToString());
}
}
相关信息截图,以供参考制作对应的prefab、excel等。(其实excel就是加载配置表那个表)