Unclaimed Package Is this your package? Claim it to unlock full analytics and manage your listing.
Claim This Package

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

Style
Preview
pkglnk installs badge
## 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
```

[![pkglnk](https://www.pkglnk.dev/badge/utils.svg?style=pkglnk)](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
  • 更明确易用的接口。区分:AddNewAddIfNotExistsInvokeInvokeAndClear
  • 注册、注销前后,保留回调的加入顺序
  • 调用允许附带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工具类

这里不做过多介绍

Comments

No comments yet. Be the first!