
Install via UPM
Add to Unity Package Manager using this URL
https://www.pkglnk.dev/utils.git README Markdown
Copy this to your project's README.md
## Installation
Add **Utils** to your Unity project via Package Manager:
1. Open **Window > Package Manager**
2. Click **+** > **Add package from git URL**
3. Enter:
```
https://www.pkglnk.dev/utils.git
```
[](https://www.pkglnk.dev/pkg/utils)Dependencies (2)
Used By (1)
README
Utils Module
Monoreopo下其他模块内提取的公共部分。
主要内容
1. PropertyDesc - 轻松访问Unity的SerializedProperty
void Foo(SerializedProperty property)
{
var desc = property.GetPropertyDesc();
print(desc.type);
print(desc.value);
print(desc.parent);
}
[!WARNING]
不要缓存PropertyDesc,它是立即值,而SerializedProperty是可能变化的。
2. DelegateList - 高性能、适合高频注册的代理类
特性:
- 高效地注册和注销回调,0GC
- 更明确易用的接口。区分:
AddNew和AddIfNotExists,Invoke和InvokeAndClear - 注册、注销前后,保留回调的加入顺序
- 调用允许附带state(可搭配PoolableTuple使用),避免捕捉上下文
- 允许指定
exceptionMode,内部回调异常时,可选打印或抛出。适合不同的场景。
DelegateList<int> cb = new();
// register callback
cb.AddNew(LogNumber); // 1 callback
cb.AddNew(LogNumber); // 2 callbacks
// register unique callback
cb.AddIfNotExists(PrintNumber); // 3 callbacks
cb.AddIfNotExists(PrintNumber); // 3 callbacks, ignored
// register stateful callback
cb.AddNew(PrintNumberWithState);
// normal nvoke
cb.Invoke(1);
// invoke with state
using (var state = PoolableTuple.Get(3, "name"))
{
cb.Invoke(2, state);
}
// invoke then clear all registered callbacks
cb.InvokeAndClear(3);
static void LogNumber(int n) => print(n);
static void PrintNumber(int n) => print(n);
static void PrintNumberWithState(int n, object state)
{
var (i, str) = state as PoolableTuple<int, string>;
print((i, n, str));
}
3. PoolableTuple - 可复用Tuple
using (var tp = (3, "asd").ToPoolable())
{
var (age, name) = tp;
}
using (var tp = PoolableTuple.Get(3, "asd"))
{
var (age, name) = tp;
}
4. RuntimeConverter - 高性能、轻松实现动态类型转换
NodeGraph、层叠指令编辑器 及 其他低码编辑器 模块的绝配。在我自己的可视化编码模块下,省去了绝大多数装箱操作,全程无gc。
支持几乎所有用得到的转换:
- reference cast : 子类和基类间转换
- numeric cast : 数值类型间的转换
- stringify cast : ToString 以及 内置类型ParseFromString
- custom operator cast - 类型自定义转换
- enum-numberic cast - enum和数值类型间转换
- custom : 允许扩展其他转换
enum MyEnum
{
Keyword0 = 0,
}
RuntimeConverter.Convert<MyEnum,int>(MyEnum.Keyword0); // 0
RuntimeConverter.Convert<float,int>(3.2f); // 3
RuntimeConverter.Convert<float,string>(3.2f); // "3.2"
RuntimeConverter.Convert<string,int>("3.14"); // 3
5. MemberAccessHelper - 高性能成员读写
使用激进的优化策略。0GC,高效访问成员。
- 对于不同的成员类型 执行不同的策略
- 对于引用类型成员,直接使用反射Delegate读写
- 对于纯值类型成员,则锁定对象后,使用内存拷贝读写
- 对于非纯值类型成员,则使用引用map锁定后,使用内存拷贝读写
- 读写可指定编译时类型,如果类型不一致,则执行动态转换再返回
class Food
{
public float recover;
public int Cost { get; set; }
}
var food = new Food();
food.GetMemberValue<float>(nameof(recover)); // 值类型,0GC
food.GetMemberValue<double>(nameof(Cost)); // 可以使用其他类型,0GC
food.SetMemberValue(nameof(Cost), 3); // 可以写入,0GC
6. CollectionPool - 可复用集合池
支持绝大多数常用集合类型
using(CollectionPool.Get<List<int>>(out var list))
{
list.Add(2);
list.Add(23);
}// `list` will be cleared and recycled here
using(CollectionPool.Get<Stack<int>>(out var stack))
{
stack.Push(2);
stack.Push(23);
}// `stack` will be cleared and recycled here
7. ReadOnlyCollections - 只读容器
并不是真正的集合类型,而是一个个值类型的包装器。对于私有模块向外部开放只读能力的集合时,很有帮助。
支持大多数常用集合类型的包装
public class MyKlass
{
private List<int> _numbers;
public ReadOnlyList<int> Numbers => _numbers.ToReadOnly();
}
8. GlobalSettings - Unity全局配置资源基类
定义类型后,自动创建一个单例资源。节省不必要的工作
public class Foo: GlobalSettings<Foo>
{
/* Will be created at Assets/Resources/Foo.asset by default without the following overriding*/
// protected override string SavePath => "Assets/my-foo-settings.asset"; // override default save path
// protected override string SavePath => "ProjectSettings/my-foo-settings.asset"; // save as project setting
// protected override string SavePath => "Temp/my-foo-settings.asset"; // save as session-temporary setting
// protected override string SavePath => "Library/my-foo-settings.asset"; // save as long-term-temporary setting
protected override void OnCreateInstance()
{
// 首次创建时的回调
}
}
var foo = Foo.Instance;
9. SimpleList - 实用的列表容器
行为上与List`1无异。但在此基础上,支持:
- 按引用访问element
- 使用Index访问element
- 更加强大的Sort接口,游戏项目必备
- EmplacedRemoveAt,防止删除element后的批量移位
var list = new SimpleList<int>();
list.Add(3);
list.Add(32);
ref var ele = ref list[0];
ref var ele2 = ref list[^1];
list.Sort(n=>{
return Random.Range(); // 可返回任意可比较类型作为权重
});
list.EmplacedRemoveAt(0);
10. 其他Utils工具类
这里不做过多介绍
No comments yet. Be the first!