QF架构是在该框架不断迭代中出现的,不同与其他的架构,她的优点是将各个模块分层管理并且提供封装好的工具方便实现以前写起来很麻烦的功能,写起来层次分明。官方讲的也很好,想要李姐原理可以去看教程+源码。
本篇是我李姐的使用方式,不涉及讲解。
文件夹管理如下图:(如果游戏当中有功能独立于该游戏的小游戏【如2077当中加入了街机小游戏】,建议再建立一个类似的文件夹)
附:Model-数据,Command-命令,System-系统,Storage-存储,Game-游戏逻辑,GameArchitecture架构【注册模块】,GameMgr-游戏管理【主要用于初始化】
Architecture代码
//游戏架构:用来注册模块
namespace QFramework.Game
{
public class Game : Architecture<Game>
{
protected override void Init()
{
//注册各个模块
}
}
}
GameMgr代码
//初始化游戏
namespace QFramework.Game
{
public class GameMgr : MonoBehaviour
{
void Start()
{
ResKit.Init();
// UIKit 的分辨率设置
//UIKit.Root.SetResolution(1920, 1080, 1);
}
}
}
我们假设需要快速实现一个Demo给老板看,效果是玩家在场景里来回走,地上随机生成奖励,碰到一个奖励就加分;加分需要保存下来,并且到一定分数触发成就系统,弹出来成就完成。
玩家的数据那就起名PlayerModel,具体属性是分数Score
namespace QFramework.Game
{
public interface IPlayerModel : IModel
{
public BindableProperty<int> Score { get; }
}
public class PlayerModel : AbstractModel, IPlayerModel
{
public BindableProperty<int> Score { get; } = new BindableProperty<int>();
protected override void OnInit()
{
var storage = this.GetUtility<IStorage>();
// 设置初始值(不触发事件)
Score.SetValueWithoutEvent(storage.Load(nameof(Score)));
// 当数据变更时 存储数据
Score.Register(newCount =>
{
storage.Save(nameof(Score), newCount);
});
}
}
}
写完后在架构注册模块
//游戏架构:用来注册模块
namespace QFramework.Game
{
public class Game : Architecture<Game>
{
protected override void Init()
{
//注册各个模块
this.RegisterModel<IPlayerModel>(new PlayerModel());
}
}
}
接触后分数增加
namespace QFramework.Game
{
public class TriggerCommand : AbstractCommand
{
protected override void OnExecute()
{
var model = this.GetModel<IPlayerModel>();
model.Score.Value++;
}
}
}
创建一个3d模型球体(命名为Player),添加刚体并设置Is Kinematic为true,选择球体Alt+V创建脚本;再建几个相同的球(命名为Ball)放到周围加上黄色材质。
namespace QFramework.Game
{
public partial class Player : ViewController
{
private Rigidbody rigidbody;
void Start()
{
rigidbody = GetComponent<Rigidbody>();
}
private void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
、
}
private void OnTriggerEnter(Collider other)
{
if (other.name.StartsWith("Ball")) {
Game.Interface.SendCommand<TriggerCommand>();
other.Hide();
}
}
}
}
核心代码:发送触碰命令Game.Interface.SendCommand
创建QF的GamePanel的UI,其中脚本继承IController用以获得model,将数据和界面绑定。
namespace QFramework.Game
{
public class GamePanelData : UIPanelData
{
}
public partial class GamePanel : UIPanel, IController
{
private IPlayerModel model;
protected override void OnInit(IUIData uiData = null)
{
mData = uiData as GamePanelData ?? new GamePanelData();
model = this.GetModel<IPlayerModel>();
model.Score.RegisterWithInitValue((value) => ScoreText.text = "分数:" + value).UnRegisterWhenGameObjectDestroyed(gameObject);
}
protected override void OnOpen(IUIData uiData = null)
{
}
protected override void OnShow()
{
}
protected override void OnHide()
{
}
protected override void OnClose()
{
}
public IArchitecture GetArchitecture()
{
return Game.Interface;
}
}
}
默认初始打开GamePanel的UI
//初始化游戏
namespace QFramework.Game
{
public class GameMgr : MonoBehaviour
{
void Start()
{
ResKit.Init();
// UIKit 的分辨率设置
//UIKit.Root.SetResolution(1920, 1080, 1);
UIKit.OpenPanel<GamePanel>();
}
}
}
成就系统初步完成,到10就会触发debug。
//成就系统
//成就系统
namespace QFramework.Game
{
public interface IAchievementSystem : ISystem
{
}
public class AchievementSystem : AbstractSystem, IAchievementSystem
{
protected override void OnInit()
{
var model = this.GetModel<IPlayerModel>();
model.Score.Register(value => {
if (value == 10){
Debug.Log("针不戳");
}
else if (value == 2000000) {
Debug.Log("还行吧");
}
});
}
}
}
注册模块
//游戏架构:用来注册模块
namespace QFramework.Game
{
public class Game : Architecture<Game>
{
protected override void Init()
{
//注册各个模块
this.RegisterModel<IPlayerModel>(new PlayerModel());
this.RegisterUtility<IStorage>(new Storage());
this.RegisterSystem<IAchievementSystem>(new AchievementSystem());
}
}
}
但我们发现逻辑上只要到10就会触发,考虑到以后加个红色的球碰到减生命值可能就会来回触发;简单改下,如果成就达成我们就把成就存下来,然后判断一下成就是否是返回默认值0。
//成就系统
namespace QFramework.Game
{
public interface IAchievementSystem : ISystem
{
}
public class AchievementSystem : AbstractSystem, IAchievementSystem
{
protected override void OnInit()
{
var storage = this.GetUtility<IStorage>();
var model = this.GetModel<IPlayerModel>();
model.Score.Register(value => {
if (value == 10 && storage.Load("针不戳") == 0)
{
storage.Save("针不戳", 1);
Debug.Log("针不戳");
}
else if (value == 2000000 && storage.Load("还行吧") == 0) {
storage.Save("还行吧", 1);
Debug.Log("还行吧");
}
});
}
}
}
如果项目有要求,这里还是在Storage那里进行封装成就相关的函数,如下进行删除等操作的扩展。
public void Clear() {
PlayerPrefs.DeleteAll();
}
pubic bool xxx(){
//判断xx
}
QF架构的基本使用,这是我李姐的使用步骤,具体有什么问题请留言。