目录
一、QFramework.Toolkits简介
QFramework.Toolkits 称为 QFramework 工具集,是一套开箱即用的、渐进式的快速开发框架。
QFramework.Toolkits 特性一览
-
工具集(QFramework.Toolkits v0.16)
-
UIKit 界面&View快速开发&管理解决方案
-
UI、GameObject 的代码生成&自动赋值
-
界面管理
-
层级管理
-
界面堆栈
-
默认使用 ResKit 方式管理界面资源
-
可自定义界面的加载、卸载方式
-
Manager Of Manager 架构集成(不推荐使用)
-
-
ResKit 资源快速开发&管理解决方案
-
AssetBundle 提供模拟模式,开发阶段无需打包即可加载资源
-
资源名称代码生成支持
-
同一个 API 可加载 AssetBundle、Resources、网络 和 自定义来源的资源
-
提供一套引用计数的资源管理模型
-
-
AudioKit 音频管理解决方案
-
提供背景音乐、人声、音效 三种音频播放 API
-
音量控制
-
默认使用 ResKit 方式管理音频资源
-
可自定义音频的加载、卸载方式
-
-
CoreKit 提供大量的代码工具
-
ActionKit:动作序列执行系统
-
CodeGenKit:代码生成 & 自动序列化赋值工具
-
EventKit:提供基于类、字符串、枚举以及信号类型的事件工具集
-
FluentAPI:对大量的 Unity 和 C# 常用的 API 提供了静态扩展的封装(链式 API)
-
IOCKit:提供依赖注入容器
-
LocaleKit:本地化&多语言工具集
-
LogKit:日志工具集
-
PackageKit:包管理工具,由此可更新框架和对应的插件模块。
-
PoolKit:对象池工具集,提供对象池的基础上,也提供 ListPool 和 Dictionary Pool 等工具。
-
SingletonKit:单例工具集
-
TableKit:提供表格类数据结构的工具集
-
-
二、View Controllor
View Controller(视图控制器) 是MVC(Model-View-Controller,模型-视图-控制器)架构模式中的一个关键组件,用于管理和协调视图(View)与模型(Model)之间的交互。
1、作用
-
管理视图的显示与更新
-
视图控制器负责加载和管理视图(View),并根据模型(Model)中的数据更新视图。
-
例如,当玩家的分数(存储在模型中)发生变化时,视图控制器会通知视图更新显示。
-
-
处理用户输入
-
视图控制器接收用户的输入(如点击按钮、移动鼠标等),并将其转换为对模型的操作。
-
例如,玩家点击“增加分数”按钮时,视图控制器会调用模型中的方法来更新分数。
-
-
协调视图与模型的交互
-
视图控制器作为视图和模型之间的桥梁,确保两者之间的数据同步。
-
它可以监听模型中的数据变化,并通知视图进行更新。
-
-
管理视图的生命周期
-
视图控制器负责管理视图的加载、显示、隐藏和销毁。
-
在Unity中,这通常通过脚本控制游戏对象的激活状态来实现。
-
2、应用场景
-
游戏开发
-
角色属性显示:玩家的血量、经验值、等级等数据存储在模型中,视图控制器负责将这些数据更新到UI视图上。
-
游戏菜单管理:主菜单、设置菜单、暂停菜单等视图由视图控制器管理,用户点击菜单项时,视图控制器处理输入并触发相应的逻辑。
-
-
UI界面管理
-
动态UI更新:例如,玩家购买道具时,视图控制器更新背包视图中的道具数量。
-
多视图切换:在游戏的不同阶段(如教程、关卡选择、游戏结束等)切换不同的视图。
-
-
复杂交互逻辑
-
事件驱动:视图控制器可以监听事件(如玩家死亡、任务完成等),并根据事件更新视图或触发其他逻辑。
-
状态管理:视图控制器可以保存和恢复视图的状态,例如在游戏暂停时保存当前界面状态。
-
3、示例
以下是一个简单的Unity MVC示例,展示如何使用视图控制器来管理玩家的分数:
PlayerModel.cs(模型)
public class PlayerModel
{
public int score;
public void AddScore(int points)
{
score += points;
}
}
PlayerView.cs(视图)
using UnityEngine;
using UnityEngine.UI;
public class PlayerView : MonoBehaviour
{
public Text scoreText;
public void UpdateScore(int score)
{
scoreText.text = "Score: " + score;
}
}
PlayerController.cs(视图控制器)
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public PlayerModel playerModel;
public PlayerView playerView;
void Start()
{
playerModel = new PlayerModel();
playerView = GetComponent<PlayerView>();
playerView.UpdateScore(playerModel.score);
}
public void OnAddScoreButtonClicked()
{
playerModel.AddScore(10); // 假设按钮点击增加10分
playerView.UpdateScore(playerModel.score);
}
}
在这个例子中:
-
PlayerModel 存储玩家的分数。
-
PlayerView 负责显示分数。
-
PlayerController 接收用户输入(按钮点击),更新模型,并通知视图更新显示。
通过这种方式,视图控制器在Unity中实现了视图与模型的解耦,使得代码更加模块化和易于维护
三、ActionKit时序动作执行系统
ActionKit 是一个强大的时序动作执行系统,用于简化游戏开发中的各种时序任务(如动画播放、延时操作、资源加载、网络请求等)。它通过统一的 API 将这些任务整合在一起,使得开发者可以更方便地管理和控制这些任务的执行顺序和逻辑。
1. 用法
ActionKit 提供了多种方法来定义和执行时序任务,包括延时回调、序列执行、条件执行、重复执行、并行执行等。以下是一些主要的用法:
(1)延时回调
using UnityEngine;
using QFramework;
public class DelayExample : MonoBehaviour
{
void Start()
{
Debug.Log("Start Time:" + Time.time);
ActionKit.Delay(1.0f, () =>
{
Debug.Log("End Time:" + Time.time);
}).Start(this);
}
}
-
在指定的延时后执行回调函数。
-
优势:简化了延时操作的代码,避免手动使用
Invoke
或Coroutine
。 -
应用场景:适用于需要在特定时间后执行某些操作的场景,例如动画播放、UI 更新等。
(2)序列执行
using UnityEngine;
using QFramework;
public class SequenceAndCallback : MonoBehaviour
{
void Start()
{
Debug.Log("Sequence Start:" + Time.time);
ActionKit.Sequence()
.Callback(() => Debug.Log("Delay Start:" + Time.time))
.Delay(1.0f)
.Callback(() => Debug.Log("Delay Finish:" + Time.time))
.Start(this, _ => { Debug.Log("Sequence Finish:" + Time.time); });
}
}
-
按照顺序执行一系列动作。
-
优势:可以方便地定义复杂的执行顺序,支持嵌套序列。
-
应用场景:适用于需要按顺序执行多个任务的场景,例如动画序列、任务流程等。
(3)帧延时
using UnityEngine;
using QFramework;
public class DelayFrameExample : MonoBehaviour
{
void Start()
{
Debug.Log("Delay Frame Start FrameCount:" + Time.frameCount);
ActionKit.DelayFrame(1, () => { Debug.Log("Delay Frame Finish FrameCount:" + Time.frameCount); })
.Start(this);
ActionKit.Sequence()
.DelayFrame(10)
.Callback(() => Debug.Log("Sequence Delay FrameCount:" + Time.frameCount))
.Start(this);
}
}
-
在指定的帧数后执行回调函数。
-
优势:基于帧数的延时,适用于需要精确控制帧数的场景。
-
应用场景:适用于动画帧控制、帧率同步等场景。
(4)条件执行
using UnityEngine;
using QFramework;
public class ConditionExample : MonoBehaviour
{
private void Start()
{
ActionKit.Sequence()
.Callback(() => Debug.Log("Before Condition"))
.Condition(() => Input.GetMouseButtonDown(0))
.Callback(() => Debug.Log("Mouse Clicked"))
.Start(this);
}
}
-
只有在满足特定条件时才执行后续动作。
-
优势:可以灵活地控制动作的执行条件。
-
应用场景:适用于需要根据用户输入或游戏状态触发操作的场景。
(5)重复执行
using UnityEngine;
using QFramework;
public class RepeatExample : MonoBehaviour
{
private void Start()
{
ActionKit.Repeat()
.Condition(() => Input.GetMouseButtonDown(0))
.Callback(() => Debug.Log("Mouse Clicked"))
.Start(this);
ActionKit.Repeat(5)
.Condition(() => Input.GetMouseButtonDown(1))
.Callback(() => Debug.Log("Mouse right clicked"))
.Start(this, () =>
{
Debug.Log("Right click finished");
});
}
}
-
重复执行某个动作,直到满足特定条件或达到指定次数。
-
优势:简化了重复操作的代码,支持无限循环和有限循环。
-
应用场景:适用于需要反复执行的任务,例如资源加载、网络请求等。
(6)并行执行
using UnityEngine;
using QFramework;
public class ParallelExample : MonoBehaviour
{
void Start()
{
Debug.Log("Parallel Start:" + Time.time);
ActionKit.Parallel()
.Delay(1.0f, () => { Debug.Log(Time.time); })
.Delay(2.0f, () => { Debug.Log(Time.time); })
.Delay(3.0f, () => { Debug.Log(Time.time); })
.Start(this, () =>
{
Debug.Log("Parallel Finish:" + Time.time);
});
}
}
-
同时执行多个动作。
-
优势:可以并行处理多个任务,提高效率。
-
应用场景:适用于需要同时执行多个任务的场景,例如多个动画同时播放、多个资源同时加载等。
(7)自定义动作
using UnityEngine;
using QFramework;
public class CustomExample : MonoBehaviour
{
class SomeData
{
public int ExecuteCount = 0;
}
private void Start()
{
ActionKit.Custom(a =>
{
a
.OnStart(() => { Debug.Log("OnStart"); })
.OnExecute(dt =>
{
Debug.Log("OnExecute");
a.Finish();
})
.OnFinish(() => { Debug.Log("OnFinish"); });
}).Start(this);
ActionKit.Custom<SomeData>(a =>
{
a
.OnStart(() =>
{
a.Data = new SomeData()
{
ExecuteCount = 0
};
})
.OnExecute(dt =>
{
Debug.Log(a.Data.ExecuteCount);
a.Data.ExecuteCount++;
if (a.Data.ExecuteCount >= 5)
{
a.Finish();
}
}).OnFinish(() => { Debug.Log("Finished"); });
}).Start(this);
}
}
-
允许开发者自定义动作的执行逻辑。
-
优势:提供了高度的灵活性,可以实现复杂的逻辑。
-
应用场景:适用于需要自定义逻辑的场景,例如自定义动画、自定义任务流程等。
(8)协程支持
using System.Collections;
using UnityEngine;
using QFramework;
public class CoroutineExample : MonoBehaviour
{
private void Start()
{
ActionKit.Coroutine(SomeCoroutine).Start(this);
SomeCoroutine().ToAction().Start(this);
ActionKit.Sequence()
.Coroutine(SomeCoroutine)
.Start(this);
}
IEnumerator SomeCoroutine()
{
yield return new WaitForSeconds(1.0f);
Debug.Log("Hello:" + Time.time);
}
}
-
支持将协程转换为 ActionKit 的动作。
-
优势:可以将协程与 ActionKit 的动作系统无缝集成。
-
应用场景:适用于需要使用协程的场景,例如复杂的异步任务。
(9)全局 Mono 生命周期
using UnityEngine;
using QFramework;
public class GlobalMonoEventsExample : MonoBehaviour
{
void Start()
{
ActionKit.OnUpdate.Register(() =>
{
if (Time.frameCount % 30 == 0)
{
Debug.Log("Update");
}
}).UnRegisterWhenGameObjectDestroyed(gameObject);
ActionKit.OnFixedUpdate.Register(() =>
{
// fixed update code here
}).UnRegisterWhenGameObjectDestroyed(gameObject);
ActionKit.OnLateUpdate.Register(() =>
{
// late update code here
}).UnRegisterWhenGameObjectDestroyed(gameObject);
ActionKit.OnGUI.Register(() =>
{
GUILayout.Label("See Example Code");
}).UnRegisterWhenGameObjectDestroyed(gameObject);
ActionKit.OnApplicationFocus.Register(focus =>
{
Debug.Log("focus:" + focus);
}).UnRegisterWhenGameObjectDestroyed(gameObject);
ActionKit.OnApplicationPause.Register(pause =>
{
Debug.Log("pause:" + pause);
}).UnRegisterWhenGameObjectDestroyed(gameObject);
ActionKit.OnApplicationQuit.Register(() =>
{
Debug.Log("quit");
}).UnRegisterWhenGameObjectDestroyed(gameObject);
}
}
-
允许开发者在全局范围内注册和管理生命周期事件。
-
优势:简化了全局事件的管理,避免在多个脚本中重复编写相同的代码。
-
应用场景:适用于需要全局管理生命周期事件的场景,例如全局状态管理、资源清理等。
(10)DOTween 集成
using DG.Tweening;
using UnityEngine;
using QFramework;
public class DOTweenExample : MonoBehaviour
{
private void Start()
{
ActionKit.Custom(c =>
{
c.OnStart(() => { transform.DOLocalMove(Vector3.one, 0.5f).OnComplete(c.Finish); });
}).Start(this);
DOTweenAction.Allocate(() => transform.DOLocalRotate(Vector3.one, 0.5f))
.Start(this);
DOVirtual.DelayedCall(2.0f, () => Debug.Log("2.0f")).ToAction().Start(this);
ActionKit.Sequence()
.DOTween(() => transform.DOScale(Vector3.one, 0.5f))
.Start(this);
}
}
-
将 DOTween 的动画功能集成到 ActionKit 中。
-
优势:可以使用 ActionKit 的统一 API 来管理 DOTween 动画。
-
应用场景:适用于需要使用 DOTween 动画的场景,例如复杂的动画序列。
(11)UniRx 集成
using System;
using UniRx;
using UnityEngine;
using QFramework;
public class UniRxExample : MonoBehaviour
{
void Start()
{
ActionKit.Custom(c =>
{
c.OnStart(() => { Observable.Timer(TimeSpan.FromSeconds(1.0f)).Subscribe(_ => c.Finish()); });
}).Start(this, () => Debug.Log("1.0f"));
UniRxAction<long>.Allocate(() => Observable.Timer(TimeSpan.FromSeconds(2.0f))).Start(this, () => Debug.Log("2.0f"));
Observable.Timer(TimeSpan.FromSeconds(3.0f)).ToAction().Start(this, () => Debug.Log("3.0f"));
ActionKit.Sequence()
.UniRx(() => Observable.Timer(TimeSpan.FromSeconds(4.0f)))
.Start(this, () => Debug.Log("4.0f"));
}
}
-
将 UniRx 的响应式编程功能集成到 ActionKit 中。
-
优势:可以使用 ActionKit 的统一 API 来管理 UniRx 的异步任务。
-
应用场景:适用于需要使用 UniRx 的场景,例如复杂的异步任务、响应式编程等。
2. 优势
-
统一的 API:ActionKit 提供了一套统一的 API 来管理各种时序任务,简化了代码的复杂性。
-
高度灵活:支持多种执行方式(如延时、序列、条件、重复、并行等),可以满足各种复杂的场景需求。
-
易于集成:支持与协程、DOTween、UniRx 等工具集成,扩展性强。
-
生命周期管理:支持全局生命周期事件的注册和管理,方便全局状态的控制。
-
简化开发:减少了手动编写重复代码的工作量,提高了开发效率。
3. 应用场景
-
游戏开发:适用于动画播放、任务流程、资源加载、网络请求等场景。
-
UI 管理:适用于复杂的 UI 动画和交互逻辑。
-
全局事件管理:适用于全局生命周期事件的管理,例如
Update
、FixedUpdate
、LateUpdate
等。 -
异步任务管理:适用于需要异步执行的任务,例如资源加载、网络请求等。
-
动画序列:适用于需要按顺序或并行播放多个动画的场景。
总结
ActionKit 是一个功能强大的时序动作执行系统,通过统一的 API 和灵活的执行方式,极大地简化了游戏开发中的时序任务管理。它支持多种执行模式(如延时、序列、条件、重复、并行等),并且可以与协程、DOTween、UniRx 等工具无缝集成,适用于各种复杂的开发场景。
四、 ResKit 资源管理&开发解决方案
ResKit 是一个资源管理与快速开发解决方案,旨在简化 Unity 项目中的资源加载和管理流程。它通过统一的 API,支持从多种来源(如 dataPath
、Resources
、StreamingAssetsPath
、PersistentDataPath
、网络等)加载资源,并基于引用计数简化资源的加载和卸载。
1. 用法
ResKit 的使用分为开发阶段和真机阶段,支持模拟模式和非模拟模式,以适应不同的开发需求。
(1)开发阶段(模拟模式)
-
标记资源:在
Asset
目录下,对需要标记的文件或文件夹右键选择@ResKit - AssetBundle Mark
。 -
编写代码:使用
ResLoader
加载资源,ResKit 会自动从Application.dataPath
加载资源,无需打包。
using UnityEngine;
using QFramework;
public class ResKitExample : MonoBehaviour
{
private ResLoader mResLoader = ResLoader.Allocate();
private void Start()
{
ResKit.Init(); // 初始化 ResKit
// 同步加载资源
var prefab = mResLoader.LoadSync<GameObject>("AssetObj");
var gameObj = Instantiate(prefab);
gameObj.name = "Loaded Object";
}
private void OnDestroy()
{
mResLoader.Recycle2Cache(); // 释放资源
mResLoader = null;
}
}
(2)真机阶段(非模拟模式)
-
打包资源:取消模拟模式,使用 ResKit 提供的工具打包 AssetBundle。
-
加载资源:在运行时加载 AssetBundle 资源,ResKit 会自动处理加载逻辑。
示例代码(异步加载):
using System.Collections;
using UnityEngine;
using QFramework;
public class AsyncLoadExample : MonoBehaviour
{
private ResLoader mResLoader = ResLoader.Allocate();
private IEnumerator Start()
{
yield return ResKit.InitAsync(); // 异步初始化 ResKit
mResLoader.Add2Load<GameObject>("AssetObj", (succeed, res) =>
{
if (succeed)
{
var gameObj = res.Asset.As<GameObject>().Instantiate();
gameObj.name = "Loaded Object";
}
});
mResLoader.LoadAsync(); // 执行异步加载
}
private void OnDestroy()
{
mResLoader.Recycle2Cache();
mResLoader = null;
}
}
2. 优势
-
统一 API:支持从多种来源加载资源,简化了资源管理的复杂性。
-
引用计数:基于引用计数管理资源加载和卸载,避免资源泄漏。
-
开发效率:模拟模式下无需频繁打包,直接从
dataPath
加载资源,提高开发效率。 -
异步加载:支持异步加载队列,优化加载性能。
-
代码生成:可生成资源名常量代码,减少拼写错误。
-
灵活扩展:支持自定义资源加载逻辑,可集成 Addressables 或其他资源管理方案。
3. 应用场景
-
游戏开发:适用于需要动态加载资源的场景,如游戏关卡加载、道具加载等。
-
UI 管理:快速加载 UI 预制体和资源,优化用户体验。
-
网络资源加载:支持从网络加载图片、模型等资源。
-
多平台支持:适用于多种平台(如 Android、iOS、WebGL 等),尤其是 WebGL 平台的异步加载支持。
-
资源热更新:支持 AssetBundle 的热更新,方便游戏版本迭代。
4. 示例
以下是一些具体的使用示例:
(1)加载场景
using UnityEngine;
using QFramework;
public class LoadSceneExample : MonoBehaviour
{
private ResLoader mResLoader = null;
void Start()
{
ResKit.Init();
mResLoader = ResLoader.Allocate();
// 同步加载场景
mResLoader.LoadSceneSync("SceneRes");
// 异步加载场景
mResLoader.LoadSceneAsync("SceneRes", onStartLoading: operation =>
{
// 加载进度处理
});
}
private void OnDestroy()
{
mResLoader.Recycle2Cache();
mResLoader = null;
}
}
(2)加载 Resources 中的资源
using UnityEngine;
using UnityEngine.UI;
using QFramework;
public class LoadResourcesResExample : MonoBehaviour
{
public RawImage RawImage;
private ResLoader mResLoader = ResLoader.Allocate();
private void Start()
{
// 加载 Resources 目录里的资源
RawImage.texture = mResLoader.LoadSync<Texture2D>("resources://TestTexture");
}
private void OnDestroy()
{
mResLoader.Recycle2Cache();
mResLoader = null;
}
}
(3)加载网络图片
using UnityEngine;
using UnityEngine.UI;
using QFramework;
public class NetImageExample : MonoBehaviour
{
private ResLoader mResLoader = ResLoader.Allocate();
private void Start()
{
var image = transform.Find("Image").GetComponent<Image>();
mResLoader.Add2Load<Texture2D>(
"http://example.com/image.jpg".ToNetImageResName(),
(succeed, res) =>
{
if (succeed)
{
var texture = res.Asset as Texture2D;
var sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.one * 0.5f);
image.sprite = sprite;
mResLoader.AddObjectForDestroyWhenRecycle2Cache(sprite);
}
});
mResLoader.LoadAsync();
}
private void OnDestroy()
{
mResLoader.Recycle2Cache();
mResLoader = null;
}
}
(4)自定义资源加载
using UnityEngine;
using QFramework;
public class CustomResExample : MonoBehaviour
{
public class MyRes : Res
{
public MyRes(string name)
{
mAssetName = name;
}
public override bool LoadSync()
{
// 自定义同步加载逻辑
State = ResState.Ready;
return true;
}
public override void LoadAsync()
{
// 自定义异步加载逻辑
State = ResState.Ready;
}
protected override void OnReleaseRes()
{
// 自定义资源释放逻辑
State = ResState.Waiting;
}
}
public class MyResCreator : IResCreator
{
public bool Match(ResSearchKeys resSearchKeys)
{
return resSearchKeys.AssetName.StartsWith("myres://");
}
public IRes Create(ResSearchKeys resSearchKeys)
{
return new MyRes(resSearchKeys.AssetName);
}
}
private void Start()
{
ResFactory.AddResCreator<MyResCreator>();
var resLoader = ResLoader.Allocate();
var resSearchKeys = ResSearchKeys.Allocate("myres://hello_world");
var myRes = resLoader.LoadResSync(resSearchKeys);
resSearchKeys.Recycle2Cache();
Debug.Log(myRes.AssetName);
Debug.Log(myRes.State);
}
}
总结
ResKit 是一个功能强大的资源管理解决方案,通过统一的 API 和灵活的加载方式,极大地简化了 Unity 项目中的资源管理流程。它支持多种加载来源、引用计数管理、异步加载队列、代码生成等功能,适用于游戏开发、UI 管理、网络资源加载等多种场景。