目录
一、UIKit 界面管理&快速开发解决方案
1、用法
(1)界面创建与层级管理
(2)代码生成与组件绑定
(3)打开与关闭界面
(4)自定义界面加载方式
2、应用场景
3、示例代码
二、AudioKit 音频管理解决方案
1、属性
2、用法
(1)播放音频
(2)音频设置
(3)音量调整
(4)自定义音频加载
3、应用场景
4、案例
(1)播放背景音乐
(2)播放音效
(3)播放人声
三、FluentAPI 链式 API 介绍
1、属性
2、用法
(1)基本用法
(2)与 ResKit 结合
3、应用场景及案例
(1)创建和设置游戏对象
(2)与 ResKit 结合
(3)UI 元素创建
总结
四、 SingletonKit 单例模板套件
1、特性
2、用法
(1)普通单例
(2)Mono单例
(3)属性单例
(4)MonoSingletonPath
(5)PersistentMonoSingleton
(6)ReplaceableMonoSingleton
3、应用场景
4、案例
(1)全局游戏管理器
(2)音频管理器
总结
五、FSMKit状态机
1、特性
2、用法
(1)链式调用
(2)类模式
3、应用场景
4、案例
(1)角色状态管理
(2)游戏流程状态管理
总结
六、PoolKit 对象池套件
1、特性
2、用法
(1)创建和使用对象池
(2)配置对象工厂
(3)数据结构封装
3、应用场景
4、案例
(1)子弹管理
(2)UI 元素管理
(3)数据结构封装
总结
七、TableKit 表数据结构介绍
1、特性
2、用法
(1)定义数据结构
(2)使用 TableKit
3、应用场景
4、案例
(1)资源管理
(2)UI 元素管理
(3)动画管理
总结
八、其他事件工具
1、EnumEventSystem
特性
用法
优势
2、StringEventSystem
特性
用法
3、 TypeEventSystem
特性
用法
4、 EasyEvent
特性
用法
对比
UIKit 是 QFramework 提供的一套界面管理与快速开发解决方案,旨在简化 Unity 游戏开发中的 UI 管理和交互逻辑。它通过界面管理、层级管理、代码生成及组件自动绑定等功能,帮助开发者高效地开发和维护 UI 系统。
创建一个测试场景(如 TestUIBasicPanel
),并拖入一个 UIRoot
Prefab。
在 Design
层级下创建一个 Panel(如 UIBasicPanel
),并将其制作成 Prefab。
在 Panel 上添加需要的控件(如按钮、文本框等),并为每个控件添加 Bind
脚本。
使用 UIKit 的代码生成工具,生成对应的 UI 脚本代码。
在生成的脚本中,可以方便地访问绑定的控件,并为其添加逻辑。
使用 UIKit.OpenPanel
打开界面。
在界面脚本中实现 OnInit
、OnOpen
、OnShow
、OnHide
、OnClose
等生命周期方法。
继承 AbstractPanelLoaderPool
类,并实现一个 IPanelLoader
的类。
在游戏启动时设置自定义的面板加载器。
游戏开发:适用于游戏中的各种 UI 场景,如主界面、设置界面、道具界面等。
独立测试:每个界面可以独立测试,方便开发和调试。
复杂交互:支持复杂的用户交互逻辑,如按钮点击、动画效果等。
多平台支持:适用于多种平台,包括移动设备和桌面设备。
以下是一个简单的 UIKit 示例,展示如何创建和使用一个基本的 UI 界面:
using UnityEngine;
using UnityEngine.UI;
using QFramework;
public class UIBasicPanelData : UIPanelData
{
public int Coin;
}
public partial class UIBasicPanel : UIPanel
{
protected override void OnInit(IUIData uiData = null)
{
mData = uiData as UIBasicPanelData ?? new UIBasicPanelData();
Debug.Log(mData.Coin);
BtnStart.onClick.AddListener(() =>
{
Debug.Log("开始游戏");
});
}
protected override void OnOpen(IUIData uiData = null)
{
Debug.Log((uiData as UIBasicPanelData).Coin);
}
protected override void OnShow()
{
// 界面显示时的逻辑
}
protected override void OnHide()
{
// 界面隐藏时的逻辑
}
protected override void OnClose()
{
// 界面关闭时的逻辑
}
}
在这个示例中:
UIBasicPanel
是一个 UI 界面类,继承自 UIPanel
。
使用 OnInit
方法初始化界面,并为按钮添加点击事件。
使用 OnOpen
方法在界面打开时传递数据。
使用 OnShow
、OnHide
和 OnClose
方法管理界面的显示、隐藏和关闭逻辑。
通过 UIKit,开发者可以快速创建和管理复杂的 UI 系统,同时保持代码的清晰和可维护性
AudioKit 是 QFramework 提供的一套音频播放管理工具,用于简化 Unity 游戏开发中的音频播放逻辑。它支持播放背景音乐、音效和人声,并提供了灵活的音频设置功能,包括音量调整、开关控制等。AudioKit 的设计目标是让音频管理更加高效和便捷。
AudioKit 的主要功能和属性包括:
背景音乐播放:同一时间只能播放一个背景音乐,播放新的音乐会自动停止当前播放的音乐。
音效播放:支持同时播放多个音效,适用于游戏中的各种音效需求。
人声播放:与背景音乐类似,同一时间只能播放一个人声,适合用于旁白等场景。
音量调整:支持独立调整背景音乐、音效和人声的音量。
开关控制:可以独立开启或关闭背景音乐、音效和人声。
自定义音频加载:支持自定义音频加载逻辑,可以集成其他资源管理方案。
AudioKit 的使用非常简单,通过提供的 API 可以快速实现音频播放和管理功能。
播放背景音乐
csharp复制
btnPlayGame.onClick.AddListener(() => { AudioKit.PlayMusic("resources://game_bg"); });
播放音效
csharp复制
btnPlaySound.onClick.AddListener(() => { AudioKit.PlaySound("resources://game_effect"); });
播放人声
csharp复制
btnPlayVoice.onClick.AddListener(() => { AudioKit.PlayVoice("resources://game_voice"); });
开启/关闭音效
csharp复制
btnSoundOn.onClick.AddListener(() => { AudioKit.Settings.IsSoundOn.Value = true; });
btnSoundOff.onClick.AddListener(() => { AudioKit.Settings.IsSoundOn.Value = false; });
开启/关闭背景音乐
csharp复制
btnMusicOn.onClick.AddListener(() => { AudioKit.Settings.IsMusicOn.Value = true; });
btnMusicOff.onClick.AddListener(() => { AudioKit.Settings.IsMusicOn.Value = false; });
开启/关闭人声
csharp复制
btnVoiceOn.onClick.AddListener(() => { AudioKit.Settings.IsVoiceOn.Value = true; });
btnVoiceOff.onClick.AddListener(() => { AudioKit.Settings.IsVoiceOn.Value = false; });
绑定音量滑块
csharp复制
AudioKit.Settings.MusicVolume.RegisterWithInitValue(v => musicVolumeSlider.value = v);
AudioKit.Settings.VoiceVolume.RegisterWithInitValue(v => voiceVolumeSlider.value = v);
AudioKit.Settings.SoundVolume.RegisterWithInitValue(v => soundVolumeSlider.value = v);
musicVolumeSlider.onValueChanged.AddListener(v => { AudioKit.Settings.MusicVolume.Value = v; });
voiceVolumeSlider.onValueChanged.AddListener(v => { AudioKit.Settings.VoiceVolume.Value = v; });
soundVolumeSlider.onValueChanged.AddListener(v => { AudioKit.Settings.SoundVolume.Value = v; });
自定义音频加载器
csharp复制
using System;
using UnityEngine;
using QFramework;
public class CustomAudioLoaderExample : MonoBehaviour
{
class ResourcesAudioLoaderPool : AbstractAudioLoaderPool
{
protected override IAudioLoader CreateLoader()
{
return new ResourcesAudioLoader();
}
}
class ResourcesAudioLoader : IAudioLoader
{
private AudioClip mClip;
public AudioClip Clip => mClip;
public AudioClip LoadClip(AudioSearchKeys audioSearchKeys)
{
mClip = Resources.Load(audioSearchKeys.AssetName);
return mClip;
}
public void LoadClipAsync(AudioSearchKeys audioSearchKeys, Action onLoad)
游戏开发:适用于游戏中的背景音乐、音效和人声播放。
多媒体应用:适用于需要播放多种音频的多媒体应用。
交互式应用:支持复杂的用户交互逻辑,如按钮点击播放音效。
多平台支持:适用于多种平台,包括移动设备和桌面设备。
以下是一个完整的 AudioKit 使用示例,展示如何在 Unity 项目中实现音频播放和管理功能:
using UnityEngine;
using UnityEngine.UI;
using QFramework;
public class AudioManagerExample : MonoBehaviour
{
public Button btnPlayGame;
public Button btnStopGame;
public Slider musicVolumeSlider;
void Start()
{
btnPlayGame.onClick.AddListener(() => { AudioKit.PlayMusic("resources://game_bg"); });
btnStopGame.onClick.AddListener(() => { AudioKit.StopMusic(); });
AudioKit.Settings.MusicVolume.RegisterWithInitValue(v => musicVolumeSlider.value = v);
musicVolumeSlider.onValueChanged.AddListener(v => { AudioKit.Settings.MusicVolume.Value = v; });
}
}
using UnityEngine;
using UnityEngine.UI;
using QFramework;
public class AudioManagerExample : MonoBehaviour
{
public Button btnPlaySound;
public Button btnStopSound;
public Slider soundVolumeSlider;
void Start()
{
btnPlaySound.onClick.AddListener(() => { AudioKit.PlaySound("resources://game_effect"); });
btnStopSound.onClick.AddListener(() => { AudioKit.StopSound("resources://game_effect"); });
AudioKit.Settings.SoundVolume.RegisterWithInitValue(v => soundVolumeSlider.value = v);
soundVolumeSlider.onValueChanged.AddListener(v => { AudioKit.Settings.SoundVolume.Value = v; });
}
}
using UnityEngine;
using UnityEngine.UI;
using QFramework;
public class AudioManagerExample : MonoBehaviour
{
public Button btnPlayVoice;
public Button btnStopVoice;
public Slider voiceVolumeSlider;
void Start()
{
btnPlayVoice.onClick.AddListener(() => { AudioKit.PlayVoice("resources://game_voice"); });
btnStopVoice.onClick.AddListener(() => { AudioKit.StopVoice(); });
AudioKit.Settings.VoiceVolume.RegisterWithInitValue(v => voiceVolumeSlider.value = v);
voiceVolumeSlider.onValueChanged.AddListener(v => { AudioKit.Settings.VoiceVolume.Value = v; });
}
}
通过这些示例,开发者可以快速实现音频播放和管理功能,同时保持代码的清晰和可维护性。
FluentAPI 是一种设计模式,通过将方法调用链接在一起,形成一种类似自然语言的流畅接口。在 Unity 开发中,FluentAPI 是对 Unity 原生 API 的链式封装,旨在简化代码的可读性和可维护性。通过 FluentAPI,开发者可以使用更简洁、更直观的代码来完成复杂的操作。
FluentAPI 的主要特性包括:
链式调用:通过方法返回对象的引用,允许连续调用多个方法。
可读性强:代码更接近自然语言,易于理解和维护。
减少冗余:减少了重复的代码,提高了开发效率。
灵活性高:可以与 Unity 原生 API 以及其他模块(如 ResKit)无缝集成。
FluentAPI 的使用非常简单,通过扩展方法将多个操作链接在一起。以下是一些常见的用法:
// Traditional style
var playerPrefab = Resources.Load("playerPrefab");
var playerObj = Instantiate(playerPrefab);
playerObj.transform.SetParent(null);
playerObj.transform.localRotation = Quaternion.identity;
playerObj.transform.localPosition = Vector3.left;
playerObj.transform.localScale = Vector3.one;
playerObj.layer = 1;
playerObj.layer = LayerMask.GetMask("Default");
Debug.Log("playerPrefab instantiated");
// FluentAPI style
Resources.Load("playerPrefab")
.Instantiate()
.transform
.Parent(null)
.LocalRotationIdentity()
.LocalPosition(Vector3.left)
.LocalScaleIdentity()
.Layer(1)
.Layer("Default")
.ApplySelfTo(_ => { Debug.Log("playerPrefab instantiated"); });
mResLoader.LoadSync("mygameobj")
.InstantiateWithParent(parent)
.transform
.LocalIdentity()
.Name("MyGameObj")
.Show();
游戏开发:适用于游戏中的对象创建、属性设置和操作。
UI 管理:简化 UI 元素的创建和布局。
资源管理:与 ResKit 结合,简化资源加载和对象创建。
动画和特效:简化动画和特效的设置和播放。
多平台支持:适用于多种平台,包括移动设备和桌面设备。
using UnityEngine;
using QFramework;
public class FluentAPIExample : MonoBehaviour
{
private void Start()
{
// 创建一个游戏对象并设置其属性
Resources.Load("playerPrefab")
.Instantiate()
.transform
.Parent(null)
.LocalRotationIdentity()
.LocalPosition(Vector3.left)
.LocalScaleIdentity()
.Layer(1)
.Layer("Default")
.ApplySelfTo(_ => { Debug.Log("playerPrefab instantiated"); });
}
}
using UnityEngine;
using QFramework;
public class FluentAPIWithResKitExample : MonoBehaviour
{
private ResLoader mResLoader = ResLoader.Allocate();
private void Start()
{
// 使用 ResKit 加载资源并设置属性
mResLoader.LoadSync("mygameobj")
.InstantiateWithParent(transform)
.transform
.LocalIdentity()
.Name("MyGameObj")
.Show();
}
private void OnDestroy()
{
mResLoader.Recycle2Cache();
mResLoader = null;
}
}
using UnityEngine;
using UnityEngine.UI;
using QFramework;
public class FluentAPIUIExample : MonoBehaviour
{
private void Start()
{
// 创建一个按钮并设置其属性
Resources.Load
FluentAPI 是一种强大的链式 API 封装方式,通过简化代码的可读性和可维护性,极大地提高了开发效率。它支持链式调用、减少冗余代码,并且可以与 Unity 原生 API 以及其他模块(如 ResKit)无缝集成。FluentAPI 适用于游戏开发、UI 管理、资源管理等多种场景,能够帮助开发者快速实现复杂的操作。
SingletonKit 是 QFramework 提供的一套成熟的单例模式实现工具,经过了多年迭代和优化。它提供了多种单例模式的实现方式,包括普通单例、Mono单例、属性单例等,帮助开发者快速实现单例模式,减少重复代码,提高开发效率。
多种单例实现:支持普通单例、Mono单例、属性单例等多种实现方式。
线程安全:生成的单例类支持线程安全的访问。
生命周期管理:支持在不同生命周期阶段初始化和销毁单例。
自动代码生成:通过模板工具自动生成单例类的代码。
灵活性高:可以自定义单例的初始化逻辑和销毁逻辑。
支持多种命名方式:支持通过路径命名、自动命名等方式管理单例。
SingletonKit 提供了多种单例实现方式,开发者可以根据需求选择合适的实现方式。
using QFramework;
public class GameDataManager : Singleton
{
private static int mIndex = 0;
private GameDataManager() {}
public override void OnSingletonInit()
{
mIndex++;
}
public void Log(string content)
{
Debug.Log($"GameDataManager{mIndex}: {content}");
}
}
// 使用方法
GameDataManager.Instance.Log("Hello");
GameDataManager.Instance.Dispose();
using QFramework;
public class GameManager : MonoSingleton
{
public override void OnSingletonInit()
{
Debug.Log(name + ": OnSingletonInit");
}
private void Awake()
{
Debug.Log(name + ": Awake");
}
private void Start()
{
Debug.Log(name + ": Start");
}
protected override void OnDestroy()
{
base.OnDestroy();
Debug.Log(name + ": OnDestroy");
}
}
// 使用方法
var gameManager = GameManager.Instance;
using QFramework;
public class GameDataManager : ISingleton
{
public static GameDataManager Instance
{
get { return SingletonProperty.Instance; }
}
private GameDataManager() {}
private static int mIndex = 0;
public void OnSingletonInit()
{
mIndex++;
}
public void Dispose()
{
SingletonProperty.Dispose();
}
public void Log(string content)
{
Debug.Log($"GameDataManager{mIndex}: {content}");
}
}
// 使用方法
GameDataManager.Instance.Log("Hello");
GameDataManager.Instance.Dispose();
using QFramework;
using UnityEngine;
[MonoSingletonPath("[Example]/MonoSingeltonPath")]
public class ClassUseMonoSingletonPath : QMonoSingleton
{
}
public class MonoSingletonPath : MonoBehaviour
{
private void Start()
{
var instance = ClassUseMonoSingletonPath.Instance;
}
}
using QFramework;
public class GameManager : PersistentMonoSingleton
{
}
IEnumerator Start()
{
var gameManager = GameManager.Instance;
var newGameManager = new GameObject().AddComponent();
yield return new WaitForEndOfFrame();
Debug.Log(FindObjectsOfType().Length); // 1
Debug.Log(gameManager == null); // false
Debug.Log(newGameManager == null); // true
}
using QFramework;
public class GameManager : ReplaceableMonoSingleton
{
}
IEnumerator Start()
{
var gameManager = GameManager.Instance;
var newGameManager = new GameObject().AddComponent();
yield return new WaitForEndOfFrame();
Debug.Log(FindObjectsOfType().Length); // 1
Debug.Log(gameManager == null); // true
Debug.Log(newGameManager == null); // false
}
全局管理器:适用于需要全局访问的管理器,如 GameManager
、AudioManager
、UIManager
等。
配置管理:用于加载和管理全局配置文件。
资源管理:用于管理全局资源加载和卸载。
网络管理:用于管理网络请求和通信。
多平台支持:适用于多种平台,包括移动设备和桌面设备。
using QFramework;
public class GameManager : MonoSingleton
{
public override void OnSingletonInit()
{
Debug.Log(name + ": OnSingletonInit");
}
private void Awake()
{
Debug.Log(name + ": Awake");
}
private void Start()
{
Debug.Log(name + ": Start");
}
protected override void OnDestroy()
{
base.OnDestroy();
Debug.Log(name + ": OnDestroy");
}
public void StartGame()
{
Debug.Log("Game Started");
}
}
// 使用方法
var gameManager = GameManager.Instance;
gameManager.StartGame();
using QFramework;
public class AudioManager : MonoSingleton
{
public override void OnSingletonInit()
{
Debug.Log(name + ": OnSingletonInit");
}
private void Awake()
{
Debug.Log(name + ": Awake");
}
private void Start()
{
Debug.Log(name + ": Start");
}
protected override void OnDestroy()
{
base.OnDestroy();
Debug.Log(name + ": OnDestroy");
}
public void PlaySound(string soundName)
{
Debug.Log($"Playing sound: {soundName}");
}
}
// 使用方法
var audioManager = AudioManager.Instance;
audioManager.PlaySound("background_music");
SingletonKit 是一个功能强大的单例模板工具,通过自动生成单例类代码,极大地简化了单例模式的实现。它支持多种单例实现方式,包括普通单例、Mono单例、属性单例等,适用于全局管理器、配置管理、资源管理和网络管理等多种场景。通过 SingletonKit,开发者可以快速实现单例模式,提高开发效率并减少错误。
FSMKit 是 QFramework 内置的一个简易的状态机工具,用于简化 Unity 开发中的状态管理和状态切换逻辑。状态机是一种常见的设计模式,用于管理对象的状态和状态之间的转换。FSMKit 提供了链式和类模式两种方式,方便开发者根据项目需求选择合适的实现方式。
链式和类模式:支持链式调用和类模式两种实现方式,灵活适应不同开发阶段和项目需求。
多种生命周期方法:支持 OnEnter
、OnExit
、OnUpdate
、OnFixedUpdate
、OnGUI
等生命周期方法,方便管理状态的进入、退出和更新逻辑。
条件触发:支持通过条件函数触发状态切换,增加了状态机的灵活性。
集成性:与 Unity 的生命周期方法(如 Update
、FixedUpdate
、OnGUI
)无缝集成,方便开发者使用。
易于扩展:可以方便地添加新的状态和状态转换逻辑。
FSMKit 的使用非常简单,以下是两种主要的使用方式:
using UnityEngine;
namespace QFramework.Example
{
public class IStateBasicUsageExample : MonoBehaviour
{
public enum States
{
A,
B
}
public FSM FSM = new FSM();
void Start()
{
FSM.State(States.A)
.OnCondition(() => FSM.CurrentStateId == States.B)
.OnEnter(() =>
{
Debug.Log("Enter A");
})
.OnUpdate(() =>
{
})
.OnFixedUpdate(() =>
{
})
.OnGUI(() =>
{
GUILayout.Label("State A");
if (GUILayout.Button("To State B"))
{
FSM.ChangeState(States.B);
}
})
.OnExit(() =>
{
Debug.Log("Exit A");
});
FSM.State(States.B)
.OnCondition(() => FSM.CurrentStateId == States.A)
.OnGUI(() =>
{
GUILayout.Label("State B");
if (GUILayout.Button("To State A"))
{
FSM.ChangeState(States.A);
}
});
FSM.StartState(States.A);
}
private void Update()
{
FSM.Update();
}
private void FixedUpdate()
{
FSM.FixedUpdate();
}
private void OnGUI()
{
FSM.OnGUI();
}
private void OnDestroy()
{
FSM.Clear();
}
}
}
using UnityEngine;
namespace QFramework.Example
{
public class IStateClassExample : MonoBehaviour
{
public enum States
{
A,
B,
C
}
public FSM FSM = new FSM();
public class StateA : AbstractState
{
public StateA(FSM fsm, IStateClassExample target) : base(fsm, target)
{
}
protected override bool OnCondition()
{
return mFSM.CurrentStateId == States.B;
}
public override void OnEnter()
{
Debug.Log("Enter A");
}
public override void OnUpdate()
{
// Update logic for State A
}
public override void OnFixedUpdate()
{
// FixedUpdate logic for State A
}
public override void OnGUI()
{
GUILayout.Label("State A");
if (GUILayout.Button("To State B"))
{
mFSM.ChangeState(States.B);
}
}
public override void OnExit()
{
Debug.Log("Exit A");
}
}
public class StateB : AbstractState
{
public StateB(FSM fsm, IStateClassExample target) : base(fsm, target)
{
}
protected override bool OnCondition()
{
return mFSM.CurrentStateId == States.A;
}
public override void OnEnter()
{
Debug.Log("Enter B");
}
public override void OnUpdate()
{
// Update logic for State B
}
public override void OnFixedUpdate()
{
// FixedUpdate logic for State B
}
public override void OnGUI()
{
GUILayout.Label("State B");
if (GUILayout.Button("To State A"))
{
mFSM.ChangeState(States.A);
}
}
public override void OnExit()
{
Debug.Log("Exit B");
}
}
private void Start()
{
FSM.AddState(States.A, new StateA(FSM, this));
FSM.AddState(States.B, new StateB(FSM, this));
FSM.StartState(States.A);
}
private void OnGUI()
{
FSM.OnGUI();
}
private void OnDestroy()
{
FSM.Clear();
}
}
}
游戏开发:用于管理游戏中的角色状态(如行走、跳跃、攻击等)、游戏流程状态(如菜单、游戏开始、游戏结束等)。
UI 管理:用于管理 UI 状态(如菜单切换、窗口显示隐藏等)。
动画管理:用于管理动画状态(如播放、暂停、停止等)。
多平台支持:适用于多种平台,包括移动设备和桌面设备。
using UnityEngine;
namespace QFramework.Example
{
public class PlayerStateMachine : MonoBehaviour
{
public enum PlayerStates
{
Idle,
Walk,
Run,
Jump
}
public FSM FSM = new FSM();
private void Start()
{
FSM.State(PlayerStates.Idle)
.OnEnter(() => { Debug.Log("Player is idle"); })
.OnUpdate(() =>
{
if (Input.GetKey(KeyCode.W))
{
FSM.ChangeState(PlayerStates.Walk);
}
});
FSM.State(PlayerStates.Walk)
.OnEnter(() => { Debug.Log("Player is walking"); })
.OnUpdate(() =>
{
if (Input.GetKey(KeyCode.LeftShift))
{
FSM.ChangeState(PlayerStates.Run);
}
});
FSM.State(PlayerStates.Run)
.OnEnter(() => { Debug.Log("Player is running"); })
.OnUpdate(() =>
{
if (Input.GetKeyUp(KeyCode.LeftShift))
{
FSM.ChangeState(PlayerStates.Walk);
}
});
FSM.StartState(PlayerStates.Idle);
}
private void Update()
{
FSM.Update();
}
}
}
using UnityEngine;
namespace QFramework.Example
{
public class GameFlowStateMachine : MonoBehaviour
{
public enum GameStates
{
Menu,
Playing,
Paused,
GameOver
}
public FSM FSM = new FSM();
private void Start()
{
FSM.State(GameStates.Menu)
.OnEnter(() => { Debug.Log("Game is in menu"); })
.OnUpdate(() =>
{
if (Input.GetKeyDown(KeyCode.Space))
{
FSM.ChangeState(GameStates.Playing);
}
});
FSM.State(GameStates.Playing)
.OnEnter(() => { Debug.Log("Game is playing"); })
.OnUpdate(() =>
{
if (Input.GetKeyDown(KeyCode.P))
{
FSM.ChangeState(GameStates.Paused);
}
});
FSM.State(GameStates.Paused)
.OnEnter(() => { Debug.Log("Game is paused"); })
.OnUpdate(() =>
{
if (Input.GetKeyDown(KeyCode.P))
{
FSM.ChangeState(GameStates.Playing);
}
});
FSM.StartState(GameStates.Menu);
}
private void Update()
{
FSM.Update();
}
}
}
FSMKit 是 QFramework 提供的一个简易而强大的状态机工具,通过链式调用和类模式两种实现方式,极大地简化了状态管理和状态切换逻辑。它支持多种生命周期方法,提供了灵活的状态条件触发机制,并与 Unity 的生命周期方法无缝集成。FSMKit 适用于游戏开发、UI 管理、动画管理等多种场景,帮助开发者高效管理复杂的逻辑。通过 FSMKit,开发者可以轻松实现状态机
SafeObjectPool 是 QFramework 提供的一种对象池工具,用于管理对象的创建、复用和销毁。对象池是一种常见的设计模式,用于减少对象频繁创建和销毁的开销,提高性能。SafeObjectPool 提供了线程安全的对象池实现,支持多种对象工厂,并且可以方便地配置和管理对象池。
线程安全:支持多线程环境下的对象池操作。
多种对象工厂:支持 DefaultObjectFactory
、NonPublicObjectFactory
和 CustomObjectFactory
,可以灵活创建对象。
灵活配置:可以动态设置对象池的初始大小、最大大小和对象工厂。
数据结构封装:提供 ListPool
和 DictionaryPool
,用于管理 List
和 Dictionary
的复用。
易于扩展:可以方便地添加新的对象类型和对象工厂。
SafeObjectPool 的使用非常简单,以下是具体的使用方法:
using UnityEngine;
using QFramework;
public class Bullet : IPoolable, IPoolType
{
public void OnRecycled()
{
Debug.Log("回收了");
}
public bool IsRecycled { get; set; }
public static Bullet Allocate()
{
return SafeObjectPool.Instance.Allocate();
}
public void Recycle2Cache()
{
SafeObjectPool.Instance.Recycle(this);
}
}
// 初始化对象池
SafeObjectPool.Instance.Init(50, 25);
// 从对象池中获取对象
var bullet = Bullet.Allocate();
Debug.Log(SafeObjectPool.Instance.CurCount);
// 将对象返回到对象池
bullet.Recycle2Cache();
Debug.Log(SafeObjectPool.Instance.CurCount);
// 设置对象工厂
SafeObjectPool.Instance.SetFactoryMethod(() =>
{
// 创建对象
return new Bullet();
});
// 使用默认对象工厂
SafeObjectPool.Instance.SetObjectFactory(new DefaultObjectFactory());
// 使用自定义对象工厂
SafeObjectPool.Instance.SetObjectFactory(new CustomObjectFactory(() => new Bullet()));
// 使用 ListPool
var names = ListPool.Get();
names.Add("Hello");
names.Release2Pool();
// 使用 DictionaryPool
var infos = DictionaryPool.Get();
infos.Add("name", "liangxie");
infos.Release2Pool();
游戏开发:适用于管理游戏中的子弹、敌人、道具等对象。
UI 管理:适用于管理 UI 元素的创建和销毁。
动画管理:适用于管理动画对象的创建和销毁。
多平台支持:适用于多种平台,包括移动设备和桌面设备。
以下是一些具体的 SafeObjectPool 使用示例,展示如何在 Unity 项目中实现对象池管理:
using UnityEngine;
using QFramework;
public class Bullet : IPoolable, IPoolType
{
public void OnRecycled()
{
Debug.Log("回收了");
}
public bool IsRecycled { get; set; }
public static Bullet Allocate()
{
return SafeObjectPool.Instance.Allocate();
}
public void Recycle2Cache()
{
SafeObjectPool.Instance.Recycle(this);
}
}
// 初始化对象池
SafeObjectPool.Instance.Init(50, 25);
// 从对象池中获取对象
var bullet = Bullet.Allocate();
Debug.Log(SafeObjectPool.Instance.CurCount);
// 将对象返回到对象池
bullet.Recycle2Cache();
Debug.Log(SafeObjectPool.Instance.CurCount);
using UnityEngine;
using QFramework;
public class UIElement : IPoolable, IPoolType
{
public void OnRecycled()
{
Debug.Log("回收了");
}
public bool IsRecycled { get; set; }
public static UIElement Allocate()
{
return SafeObjectPool.Instance.Allocate();
}
public void Recycle2Cache()
{
SafeObjectPool.Instance.Recycle(this);
}
}
// 初始化对象池
SafeObjectPool.Instance.Init(10, 5);
// 从对象池中获取对象
var uiElement = UIElement.Allocate();
Debug.Log(SafeObjectPool.Instance.CurCount);
// 将对象返回到对象池
uiElement.Recycle2Cache();
Debug.Log(SafeObjectPool.Instance.CurCount);
// 使用 ListPool
var names = ListPool.Get();
names.Add("Hello");
names.Release2Pool();
// 使用 DictionaryPool
var infos = DictionaryPool.Get();
infos.Add("name", "liangxie");
infos.Release2Pool();
SafeObjectPool 是 QFramework 提供的一种安全的对象池工具,通过对象池管理对象的创建、复用和销毁,减少对象频繁创建和销毁的开销,提高性能。它支持线程安全、多种对象工厂和灵活配置,适用于游戏开发、UI 管理、动画管理等多种场景。通过 SafeObjectPool,开发者可以高效管理对象池,减少内存分配和垃圾回收的开销。
TableKit 是 QFramework 提供的一个封装的数据结构,用于高效管理和查询复杂的数据集合。它通过扩展 List
和 Dictionary
的功能,提供了更强大的查询能力和更高的性能。TableKit 特别适用于需要频繁查询和操作的数据集合,例如游戏中的资源管理、UI 元素管理等。
多索引支持:支持通过多个索引对数据进行快速查询。
高性能查询:通过索引优化查询性能,支持联合查询。
灵活的数据操作:支持添加、删除、清空和遍历数据。
线程安全:支持多线程环境下的数据操作。
易于扩展:可以方便地扩展和自定义数据结构。
TableKit 的使用非常简单,以下是具体的使用方法:
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace QFramework
{
public class TableKitExample : MonoBehaviour
{
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public int Level { get; set; }
}
public class School : Table
{
public TableIndex AgeIndex = new TableIndex((student) => student.Age);
public TableIndex LevelIndex = new TableIndex((student) => student.Level);
protected override void OnAdd(Student item)
{
AgeIndex.Add(item);
LevelIndex.Add(item);
}
protected override void OnRemove(Student item)
{
AgeIndex.Remove(item);
LevelIndex.Remove(item);
}
protected override void OnClear()
{
AgeIndex.Clear();
LevelIndex.Clear();
}
public override IEnumerator GetEnumerator()
{
return AgeIndex.Dictionary.Values.SelectMany(s => s).GetEnumerator();
}
protected override void OnDispose()
{
AgeIndex.Dispose();
LevelIndex.Dispose();
}
}
}
}
private void Start()
{
var school = new School();
school.Add(new Student() { Age = 1, Level = 2, Name = "liangxie" });
school.Add(new Student() { Age = 2, Level = 2, Name = "ava" });
school.Add(new Student() { Age = 3, Level = 2, Name = "abc" });
school.Add(new Student() { Age = 3, Level = 3, Name = "efg" });
foreach (var student in school.LevelIndex.Get(2).Where(s => s.Age < 3))
{
Debug.Log(student.Age + ":" + student.Level + ":" + student.Name);
}
}
游戏开发:适用于管理游戏中的资源、角色、道具等数据。
UI 管理:适用于管理 UI 元素的数据,例如按钮、文本框等。
动画管理:适用于管理动画数据,例如动画剪辑、动画状态等。
多平台支持:适用于多种平台,包括移动设备和桌面设备。
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace QFramework
{
public class Resource
{
public string Name { get; set; }
public int Type { get; set; }
public int Size { get; set; }
}
public class ResourceManager : Table
{
public TableIndex TypeIndex = new TableIndex((resource) => resource.Type);
protected override void OnAdd(Resource item)
{
TypeIndex.Add(item);
}
protected override void OnRemove(Resource item)
{
TypeIndex.Remove(item);
}
protected override void OnClear()
{
TypeIndex.Clear();
}
public override IEnumerator GetEnumerator()
{
return TypeIndex.Dictionary.Values.SelectMany(r => r).GetEnumerator();
}
protected override void OnDispose()
{
TypeIndex.Dispose();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace QFramework
{
public class UIElement
{
public string Name { get; set; }
public int Type { get; set; }
public int Layer { get; set; }
}
public class UIManager : Table
{
public TableIndex TypeIndex = new TableIndex((element) => element.Type);
public TableIndex LayerIndex = new TableIndex((element) => element.Layer);
protected override void OnAdd(UIElement item)
{
TypeIndex.Add(item);
LayerIndex.Add(item);
}
protected override void OnRemove(UIElement item)
{
TypeIndex.Remove(item);
LayerIndex.Remove(item);
}
protected override void OnClear()
{
TypeIndex.Clear();
LayerIndex.Clear();
}
public override IEnumerator GetEnumerator()
{
return TypeIndex.Dictionary.Values.SelectMany(e => e).GetEnumerator();
}
protected override void OnDispose()
{
TypeIndex.Dispose();
LayerIndex.Dispose();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace QFramework
{
public class AnimationClip
{
public string Name { get; set; }
public int Type { get; set; }
public float Length { get; set; }
}
public class AnimationManager : Table
{
public TableIndex TypeIndex = new TableIndex((clip) => clip.Type);
protected override void OnAdd(AnimationClip item)
{
TypeIndex.Add(item);
}
protected override void OnRemove(AnimationClip item)
{
TypeIndex.Remove(item);
}
protected override void OnClear()
{
TypeIndex.Clear();
}
public override IEnumerator GetEnumerator()
{
return TypeIndex.Dictionary.Values.SelectMany(c => c).GetEnumerator();
}
protected override void OnDispose()
{
TypeIndex.Dispose();
}
}
}
TableKit 是 QFramework 提供的一个高效的数据管理工具,通过封装 List
和 Dictionary
的功能,提供了更强大的查询能力和更高的性能。它支持多索引查询、高性能查询、灵活的数据操作和线程安全,适用于游戏开发、UI 管理、动画管理等多种场景。通过 TableKit,开发者可以高效管理复杂的数据集合,减少查询开销,提高性能。
QFramework 提供了多种事件系统,包括 TypeEventSystem
、EasyEvent
、EnumEventSystem
和 StringEventSystem
。这些事件系统各有特点,适用于不同的开发场景。下面将详细介绍每种事件系统的使用方法、优势、应用场景及案例。
EnumEventSystem
是 QFramework 提供的一种基于枚举的事件系统。它使用枚举值作为事件 ID,通过整数类型来区分不同的事件。这种方式在性能上较为高效,适合需要高性能的场景,例如与服务端通信或处理大量事件的情况。
高性能:使用整数作为事件 ID,查询和分发效率高。
类型安全:通过枚举定义事件类型,避免了字符串或类型作为事件 ID 的潜在错误。
适合与服务端通信:适合与服务端的 Protobuf 或带有消息 ID 的长连接通信。
using UnityEngine;
using QFramework;
public class EnumEventExample : MonoBehaviour
{
public enum TestEvent
{
Start,
TestOne,
End,
}
public enum TestEventB
{
Start = TestEvent.End, // 为了保证每个消息 ID 唯一,需要头尾相接
TestB,
End,
}
void Start()
{
EnumEventSystem.Global.Register(TestEvent.TestOne, OnEvent);
}
void OnEvent(int key, params object[] obj)
{
switch (key)
{
case (int)TestEvent.TestOne:
Debug.Log(obj[0]);
break;
}
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
EnumEventSystem.Global.Send(TestEvent.TestOne, "Hello World!");
}
}
private void OnDestroy()
{
EnumEventSystem.Global.UnRegister(TestEvent.TestOne, OnEvent);
}
}
高性能:使用整数作为事件 ID,查询和分发效率高。
类型安全:通过枚举定义事件类型,避免了字符串或类型作为事件 ID 的潜在错误。
适合与服务端通信:适合与服务端的 Protobuf 或带有消息 ID 的长连接通信。
StringEventSystem
是 QFramework 提供的一种基于字符串的事件系统。它使用字符串作为事件 ID,通过字符串来区分不同的事件。这种方式在灵活性上较高,但性能相对较低。
灵活性高:使用字符串作为事件 ID,便于与其他脚本层(如 Lua、ILRuntime、PlayMaker)通信。
性能一般:字符串比较和分发效率相对较低。
适合与其他脚本层通信:适合与 Lua、ILRuntime 等脚本层通信。
using UnityEngine;
using QFramework;
public class StringEventSystemExample : MonoBehaviour
{
void Start()
{
StringEventSystem.Global.Register("TEST_ONE", () =>
{
Debug.Log("TEST_ONE");
}).UnRegisterWhenGameObjectDestroyed(gameObject);
// 事件 + 参数
StringEventSystem.Global.Register("TEST_TWO", (count) =>
{
Debug.Log("TEST_TWO:" + count);
}).UnRegisterWhenGameObjectDestroyed(gameObject);
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
StringEventSystem.Global.Send("TEST_ONE");
StringEventSystem.Global.Send("TEST_TWO", 10);
}
}
}
TypeEventSystem
是 QFramework 提供的一种基于类型的事件系统。它使用类型作为事件 ID,通过类型来区分不同的事件。这种方式在性能上较好,但使用反射,CPU 性能相对较低。
事件体定义简洁:使用类型作为事件 ID,定义简洁。
支持 struct:支持 struct 类型,获得较好的内存性能。
使用反射:使用反射,CPU 性能相对较低。
using UnityEngine;
using QFramework;
public class TypeEventSystemExample : MonoBehaviour
{
void Start()
{
TypeEventSystem.Global.Register(OnTestEvent);
}
void OnTestEvent(TestEvent e)
{
Debug.Log(e.Message);
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
TypeEventSystem.Global.Send(new TestEvent { Message = "Hello World!" });
}
}
private void OnDestroy()
{
TypeEventSystem.Global.UnRegister(OnTestEvent);
}
}
public class TestEvent
{
public string Message { get; set; }
}
EasyEvent
是 QFramework 提供的一种简单易用的事件系统。它提供了方便的事件注册和分发机制,适合通用工具的开发。
方便易用:开发效率高,使用简单。
CPU 性能、内存性能较好:接近委托,性能较好。
功能有限:功能相对有限,适合通用工具的开发。
using UnityEngine;
using QFramework;
public class EasyEventExample : MonoBehaviour
{
void Start()
{
EasyEventSystem.Global.Register("TEST_ONE", () =>
{
Debug.Log("TEST_ONE");
}).UnRegisterWhenGameObjectDestroyed(gameObject);
// 事件 + 参数
EasyEventSystem.Global.Register("TEST_TWO", (count) =>
{
Debug.Log("TEST_TWO:" + count);
}).UnRegisterWhenGameObjectDestroyed(gameObject);
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
EasyEventSystem.Global.Send("TEST_ONE");
EasyEventSystem.Global.Send("TEST_TWO", 10);
}
}
}
TypeEventSystem:
事件体定义简洁
比较适合用于设计框架
支持 struct 获得较好内存性能
使用反射,CPU 性能相对比较差
EasyEvent
方便、易用、开发效率高
CPU 性能、内存性能较好,接近委托
功能有限
比较适合设计通用解决工具,比如通用背包、全局生命周期触发等
StringEventSystem、TypeEventSystem 的底层由 EasyEvent 实现
EnumEventSystem
使用枚举作为事件 id,比较适合和服务端的 protobuf 或带有消息 id 的长链接通信
性能较好
枚举用于定义消息体有维护成本
StringEventSystem
使用字符串作为事件 id,比较适合和其他脚本层通信,比如 Lua、ILRuntime、PlayMaker 等。
性能一般
目前官方推荐使用 TypeEventSystem 和 EasyEvent 这两个工具。