UGF游戏框架实例开发教程—FlappyBird(五)菜单流程的代码编写
在正式开始写代码之前,我们需要先将命名空间给重命名一下
随便找一个Scripts下的文件,修改命名空间为FlappyBird
修改命名空间后,有几个地方需要重新设置
OK,接下来处理流程相关的东西,创建两个类,分别命名为ProcedureMenu和ProcedureMain,代表菜单流程与主流程,作为流程类,需要继承ProcedureBase
namespace FlappyBird
{
/// <summary>
/// 菜单流程
/// </summary>
public class ProcedureMenu : ProcedureBase
{
}
}
namespace FlappyBird
{
/// <summary>
/// 主流程
/// </summary>
public class ProcedureMain : ProcedureBase
{
}
}
然后找到ProcedureComponent所在的游戏物体,勾选所有流程类,并设置入口流程
打开ProcedureChangeScene(这个流程负责切换场景的处理),找到TODO的地方,编写如下代码
protected override void OnUpdate(ProcedureOwner procedureOwner, float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
if (!m_IsChangeSceneComplete)
{
return;
}
//TODO:在这里根据切换到的场景编号进行对应的流程切换
switch (gotoSceneId)
{
case 1:
ChangeState<ProcedureMenu>(procedureOwner);
break;
case 2:
ChangeState<ProcedureMain>(procedureOwner);
break;
default:
break;
}
}
接着打开ProcedurePreload(负责处理预加载的流程),找到TODO的地方,编写如下代码
protected override void OnUpdate(ProcedureOwner procedureOwner, float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
IEnumerator<bool> iter = m_LoadedFlag.Values.GetEnumerator();
while (iter.MoveNext())
{
if (!iter.Current)
{
return;
}
}
// TODO:这里开始,切换到你的场景,场景编号可在DefaultConfig中配置
procedureOwner.SetData<VarInt>(Constant.ProcedureData.NextSceneId, GameEntry.Config.GetInt("Scene.Menu"));
ChangeState<ProcedureChangeScene>(procedureOwner);
}
这些TODO的地方处理完成后,可以开始编写菜单流程的相关代码了
using UnityGameFramework.Runtime;
using GameFramework.Procedure;
using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;
namespace FlappyBird
{
/// <summary>
/// 菜单流程
/// </summary>
public class ProcedureMenu : ProcedureBase
{
public bool IsStartGame { get; set; }
protected override void OnEnter(ProcedureOwner procedureOwner)
{
base.OnEnter(procedureOwner);
IsStartGame = false;
//打开UI界面
GameEntry.UI.OpenUIForm(UIFormId.MenuForm, this);
}
protected override void OnUpdate(ProcedureOwner procedureOwner, float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
if (IsStartGame)
{
//切换到主要场景
procedureOwner.SetData<VarInt>(Constant.ProcedureData.NextSceneId, GameEntry.Config.GetInt("Scene.Main"));
ChangeState<ProcedureChangeScene>(procedureOwner);
}
}
}
}
这里的OnEnter和OnUpdate是流程的生命周期方法,在UGF中,流程是一种特殊的状态,受状态机管理,所以也有相应的生命周期方法
在上面那段代码中,我们打开了菜单UI,所以我们接下来需要编写菜单UI的相关代码
先去UIComponent里添加一个UIGroup,并且指定InstanceRoot
把MenuForm拖到UI Form Instances下面,然后新建一个MenuForm脚本,继承UGuiForm,编写如下代码
/// <summary>
/// 菜单界面脚本
/// </summary>
public class MenuForm : UGuiForm
{
/// <summary>
/// 菜单流程
/// </summary>
private ProcedureMenu m_ProcedureMenu = null;
protected override void OnOpen(object userData)
{
base.OnOpen(userData);
m_ProcedureMenu = (ProcedureMenu)userData;
}
protected override void OnClose(object userData)
{
m_ProcedureMenu = null;
base.OnClose(userData);
}
public void OnStartButtonClick()
{
m_ProcedureMenu.IsStartGame = true;
}
public void OnSettingButtonClick()
{
GameEntry.UI.OpenUIForm(UIFormId.SettingForm);
}
把这个脚本拖到MenuForm上面,然后把MenuForm下的两个按钮的Button组件删除,添加CommonButton脚本,在OnClick委托中注册MenuForm的PlaySound方法,参数输入1
然后分别将MenuForm里的按钮监听方法注册到对应的按钮上
应用预制体变更,完善菜单流程类的代码
using UnityGameFramework.Runtime;
using GameFramework.Procedure;
using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;
using GameFramework.Event;
namespace FlappyBird
{
/// <summary>
/// 菜单流程
/// </summary>
public class ProcedureMenu : ProcedureBase
{
public bool IsStartGame { get; set; }
/// <summary>
/// 菜单界面脚本
/// </summary>
private MenuForm m_MenuForm = null;
protected override void OnEnter(ProcedureOwner procedureOwner)
{
base.OnEnter(procedureOwner);
IsStartGame = false;
//订阅UI打开成功事件
GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OnOpenUIFormSuccess);
//打开UI界面
GameEntry.UI.OpenUIForm(UIFormId.MenuForm, this);
}
protected override void OnUpdate(ProcedureOwner procedureOwner, float elapseSeconds, float realElapseSeconds)
{
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
if (IsStartGame)
{
//切换到主场景
procedureOwner.SetData<VarInt>(Constant.ProcedureData.NextSceneId, GameEntry.Config.GetInt("Scene.Main"));
ChangeState<ProcedureChangeScene>(procedureOwner);
}
}
protected override void OnLeave(ProcedureOwner procedureOwner, bool isShutdown)
{
base.OnLeave(procedureOwner, isShutdown);
if (m_MenuForm != null)
{
m_MenuForm.Close(isShutdown);
m_MenuForm = null;
}
//取消订阅UI打开成功事件
GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId, OnOpenUIFormSuccess);
}
private void OnOpenUIFormSuccess(object sender, GameEventArgs e)
{
OpenUIFormSuccessEventArgs ne = (OpenUIFormSuccessEventArgs)e;
if (ne.UserData != this)
{
return;
}
m_MenuForm = (MenuForm)ne.UIForm.Logic;
}
}
}
我们刚才在MenuForm里编写了打开设置界面的代码,因此我们也需要来编写设置面板的脚本
创建一个SettingForm脚本拖到对应UI物体上,为其编写如下代码
/// <summary>
/// 设置界面脚本
/// </summary>
public class SettingForm : UGuiForm
{
public void OnCloseButtonClick()
{
Close();
}
public void OnMusicSettingValueChange(float value)
{
GameEntry.Sound.SetVolume("Music", value);
}
public void OnSoundSettingValueChange(float value)
{
GameEntry.Sound.SetVolume("Sound", value);
GameEntry.Sound.SetVolume("UISound", value);
}
}
在这个脚本里监听了按钮的点击与两个Slider的变化,因此我们也需要将这三个方法注册进去
应用预制体变更,现在我们可以点击运行来看看项目能不能跑起来了
点击设置,调整音乐大小
点击开始按钮,进入Main场景
虽然没有做UI,但已经可以听到背景音乐了