GameFramework使⽤教程
今年开始接触这个框架,最开始技术选型的时候是准备使⽤这个框架进⾏弱联⽹⼩游戏的开发,做⼀些休闲⼩游戏的开发。由于⼀些原因项⽬在demo阶段告⼀段落,算起来使⽤这个框架⼀共是4个⽉左右的时间。不知道下⼀个项⽬还会不会采⽤这个框架,利⽤缓冲时间来整理⼀下技术以及⾃⼰在项⽬中的收获。
⼀.框架介绍:
Game Framework 是⼀个基于 Unity 引擎的游戏框架,主要对游戏开发过程中常⽤模块进⾏了封装,很⼤程度地规范开发过程、加快开发速度并保证产品质量。
具体的接⼊使⽤细节在官⽅⽹站都可以进⾏查阅,这⾥说⼀些常见的注意点:
1.在E神的github可以看到这个框架是分了⼀下层的,Framework是可以脱离unity单独使⽤的,在unity中的使⽤需要结合UnityGameFramework,Runtime中的代码是与Mono紧密结合的。在UnityGameFramework中prefabs⽂件夹中可以到⼀个GameFramework的预制体,这个预制体可以看成⼀个基础组件,放在初始场景中贯穿整个游戏。
2.GF通过组件控制各个模块,GameEntry是整个游戏的⼊⼝,负责初始化框架的基础组件。
private static void InitBuiltinComponents()
{
Base = UnityGameFramework.Runtime.GameEntry.GetComponent<BaseComponent>();
Config = UnityGameFramework.Runtime.GameEntry.GetComponent<ConfigComponent>();
DataNode = UnityGameFramework.Runtime.GameEntry.GetComponent<DataNodeComponent>();
DataTable = UnityGameFramework.Runtime.GameEntry.GetComponent<DataTableComponent>();
Debugger = UnityGameFramework.Runtime.GameEntry.GetComponent<DebuggerComponent>();
Download = UnityGameFramework.Runtime.GameEntry.GetComponent<DownloadComponent>();
Entity = UnityGameFramework.Runtime.GameEntry.GetComponent<EntityComponent>();
Event = UnityGameFramework.Runtime.GameEntry.GetComponent<EventComponent>();
Fsm = UnityGameFramework.Runtime.GameEntry.GetComponent<FsmComponent>();
Localization = UnityGameFramework.Runtime.GameEntry.GetComponent<LocalizationComponent>();
Network = UnityGameFramework.Runtime.GameEntry.GetComponent<NetworkComponent>();
ObjectPool = UnityGameFramework.Runtime.GameEntry.GetComponent<ObjectPoolComponent>();
Procedure = UnityGameFramework.Runtime.GameEntry.GetComponent<ProcedureComponent>();
Resource = UnityGameFramework.Runtime.GameEntry.GetComponent<ResourceComponent>();
Scene = UnityGameFramework.Runtime.GameEntry.GetComponent<SceneComponent>();
Setting = UnityGameFramework.Runtime.GameEntry.GetComponent<SettingComponent>();
Sound = UnityGameFramework.Runtime.GameEntry.GetComponent<SoundComponent>();
UI = UnityGameFramework.Runtime.GameEntry.GetComponent<UIComponent>();
WebRequest = UnityGameFramework.Runtime.GameEntry.GetComponent<WebRequestComponent>();
CD = UnityGameFramework.Runtime.GameEntry.GetComponent<CDComponent>();
Timer = UnityGameFramework.Runtime.GameEntry.GetComponent<TimerComponent>();
SimpleEvent = UnityGameFramework.Runtime.GameEntry.GetComponent<SimpleEventComponent>();
}
下⾯CD Timer SimpleEvent 是根据项⽬需要添加的,其他组件的功能在官⽹的介绍中都可以了解到,
基本上很多组件单独拎出来解释都可以作为⼀篇教程,后⾯也会介绍⾃⼰使⽤的⽐较多的组件。
3.这个框架是通过流程组件来设置游戏的当前的⼀个状态。
⾸先选择初始流程,⼀般会在初始流程中初始化config的信息等,每个流程实质都是⼀个状态机,都有
OnInit(),OnEnter(),OnUpdata(),OnLeave(),⽅法,在进⼊流程的时候做⼀些初始化⽅法。
public override void OnEnter(ProcedureOwner procedureOwner)
{
base.OnEnter(procedureOwner);
/
unity 教程/ 构建信息:发布版本时,把⼀些数据以 Json 的格式写⼊ Assets/GameMain/,供游戏逻辑读取。
//GameEntry.BuiltinData.InitBuildInfo();
// 语⾔配置:设置当前使⽤的语⾔,如果不设置,则默认使⽤操作系统语⾔。
InitLanguageSettings();
// 变体配置:根据使⽤的语⾔,通知底层加载对应的资源变体。
InitCurrentVariant();
// 画质配置:根据检测到的硬件信息 Assets/Main/Configs/DeviceModelConfig 和⽤户配置数据,设置即将使⽤的画质选项。
InitQualitySettings();
// 声⾳配置:根据⽤户配置数据,设置即将使⽤的声⾳选项。
InitSoundSettings();
// 默认字典:加载默认字典⽂件 Assets/GameMain/l。
// 此字典⽂件记录了资源更新前使⽤的各种语⾔的字符串,会随 App ⼀起发布,故不可更新。
//GameEntry.BuiltinData.InitDefaultDictionary();
}
切换流程直接调⽤ChangeState()⽅法,我们项⽬在launch之后会进到⼀个热更流程,检查版本更新,进⾏资源热更,然后在进⼊到load 流程开始正式的load资源,然后在进⼊到main流程和game流程等开始游戏。在load流程中有⼀个坑,在编辑器模式下直接调PreloadResources()⽅法就可以了,但是打出真机包这⾥要改为GameEntry.Resource.InitResources(OnInitResourcesComplete)然后在OnInitResourcesComplete的回调中去调PreloadResources().
4.这个框架很多数据是直接采⽤配表的⽅式,在load的DatatableNames中写⼊配好的表的名称,在编辑器有⼀个GenerateDataTables可以直接将表数据转化成vs的数据格式,可以⾃⼰定义好数据类接收这些数据,例如我们项⽬的部分⾓⾊数据按如下⽅式获取:
public RoleData(int entityId, int typeId) : base(entityId, typeId)
{
IDataTable<DRRole> dtRole = GameEntry.DataTable.GetDataTable<DRRole>();
DRRole dtRoleData = dtRole.GetDataRow(typeId);
if (dtRoleData == null)
{
return;
}
assetPath = dtRoleData.AssetPath;
MaxHp = dtRoleData.MaxHP;
currentHp = dtRoleData.MaxHP;
Defence = dtRoleData.Defense;
lockDistance = dtRoleData.LockDistane;
MoveSpeed = dtRoleData.MoveSpeed;
m_RotateSpeed = dtRoleData.RotateSpeed;
}
⼆.框架组件
框架组件的调⽤⽐较⽅便,因为在GameEntry中已经初始化了组件,并且组件是⼀直存在项⽬中的,调⽤组件只需要GameEntry点出组件名称就可以调⽤组件的⽅法了。框架组件这⾥我就按在我们项⽬中的使⽤顺序介绍⼀些⽐较重要的吧。
1.UI组件:这⾥需要关注的⼀般就是UIGroups,根据⾃⼰的项⽬设置好UI分层。我们项⽬暂时是分的4层,最底层是放类似⾎条UI等,中间层放⼀些选择界⾯,顶层放摇杆界⾯,属性介绍界⾯等;最顶层算是弹出框之类的。指定好depth就ok了。然后在InstanceRoot中指定Canvas,配好表以后就可以使⽤了。打开⾯板调⽤的是OpenUIForm传⼊配好的id就可以打开⾯板了,关于如何读取表中数据,以及如何去进⾏显⽰可以查看
public static int? OpenUIForm(this UIComponent uiComponent, UIFormId uiFormId, object userData = null)
{
return uiComponent.OpenUIForm((int)uiFormId, userData);
}
public static int? OpenUIForm(this UIComponent uiComponent, int uiFormId, object userData = null)
{
IDataTable<DRUIForm> dtUIForm = GameEntry.DataTable.GetDataTable<DRUIForm>();
DRUIForm drUIForm = dtUIForm.GetDataRow(uiFormId);
if (drUIForm == null)
{
Log.Warning("Can not load UI form '{0}' from data table.", uiFormId.ToString());
return null;
}
string assetName = AssetUtility.GetUIFormAsset(drUIForm.AssetName);
if (!drUIForm.AllowMultiInstance)
{
if (uiComponent.IsLoadingUIForm(assetName))
{
return null;
}
if (uiComponent.HasUIForm(assetName))
{
return null;
}
}
return uiComponent.OpenUIForm(assetName, drUIForm.UIGroupName, Constant.AssetPriority.UIFormAsset, drUIForm.PauseCoveredUIForm, userData }
最后跳进OpenUIForm中查看可以在UIManager中到打开界⾯的具体操作:
/// <summary>
/// 打开界⾯。
/// </summary>
/// <param name="uiFormAssetName">界⾯资源名称。</param>
/// <param name="uiGroupName">界⾯组名称。</param>
/// <param name="priority">加载界⾯资源的优先级。</param>
/// <param name="pauseCoveredUIForm">是否暂停被覆盖的界⾯。</param>
/// <param name="userData">⽤户⾃定义数据。</param>
/// <returns>界⾯的序列编号。</returns>
public int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority, bool pauseCoveredUIForm, object userData)
{
if (m_ResourceManager == null)
{
throw new GameFrameworkException("You must set resource manager first.");
}
if (m_UIFormHelper == null)
{
throw new GameFrameworkException("You must set UI form helper first.");
}
if (string.IsNullOrEmpty(uiFormAssetName))
{
throw new GameFrameworkException("UI form asset name is invalid.");
}
if (string.IsNullOrEmpty(uiGroupName))
{
throw new GameFrameworkException("UI group name is invalid.");
}
UIGroup uiGroup = (UIGroup)GetUIGroup(uiGroupName);
if (uiGroup == null)
{
throw new GameFrameworkException(Utility.Text.Format("UI group '{0}' is not exist.", uiGroupName));
}
int serialId = ++m_Serial;
UIFormInstanceObject uiFormInstanceObject = m_InstancePool.Spawn(uiFormAssetName);
if (uiFormInstanceObject == null)
{
m_UIFormsBeingLoaded.Add(serialId, uiFormAssetName);
m_ResourceManager.LoadAsset(uiFormAssetName, priority, m_LoadAssetCallbacks, OpenUIFormInfo.Create(serialId, uiGroup, pauseCoveredUIForm }
else
{
InternalOpenUIForm(serialId, uiFormAssetName, uiGroup, uiFormInstanceObject.Target, pauseCoveredUIForm, false, 0f, userData);
}
return serialId;
}
因为这个项⽬暂停的⽐较早,UI界⾯这⼀块其实基本是还没开始做的,可能还有很多可以学习的地⽅,
以后涉及到再慢慢总结。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论