# TinyToolKit
**Repository Path**: wiit/TinyToolKit
## Basic Information
- **Project Name**: TinyToolKit
- **Description**: 汇总平时开发中的常用功能模块,例如:事件中心、界面管理、计时器、数据结点、音频管理、有限状态机、对象池、资源加载、本地化、网络等。
- **Primary Language**: C#
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 2
- **Created**: 2023-02-06
- **Last Updated**: 2023-02-06
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# TinyToolKit
TinyToolKit是一个基于Unity引擎的工具套件(基础框架),主要目的在于能规范化开发过程,提供常用功能模块,缩短项目开发时间。
主要功能模块包括:事件中心、界面管理、计时器、数据结点、音频管理、有限状态机、对象池、资源加载、本地化、网络等。
## 编辑器窗口
### TinyToolKit窗口
通过编辑器扩展实现 TinyToolKit 的编辑窗口,包含两种模式 Manager 和 Editor。
打开路径:TinyToolKit/Window/TinyToolKit
在Manager模式下,可以在编辑器运行后,实时查看各个功能模块的运行数据,例如AB包资源加载情况、计时器的运行情况、

在Editor模式下,主要功能包括:常量列表和UI配置表的编辑输出,多国语言的可视化编辑,AssetBundle资源打包。


### ShaderLab查询窗口
记录ShaderLab相关的内容,包含编译指令、渲染状态、预定义宏、矩阵变换、函数方法等内容,支持存储、查询、修改、删除的功能。

