QFramework之架构使用


前言

QF架构是在该框架不断迭代中出现的,不同与其他的架构,她的优点是将各个模块分层管理并且提供封装好的工具方便实现以前写起来很麻烦的功能,写起来层次分明。官方讲的也很好,想要李姐原理可以去看教程+源码。
本篇是我李姐的使用方式,不涉及讲解。


一、准备

文件夹管理如下图:(如果游戏当中有功能独立于该游戏的小游戏【如2077当中加入了街机小游戏】,建议再建立一个类似的文件夹)
在这里插入图片描述
附:Model-数据,Command-命令,System-系统,Storage-存储,Game-游戏逻辑,GameArchitecture架构【注册模块】,GameMgr-游戏管理【主要用于初始化】

Architecture代码

//游戏架构:用来注册模块
namespace QFramework.Game
{
    public class Game : Architecture<Game>
    {
        protected override void Init()
        {
            //注册各个模块
            //储存
            this.RegisterUtility<IStorage>(new Storage());
        }
    }
}

储存(简单用LitJson写了一个,想要更全面更系统化可以参考另一篇文章unity强力配置插件

using UnityEngine;
using System.IO;
using LitJson;
//存储类
namespace QFramework.Game
{
    public interface IStorage : IUtility
    {
        void Save<T>(string file,T data);
        T Load<T>(string fileName);
    }
    public class Storage : IStorage
    {
        public void Save<T>(string name, T data)
        {
            string filePath = Application.streamingAssetsPath + "/" + name +".json";
            //利用JsonMapper将save对象转换为Json格式的字符串
            string saveJsonStr = JsonMapper.ToJson(data);
            //将这个字符串写入到文件中
            //创建一个StreamWriter,并将字符串写入文件中
            StreamWriter sw = new StreamWriter(filePath);
            sw.Write(saveJsonStr);
            //关闭StreamWriter
            sw.Close();
        }

        public T Load<T>(string name)
        {
            T t = default;
            string filePath = Application.streamingAssetsPath + "/" + name + ".json";
            if (File.Exists(filePath))
            {
                //创建一个StreamReader,用来读取流
                StreamReader sr = new StreamReader(filePath);
                //将读取到的流赋值给jsonStr
                string jsonStr = sr.ReadToEnd();
                //关闭
                sr.Close();

                //将字符串jsonStr转换为Save对象
                t = JsonMapper.ToObject<T>(jsonStr);
            }
            else
            {
                Debug.LogWarning("存档文件不存在");
            }
            return t;
        }

    }
    
}

GameMgr代码

//初始化游戏
namespace QFramework.Game
{
    public class GameMgr : MonoBehaviour
    {
	void Start()
	{
            ResKit.Init();
            // UIKit 的分辨率设置
            //UIKit.Root.SetResolution(1920, 1080, 1);
        }
    }
}

二、使用

我们假设需要快速实现一个Demo给老板看,效果是玩家在场景里来回走,地上随机生成奖励,碰到一个奖励就加分;加分需要保存下来,并且到一定分数触发成就系统,弹出来成就完成。

1、第一步:创建Model数据

玩家的数据那就起名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());
            //储存
            this.RegisterUtility<IStorage>(new Storage());
        }
    }
}

2、创建接触命令TriggerCommand

接触后分数增加

namespace QFramework.Game
{
    public class TriggerCommand : AbstractCommand
    {
        protected override void OnExecute()
        {
            var model = this.GetModel<IPlayerModel>();
            model.Score.Value++;
        }
    }

}

3、创建Player玩家脚本

创建一个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<TriggerCommand>();

4、创建UI,联动数据

创建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;
        }
    }
}

5、初始化游戏

默认初始打开GamePanel的UI

//初始化游戏
namespace QFramework.Game
{
    public class GameMgr : MonoBehaviour
    {
	void Start()
	{
            ResKit.Init();
            // UIKit 的分辨率设置
            //UIKit.Root.SetResolution(1920, 1080, 1);
            UIKit.OpenPanel<GamePanel>();
        }
    }
}

6、额外系统添加(成就系统)

成就系统初步完成,到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架构的基本使用,这是我李姐的使用步骤,具体有什么问题请留言。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值