## 基础工具
### 日志输出
大量的日志打印也会影响一定的性能。通过宏定义来控制是否打印日志,可以减小性能的浪费。
**类图**
```
graph BT
A[TLogTool]-.->B[ILogTemplate]
```
**用法**
日志打印根据重要程度分为四个等级,调试,信息,警告,错误。
```c#
public enum LogLevel
{
DEBUG,//调试
INFO,//信息
WARNING,//警告
ERROR//错误
}
```
注意:日志参数的数量尽量不要超过3个,否则生成可变参数数组,产生更多的内存分配。
```c#
TLogTool.Debug("");
TLogTool.Info("");
TLogTool.Warning("");
TLogTool.Error("");
```
**编辑器添加宏定义**
日志输出可以通过宏定义来设置,可以规定哪些级别的日志可以输出,哪些级别的日志内容被屏蔽。可以在TinyToolKit窗口中进行设置。
**自定义日志模板**
日志模板类需要继承自接口TLogTool.ILogBase,实现Log方法,并调用TLogTool.SetLogTemplate()设置日志的模板即可。如果没有自定义日志模板,系统会自动调用默认的DefaultLogTemplate模板。
```
using UnityEngine;
namespace TinyToolKit
{
public class DefaultLogTemplate : TLogTool.ILogBase
{
public void Log(TLogTool.LogLevel level, object msg)
{
switch (level)
{
case TLogTool.LogLevel.DEBUG:
Debug.Log("" + msg.ToString() + "");
break;
case TLogTool.LogLevel.INFO:
Debug.Log("" + msg.ToString() + "");
break;
case TLogTool.LogLevel.WARNING:
Debug.LogWarning("" + msg.ToString() + "");
break;
case TLogTool.LogLevel.ERROR:
Debug.LogError("" + msg.ToString() + "");
break;
}
}
}
}
```
### 事件中心
为了降低各个业务模块之间的耦合度,使用一套消息通信机制很有必要。事件中心模块基于观察者模式提供了游戏事件的订阅、注销和广播的功能。
**用法**
定义事件类型,不同事件类型有自己的消息枚举,方便维护各自内部的消息事件
```
public enum MathType
{
Add
}
```
订阅事件
```
EventCenter.Subscribe(MathType.Add, Add);
```
注销事件
```
EventCenter.Unsubscribe(MathType.Add, Add);
```
广播事件
```
EventCenter.Broadcast(MathType.Add, 1, 2);
```
**注意**
事件的订阅与注销在使用生命周期内,应当成对出现。比如实体显示时订阅、隐藏时注销,界面打开时订阅、关闭时注销。
### 引用池
为了减少系统频繁地创建和销毁引用类型对象时的开销,加入引用池的模块,以实现复用引用类型对象的功能。在引用类型对象使用结束后,将其清理并缓存起来,以供后续使用。
**类图**
```
graph BT
A[TReferencePool] -.-> B[ReferenceBasePool]
B -.-> C[IReference]
```
**用法**
若要定义引用类,只需要继承IReference接口,并实现Clear方法。
```
public class ReferenceExample : IReference
{
//回收时,清理数据
public void Clear()
{
}
}
```
从引用池获取引用
```
//ReferenceExample reference = TReferencePool.Acquire(typeof(ReferenceExample)) as ReferenceExample;
ReferenceExample reference = TReferencePool.Acquire();
```
向引用池添加指定数量的引用
```
TReferencePool.Add(100);
```
将引用归还引用池
```
TReferencePool.Release(reference);
```
获取引用池内正在使用的引用个数
```
TReferencePool.GetUsingReferenceCount()
```
获取引用池内还未使用的个数
```
TReferencePool.GetUnusedReferenceCount()
```
移除引用池内指定个数的引用
```
TReferencePool.Remove(10);
```
移除引用池内所有的引用
```
TReferencePool.RemoveAll();
```
获取引用池的数量
```
TReferencePool.Count
```
清空所有引用池
```
TReferencePool.ClearAllPools();
```
### 静态类扩展
**GameObject**
获取组件,没有组件则增加
```
gameObject.GetOrAddComponent()
```
销毁自身对象
```
gameObject.DestroySelf()
```
立刻销毁自身
```
gameObject.DestroyImmediate()
```
在场景加载时,不销毁自身
```
gameObject.DontDestroyOnLoad()
```
查找子物体,如果不存在则创建
```
gameObject.FindOrCreate(name)
```
判断当前对象是否为空
```
gameObject.IsNull()
```
**Transform**
设置绝对位置的X坐标,其他方法类似
```
transform.SetPosX(x)
```
设置局部坐标的X值,其他方法类似
```
transform.SetLocalPosX(x)
```
重设局部坐标
```
transform.Reset()
```
递归遍历所有子对象,查找目标
```
transform.FindTargetInChildren(targetName)
```
设置子节点,并重设子节点局部坐标
```
transform.SetStandardChild(child)
```
查找子类对象,如果找不到则创建
```
transform.FindOrCreate(childName,isIncludeAllChildren)
```
**String**
判断是否为空或是否为空字符串
```
string.IsNullOrEmpty()
```
## 界面管理
基于UGUI封装了窗体的各种属性和方法,例如界面进入、退出、暂停、回复等功能。通过UI管理器来调用各个窗体的切换显示,并支持模态窗体显示。在窗体结束使用后不进行销毁,等待下一次的调用。资源加载方式支持Resources动态加载,或AB包加载。
>“模态”:模态对话框(Modal Dialogue Box,又叫做模式对话框),是指在用户想要对对话框以外的应用程序进行操作时,必须首先对该对话框进行响应。如单击【确定】或【取消】按钮等将该对话框关闭。
**类图**
```
graph BT
A[TUIManager]-.->B[UIFormBase]
```
**用法**
1. 所有的窗体类需要派生自UIFormBase,UIFormBase作为窗体的基类,实现了一些窗体的特性和方法,并提供了默认的实现。
- 可以重写的方法,方便在UI窗体状态发生改变的时候,更新界面
初始化窗体,只调用一次
```
void OnInit()
```
界面进入,每一次进入时都调用
```
void OnEnter()
```
界面暂停,每一次暂停时都调用
```
void OnPause()
```
界面继续,每一次继续时都调用
```
void OnResume()
```
界面退出,每一次退出时都调用
```
void OnExit()
```
- 辅助方法
打开窗体
```
UIFormBase OpenUIForm(string uiFormName)
```
关闭窗体
```
void CloseUIForm(string uiFormName)
```
关闭自身窗体
```
void Close()
```
2. 生成UI配置表,可以直接使用TinyToolKit编辑器来创建UI配置表,可以将其放在Resources文件夹内自动读取,或者通过调用方法来指定配置表。格式如下:
```json
{
"UIFormPaths": [
{
"UIFormName": "ChooseHeroForm",
"UIFormSavePath": "Assets/TinyToolKit_SimpleDemo/Resources/UIForm/ChooseHeroForm.prefab"
},
{
"UIFormName": "LoginUIForm",
"UIFormSavePath": "Assets/TinyToolKit_SimpleDemo/Resources/UIForm/LoginUIForm.prefab"
}
]
}
```
3. UI管理器
获取UI管理器
```
TUIManager uiManager = TinyTool.Instance.GetManager();
```
设置并解析UIForm的Json格式配置表
```
void SetUIFormPaths(string jsonMsg)
```
打开窗体
```
UIFormBase OpenUIForm(string uiFormName)
```
关闭窗体
```
void CloseUIForm(string uiFormName)
```
获取指定窗体
```
UIFormBase GetUIForm(string uiFormName)
```
关闭所有窗体
```
void CloseAllUIForms()
```
## 计时器
**功能**
高效便捷计时器工具,定时任务可循环、可替换、可取消。
协程定时的弊端:取消定时,循环操作,多个协程管理等不方便,依赖于MonoBehaviour,不能扩展到其他地方。
**类图**
```
graph BT
A[TTimerManager]-.->B[TimerTask]
```
**用法**
定时管理器的相关操作
获取定时管理器
```
TTimerManager timerManager = TMainManager.Instance.GetManager();
```
添加定时任务,返回当前定时任务的ID号,回调方法callback在每一次计时任务完成后,都会调用一次
```
int AddTimerTask(Action callback,float duration,TimerUnit timerUnit = TimerUnit.Second ,int repeatCount = 1)
int AddTimerTask(Action callBack,T obj, float duration, int repeatCount = 1)
```
暂停定时任务
```
bool PauseTimerTask(int taskID)
```
恢复定时任务
```
bool ResumeTimerTask(int taskID)
```
删除定时任务
```
bool DeleteTimerTask(int taskID)
```
替换定时任务
```
bool ReplaceTimerTask(int taskID, Action callback, float duration, TimerUnit timerUnit = TimerUnit.Second, int repeatCount = 1)
```
添加帧定时任务
```
int AddTimeTaskByFrame(Action callback, int frameCount, int repeatCount = 1)
int AddTimeTaskByFrame(Action callBack,T obj,int frameCount, int repeatCount = 1)
```
暂停帧定时任务
```
bool PauseTimerTaskByFrame(int taskID)
```
恢复帧定时任务
```
bool ResumeTimerTaskByFrame(int taskID)
```
删除帧定时任务
```
bool DeleteTimerTaskByFrame(int taskID)
```
替换帧定时任务
```
bool ReplaceTimerTaskByFrame(int taskID, Action callback, int frameCount, int repeatCount = 1)
```
根据任务ID获取任务的状态
```
TaskState GetTaskState(int taskID)
```
定时器拓展方法
```
string ConvertSecondsToTime(int secondTime)
string GetNowLocalTime()
int GetYear()
int GetMonth()
int GetDay()
int GetWeek()
int GetHour()
int GetMinute()
int GetSecond()
```
## 数据结点
存储游戏运行中的数据,将任意类型的数据以树状结构进行存储
**类图**
```
graph BT
A[TDataNodeManager]-.->B[DataNode]
B -.-> C[TinyData]
```
**用法**
使用该方法进行存储的数据,需要继承自TinyData类,例如:
```
public class T_Int : TinyData
{
public T_Int(int value):base(value)
{
}
}
public class T_String : TinyData
{
public T_String(string value):base(value)
{
}
}
```
也可以存储自定义的类,为了方便编辑器面板查看具体值,可以重写ToString方法,例如:
```
public class MyHero
{
public string name;
public bool sex;
public int level;
}
public class T_MyHero : TinyData
{
public T_MyHero(MyHero value):base(value)
{
}
public override string ToString()
{
return $"name:{Value.name},sex:{Value.sex},level:{Value.level}";
}
}
```
获取数据结点管理器
```
TDataNodeManager dataNodeManager = TinyTool.Instance.GetManager();
```
管理器的主要方法示例:
```
//注意这里的路径都需要写全路径,但不用包含"Root"
dataNodeManager.SetData("Player.Name.FirstName",new T_String("Yu"));
dataNodeManager.GetData("Player.Name.LastName");
dataNodeManager.GetNode("Player.Name");
dataNodeManager.RemoveNode("Player.Name");
```
结点类的主要方法示例:
```
DataNode player = root.GetChildNode("Player");
player.AddChildNode("Name", new T_String("Lili"));
player.HasChildNode("Name");
player.RemoveChildNode("Name");
player.GetData();
```
## 音频管理
音频管理器将程序中使用的音频分为了三类:背景音乐、特效音效、UI音效。
主要实现功能:
- 控制音乐的播放控制
- 全局音量管理
- 背景音乐的淡入淡出效果
- 可跨场景持久化播放
- 是否允许同时播放相同的音效
- 音频缓存池
- 可以设置2D\3D音效,将其绑定在目标对象身上
**用法**
获取音频管理器
```
TSoundManager soundManager = TinyTool.Instance.GetManager();
```
播放音频
```
int PlayMusic(...)
int PlayFxSound(...)
int PlayUISound(...)
```
暂停音频
```
void Pause(...)
void PauseAllMusic(...)
void PauseAllFxSounds(...)
void PauseAllUISounds(...)
void PauseAll(...)
```
恢复播放音频
```
void Resume(...)
void ResumeAllMusic(...)
void ResumeAllSounds(...)
void ResumeAllUISounds(...)
void ResumeAll(...)
```
停止播放音频
```
void Stop(...)
void StopAllMusic(...)
void StopAllFxSounds(...)
void StopAllUISounds(...)
void StopAll(...)
```
获取音频AudioItem信息
```
void GetMusicAudio(...)
void GetFxSoundAudio(...)
void GetUISoundAudio(...)
```
## 有限状态机
**定义**
有限状态机(FSM),是指在不同阶段呈现不同运行状态的系统,这些状态是有限的,不重叠的。这样的系统在某一时刻一定会处于其中所有状态中的一个状态,此时它接收一部分输入,并产生相应的响应,并且迁移到可能的状态。提供了描述和控制应用逻辑的强大功能,常常应用于控制NPC的行为,图形界面管理等。FSM可以使得各个状态之间相互独立,互不影响,避免了状态和状态之间的耦合度,具有规则简单,可读性和可验证性等优点。
**功能**
FSM管理器提供创建、使用、切换和销毁状态机的功能。允许同一个有限状态机被多个实例运用,但需要注意有限状态机的名称不能重复。
**类图**
```
graph BT
subgraph FSM系统
A[FsmSystem]-.->B[IFsm]
A[FsmSystem]-.->C[FsmBase]
end
A-->D[FsmState]
subgraph FSM管理器
E[FsmManager]-.->F[IFsmManager]
E[FsmManager]-.->G[ManagerBase]
E[FsmManager]-->A
end
```
**用法**
- 有限状态机管理器的相关操作
1. 获取有限状态机管理器
```
TFsmManager fsmManager = TinyTool.Instance.GetManager();
```
2. 创建有限状态机实例
创建有限状态机,持有者为owner,类型为T,有限状态机实例名称为name,states是有限状态机的状态
```
IFsm CreateFsm(string name, T owner, params FsmState[] states) where T : class
IFsm CreateFsm(string name, T owner, List> states) where T : class
```
3. 判断是否存在有限状态机
```
bool HasFsm(string name) where T : class
bool HasFsm(Type ownerType, string name)
```
4. 获取有限状态机
```
IFsm GetFsm(string name) where T : class
FsmBase GetFsm(Type ownerType, string name)
FsmBase[] GetAllFsms()
void GetAllFsms(List fsms)
```
5. 销毁有限状态机
```
bool DestroyFsm(FsmBase fsm);
bool DestroyFsm(Type ownerType, string name);
bool DestroyFsm(string name) where T : class;
bool DestroyFsm(IFsm fsm) where T : class;
```
6. 获取有限状态机的数量
```
int FsmCount { get; }
```
- 有限状态机的状态相关操作
1. 定义有限状态机的状态
有限状态机的状态均派生自FsmState,T是该有限状态机的持有者类型。
```
using UnityEngine;
using TinyToolKit;
using TinyToolKit.FSM;
public class PatrolState : FsmState
{
//有限状态机开启的时候调用
protected internal override void OnInit()
{
base.OnInit();
TLogTool.Debug("Patrol_OnInit");
}
//进入该状态的时候调用
protected internal override void OnEnter()
{
base.OnEnter();
TLogTool.Debug("Patrol_OnEnter");
}
//离开该状态的时候调用
protected internal override void OnLeave()
{
base.OnLeave();
TLogTool.Debug("Patrol_OnLeave");
}
//本状态在轮询的时候调用
protected internal override void OnUpdate()
{
base.OnUpdate();
TLogTool.Debug("Patrol_OnUpdate");
}
//该有限状态机销毁的时候调用
protected internal override void OnDestroy()
{
base.OnDestroy();
TLogTool.Debug("Patrol_OnDestroy");
}
}
```
2. 有限状态机的相关操作
开启有限状态机
```
void Start() where T2 : FsmState
void Start(Type stateType)
```
切换有限状态机的状态
```
void ChangeState() where T2 :FsmState
void ChangeState(Type stateType)
```
判断是否存在状态
```
bool HasState() where T2 : FsmState
bool HasState(Type stateType)
```
获取有限状态机的状态
```
T2 GetState() where T2 : FsmState
FsmState GetState(Type stateType)
FsmState[] GetAllStates()
void GetAllStates(List> results)
```
切换有限状态机的状态
```
void ChangeState(Type stateType)
void ChangeState() where T2 : FsmState
```
状态机的数据处理
```
bool HasData(string name)
object GetData(string name)
T2 GetData(string name) where T2 : class
void SetData(string name, object data)
void SetData(string name, T2 data) where T2 : class
bool RemoveData(string name);
```
- 常用属性
```
// 获取有限状态机的名称
string Name { get; }
// 获取有限状态机的完整名称
string FullName { get; }
// 获取有限状态机持有者
T Owner { get; }
// 获取有限状态机的状态数量
int FsmStateCount { get; }
// 判断该状态机是否正在运行
bool IsRunning { get; }
// 判断该状态机是否被销毁
bool IsDestroyed { get; }
// 获取当前有限状态机的状态
FsmState CurrentState { get; }
// 获取当前状态的全名
string CurrentStateName { get; }
// 获取当前状态持续时间
float CurrentStateTime { get; }
```
## 对象池
对象池管理器,提供了对象缓存池的功能,避免频繁的创建和销毁各种对象,减少程序性能消耗。
**类图**
```
graph BT
A[TObjectPool]-- 实现接口 -->B[IObjectPool]
A-.->C[ObjectPoolItem]
D[TObjectManager]-.->A
D-- 实现接口 -->E[IObjectManager]
```
**用法**
1. 获取对象池管理类
```
TObjectPoolManager objectPoolManager = TinyToolKit.TinyTool.Instance.GetManager();
```
2. 对象池管理类的方法
判断是否已经存在poolName对应的对象池
```
bool HasObjectPool(string poolName)
```
根据对象池名返回TObjectPool
```
TObjectPool GetObjectPool(string poolName)
```
创建对象池
```
TObjectPool CreateObjectPool(...)
```
销毁对象池
```
bool DestroyObjectPool(string poolName)
```
实例化对象池中的对象
```
GameObject SpawnObject(string poolName)
```
实例化对象池中的对象
```
GameObject SpawnObject(...)
```
回收对象池中的对象
```
bool RecycleObject(GameObject obj)
```
3. 对象池类的方法
产生对象
```
T Spawn()
```
回收对象
```
bool Recycle(T obj)
```
优先释放未被使用的对象,如果释放数量大于剩余未使用的数量,则释放所有未使用的
```
void Release(int releaseCount)
```
释放所有未被使用的对象
```
void ReleaseAllUnused()
```
间隔一定时间,自动释放未使用的对象
```
void ActiceAutoRelease(float time)
```
取消自动释放
```
void DeacticeAutoRelease()
```
## 资源加载
提供两种资源加载的方式:Resources加载、AB包加载
Resources加载主要功能:
- 资源缓存池,加载过的资源会被缓存起来,下一次加载可以直接从缓存池中获取
- 提供同步、异步加载资源的方法
AB包加载:
- 资源缓存池
- 同步、异步加载本地资源
- 支持预加载远程资源
- 提供资源的编辑器模式,仅可在编辑器内使用。为了开发时的方便,避免反复构建AssetBundle,该模式下,所有资源利用UnityEditor.AssetDatabase直接从磁盘加载资源,即使保存勾选此选项,在发布后此选项也将失效
**用法**
### Resources 管理器
主要封装了Resources动态加载资源的方法,可以同步或异步加载资源,同时添加了缓存池功能。
获取Resources管理器
```
TResourcesManager resourcesManager = TinyTool.Instance.GetManager();
```
加载资源
```
Object LoadAsset(string resPath)
T LoadAsset(string resPath)
```
加载指定文件夹路径下的所有的资源
```
Object[] LoadAllAssets(string resPath)
T[] LoadAllAssets(string resPath)
```
异步加载资源
```
void LoadAssetsAsync()
```
卸载资源
```
void UnloadUnusedAssets()
```
### AssetBundle 管理器
AB包资源加载分为:编辑器模拟模式 和 AB包加载模式。
**编辑器模拟模式:** 模拟加载AB包资源,并没有真正的去加载AB包,而是通过编辑器API直接加载Assets目录下的资源,该模式在发布后将会失效。编辑器模式可以预演发布状态下的各种情况,如资源异步加载等,方便调试发布时的相关问题。在开发阶段,解决了频繁打AB包资源的问题,提高了开发效率。
**AB包加载模式:** 该模式需要预先构建并准备完成AB包资源,是真机测试阶段使用的模式。基于引用计数,简化AB包资源的加载和卸载。有两种加载AB包资源的方式:本地加载、服务器加载(非缓存下载,缓存加载)。支持同步或异步加载AB包资源对象。支持AB包版本对比,提供简单的加密解密AB包资源的方式,避免AB包资源被轻易破解。注意:服务器加载AB包资源的缓存加载模式不支持加载加密的AB包资源。
获取AssetBundle管理器
```
TAssetBundleManager assetBundleManager = TinyTool.Instance.GetManager();
```
加载本地AB配置表
```
AssetBundleConfig LoadABConfig(string targetPath)
```
下载AB包配置表
```
void LoadABConfigAsync(...)
```
异步加载AB包资源,可以将AB包下载至本地,或者加载到内存中
```
void LoadABResAsync(...)
```
获取当前下载的进度
```
float GetDownloadProgress()
```
同步加载本地资源或缓存资源,如果缓存中没有该AB包,会尝试从本地加载
```
T LoadResource(...)
```
**异步加载Asset资源的方法消耗性能有待改善**
初始化用于异步加载资源的协程,需要在异步加载Asset方法之前调用
```
void InitCoroutine(ReadPathType readPathType,string path)
```
异步加载本地资源,可以同时异步加载多个资源
```
void LoadLocalResAsync(...)
```
释放资源
```
//AssetBundle.Unload(true) 可能会导致克隆出来的预制体对象丢失贴图和材质
//在Instantiate将运存中的预制体克隆到内存后,根据依赖关系找到对应的贴图和材质。所以当预制体的AB包卸载后,丢失引用,但克隆的对象还在。
//如果cache为true,则资源会被缓存下来,等待下一次调用
//如果cache为false,当引用次数为0时,obj资源会被置空,对应的AB包资源也会被完全卸载
bool ReleaseResource(Object obj, bool cache = true)
```
## 本地化
提供本地化功能,主要解决一个程序需要实现多种语言切换的功能。
**用法**
获取本地化管理器
```
TLocalizationManager localizationManager = TinyTool.Instance.GetManager();
```
自定义模式下,设置翻译配置表
```
void SetLanTranslates(Language lan, string jsonMsg)
```
切换至本机系统语言
```
bool ChangeSystemLanguage()
```
切换至指定语言
```
bool ChangeLanguage(Language lan)
```
根据关键词判断是否存在该翻译
```
bool HasTranslation(string key)
```
根据关键词得到该翻译
```
string GetTranslation(string key)
```
添加翻译
```
bool AddTranslation(string key, string value)
```
根据关键词移除翻译
```
bool RemoveTranslation(string key)
```
提供两个回调方法,在切换语言时、切换语言结束后的回调函数
```
public event Action OnLanguageChanged;
public event Action OnLanguageChangedLater;
```
## 网络
- 通过UDP广播自动获取局域网IP地址
- 提供使用Socket长连接功能,支持TCP协议,可以同时建立多个客户端与服务器进行通信,主要支持局域网开发
> UDP广播:与单播的区别就是IP地址不同,广播使用广播地址,将信息发送到在同一个广播网络上的每一个主机,但本地广播不会被路由器转发的。
## 扩展工具
### Xml 序列化
定义:序列化,又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制。其目的是以某种存储形式使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方。简单来说就是**将对象保存到文件中**。
如Unity的场景文件和预制体默认就是以二进制的文件保存在工程目录下。
**1. 序列化**
将类序列化为Xml文件,需要引用命名空间:System.Xml.Serialization
需要为序列化的类,加上System.Serializable的标签
[XmlAttribute()] 序列化属性
[XmlElement()] 序列化字段
[XmlArray()] 序列化数组
```
[System.Serializable]
public class TestSerialize
{
[XmlElement("Id")]
public int Id { get; set; }
[XmlElement("Name")]
public string Name { get; set; }
[XmlArray("IntValueList")]
public List IntValueList { get; set; }
}
```
**2. 常用方法**
Xml序列化
```
TinyUtility.XML.XmlSerialize(TinyUtility.Path.GetStreamingAssetsPath() + "XMLtest.xml", test);
```
Xml反序列化
```
TestSerialize test = TinyUtility.XML.XmlDeSerialize(TinyUtility.Path.GetStreamingAssetsPath() + "XMLtest.xml");
```
````
TestSerialize test = TinyUtility.XML.XmlDeSerialize(typeof(TestSerialize),TinyUtility.Path.GetStreamingAssetsPath() + "XMLtest.xml") as TestSerialize;
````
**3. 自定义XML函数集模板**
修改DefaultXmlTemplate脚本,可以自定义XML函数集模板
```
namespace TinyToolKit
{
///
/// 默认的XML函数集辅助模板
///
public class DefaultXmlTemplate : TinyUtility.XML.IXmlTemplate
{
public void XmlSerialize(string savePath, object obj)
{
//TODO
}
public T XmlDeSerialize(string targetPath) where T : class
{
//TODO
}
public object XmlDeSerialize(Type objectType, string targetPath)
{
//TODO
}
}
}
```
### Json 函数集
**1. 常用方法**
```
// 将对象序列化为JSON字符串
string ToJson(object obj);
// 将Json字符串反序列化为对象
T ToObject(string json);
// 将JSON字符串反序列化为对象
object ToObject(Type objectType, string json);
```
示例:
```
Test01 test02 = TinyUtility.Json.ToObject(str);
```
```
string str = TinyUtility.Json.ToJson(test);
```
**2. 自定义Json函数集模板**
通过修改DefaultJsonTemplate可以自定义Json函数集格式
```c#
public class DefaultJsonTemplate : TinyUtility.Json.IJsonTemplate
{
public string ToJson(object obj)
{
return JsonUtility.ToJson(obj);
}
public T ToObject(string json)
{
return JsonUtility.FromJson(json);
}
public object ToObject(Type objectType, string json)
{
return JsonUtility.FromJson(json,objectType);
}
}
```
# 特别感谢
Ellan Jiang 的 [GameFramework](https://github.com/EllanJiang) 框架
凉鞋 的 [Qframework](https://qframework.cn/intro) 框架