Skip to content

Commit

Permalink
更新 1.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Giresharu committed Oct 14, 2022
1 parent 91bf3c4 commit 3b59b77
Show file tree
Hide file tree
Showing 7 changed files with 453 additions and 104 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/Assets/Runtime/.idea
434 changes: 356 additions & 78 deletions Assets/Runtime/HomoAddressable.cs

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions Assets/Runtime/HomoAddressableConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#if UNITY_EDITOR || DEVELOPMENT_BUILD

using UnityEngine;

[CreateAssetMenu(fileName = "HomoAddressableConfig", menuName = "Addressables/HomoAddressableConfig", order = 1)]
public class HomoAddressableConfig: ScriptableObject {
public enum LogLevel {
None, Log, Warning, Error
}
public LogLevel SucceededLogLevel = LogLevel.Log;
public LogLevel CanceledLogLevel = LogLevel.Warning;
public LogLevel TimeoutLogLevel = LogLevel.Warning;
public LogLevel FailedLogLevel = LogLevel.Error;

public LogLevel ReleaseSenderNullWarning = LogLevel.Warning;
}
#endif
11 changes: 11 additions & 0 deletions Assets/Runtime/HomoAddressableConfig.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions Assets/package.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
{
"name": "com.gsr.homo_addressable",
"version": "1.0.0",
"version": "1.1.0",
"displayName": "HomoAddressable",
"description": "an Addressable auto-release solution",
"dependencies": {
"com.unity.addressables": "1.19.19",
"com.cysharp.unitask": "2.3.1"
},
"keywords": [
"Addressable",
"Addressables",
"AssetBundle",
"GSR"
"GSR",
"Homo",
"HomoAddressable"
],
"author": {
"name": "Giresharu",
"email": "[email protected]",
"url": "https://giresharu.github.io"
}
},
"changelogUrl": "https://github.com/Giresharu/HomoAddressable/blob/master/CHANGELOG.md",
"documentationUrl": "https://github.com/Giresharu/HomoAddressable/blob/master/README.md",
"license": "MIT",
"licensesUrl": "https://github.com/Giresharu/HomoAddressable/blob/master/LICENSE.md"
}
17 changes: 17 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
ChangeLog
---

## [1.1.0](https://github.com/Giresharu/HomoAddressable#%E9%80%9A%E8%BF%87-openupm-%E5%AE%89%E8%A3%85)

### 特性

* 各个异步读取功能增加超时功能;
* 各个异步读取功能增加回调功能,分为超时回调、取消回调以及失败回调;
* 各个同步读取功能增加失败回调功能;
* 增加读取成功、超时、取消、失败的 Debug.Log 提示,并提供关闭提示或修改提示等级的设置。

### 已知Bug

* 超时的精确性有一点问题,取消读取会比预想要晚一些。

## [1.0.0](https://github.com/Giresharu/HomoAddressable/releases/tag/1.0.0)
63 changes: 41 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ HomoAddressable
===
[![Releases](https://img.shields.io/github/release/Giresharu/HomoAddressable.svg)](https://github.com/Giresharu/HomoAddressable/releases)

一个更人性化的 Addressable 资源读取解决方案。人的学名前缀便是 Homo ,本着以人为本的思想创建了这个工具,所以给它起名叫做 HomoAddressable。(大嘘)
一个更人性化的 Addressables 资源读取解决方案。人的学名前缀便是 Homo ,本着以人为本的思想创建了这个工具,所以给它起名叫做 HomoAddressable。(大嘘)

* 自动管理 LoadAsset 所生成的 AsyncOperationHandle ,在读取资源的 GameObject 实例销毁时自动释放;
* 使用 Unitask 作为异步的方式,让读取资源后的回调更加简单;

## 更新日志

查看 [CHANGELOG](./CHANGELOG.md)

## 目录

- [依赖](#依赖)
Expand All @@ -24,12 +28,13 @@ HomoAddressable
- [HomoAddressable.LoadAssetHandle](#homoaddressableloadassethandle)
- [HomoAddressable.InstantiateAsync](#homoaddressableinstantiateasync)
- [HomoAddressable.LoadSceneAsync](#homoaddressableloadsceneasync)
- [Debug.Log 提示与设置](#DebugLog-提示与设置)
- [许可证](#许可证)


依赖
---
本工具依赖于 [com.unity.addressable](https://docs.unity3d.com/Packages/[email protected]/manual/AddressableAssetsGettingStarted.html)[com.cysharp.unitask](https://github.com/Cysharp/UniTask) 运行,请确保项目已安装这两个插件。
本工具依赖于 [com.unity.addressables](https://docs.unity3d.com/Packages/[email protected]/manual/AddressableAssetsGettingStarted.html)[com.cysharp.unitask](https://github.com/Cysharp/UniTask) 运行,请确保项目已安装这两个插件。

安装
---
Expand Down Expand Up @@ -107,54 +112,60 @@ public class Test : MonoBehaviour, IOnDestroyAssetLoad {

### 关于非 MonoBehaviour 类

非 MonoBehaviour 类不存在 OnDestroy ;而 Addressable.Release 函数在析构函数中不产生作用。对此我的建议是:
非 MonoBehaviour 类不存在 OnDestroy ;而 Addressables.Release 函数在析构函数中不产生作用。对此我的建议是:
* 如果非 MonoBehaviour 类是一个需要读取资源的数据结构,请让使用此数据结构的 MonoBehaviour 类来承当绑定资源与释放的作用;
* 如果该类是一个需要读取资源并使用的静态类,则建议使用原生 Addressable 来进行手动加载与释放。
* 如果该类是一个需要读取资源并使用的静态类,则建议使用原生 Addressables 来进行手动加载与释放。

HomoAddressable.LoadAssetAsync<T>
---

```cs
async UniTask<T> LoadAssetAsync<T>(this IOnDestroyAssetLoad bindObj, string path, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken token = default);
async UniTask<T> LoadAssetAsync<T>(this IOnDestroyAssetLoad bindObj, string path, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, Action failedCallback = null, Action timeoutCallback = null, Action canceledCallback = null, int millisecondsTimeout = 0, CancellationToken token = default);

async UniTask<T> LoadAssetAsync<T>(this IOnDestroyAssetLoad bindObj, AssetReference reference, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken token = default);
async UniTask<T> LoadAssetAsync<T>(this IOnDestroyAssetLoad bindObj, AssetReference reference, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, Action failedCallback = null, Action timeoutCallback = null, Action canceledCallback = null, int millisecondsTimeout = 0, CancellationToken token = default);
```
* 其中 `bindObj` 为资源所绑定的实现了 IOnDestroyAssetLoad 接口的 MonoBehaviour 实例,当我们销毁这个实例时,这次加载的资源也会自动被释放;
* `path` 即为资源在 Addressable 中的路径,通常来说,只要你不去修改,它默认就是资源在项目中的路径,可以方便地搭配诸如 Odin 等插件进行方便地选择;
* `path` 即为资源在 Addressables 中的路径,通常来说,只要你不去修改,它默认就是资源在项目中的路径,可以方便地搭配诸如 Odin 等插件进行方便地选择;
* 也可以不用路径而是用重载的 AssetReference 来读取资源;
* `progress` 是一个返回资源读取进度的委托
* `progress` 可以使用原生的 Progress 类
* `timing` 表示异步操作在主线程循环的哪一步执行,具体可以参考 UniTask 的文档;
* `token` 则是取消信号,当我们不填或者填写 default 时,它会被视为 bindObj 的 GetCancellationTokenOnDestroy ,如果在读取完之前,所绑定的 MonoBehaviour 就被销毁,则任务会被取消。
* `failedCallback` 是读取失败时的回调, `timeoutCallback` 是读取超时的回调,而 `canceledCallback` 则是读取被取消时的回调;
* `millisecondsTimeout` 是设置超时时间,单位为毫秒。当其为0时,表示不限时。
* `token` 则是取消信号,供我们从外部取消。无论我们是否填写,当绑定的 MonoBehaviour 实例被销毁时,为了防止内存泄漏,都会取消当前的读取。

是用这个函数读取资源时,如果该 MonoBehaviour 实例已经读取过同一资源,则会跳过异步任务直接获取结果。虽然 Addressable 本身就有防止重复读取的优化,但是我们连 Addressable 的过程都跳过了,实乃省中之省。
是用这个函数读取资源时,如果该 MonoBehaviour 实例已经读取过同一资源,则会跳过异步任务直接获取结果。虽然 Addressables 本身就有防止重复读取的优化,但是我们连 Addressables 的过程都跳过了,实乃省中之省。

```cs
TextAsset data;
float data_progress;

async void Load() {
data = await HomoAddressable.LoadAssetAsync<TextAsset>(this, "Asset/Data/data.csv",new Progress<float>(progress =>data_progress = progress));
data = await HomoAddressable.LoadAssetAsync<TextAsset>(this, "Assets/Data/data.csv",new Progress<float>(progress =>data_progress = progress),failedCallback: FailedCallback);
}

void FailedCallback(){
Debug.log("Failed Callback.");
}
```
使用扩展方法的形式:
```cs
data = await this.LoadAssetAsync<TextAsset>("Asset/Data/data.csv",new Progress<float>(progress =>data_progress = progress));
data = await this.LoadAssetAsync<TextAsset>("Assets/Data/data.csv",new Progress<float>(progress =>data_progress = progress),failedCallback: FailedCallback);
```

HomoAddressable.LoadAsset<T>
---
同步版本的 LoadAssetAsync<T>,由于是同步的,它不像异步版本拥有那么多参数:
```cs
T LoadAsset<T>(this IOnDestroyAssetLoad bindObj, string path);
T LoadAsset<T>(this IOnDestroyAssetLoad bindObj, AssetReference reference);
T LoadAsset<T>(this IOnDestroyAssetLoad bindObj, string path, Action failedCallback = nul);
T LoadAsset<T>(this IOnDestroyAssetLoad bindObj, AssetReference reference, Action failedCallback = nul);
```

大多异步加载函数都大同小异有同步的版本,不多赘述,可以自己 F12 观看。

HomoAddressable.LoadAssetHandle<T>
---

我们还提供了原本的 Addressable.LoadAssetAsync<T> 的封装,原汁原味,供希望读取资源的静态函数看起来整整齐齐的强迫症使用。
我们还提供了原本的 Addressables.LoadAssetAsync<T> 的封装,原汁原味,供希望读取资源的静态函数看起来整整齐齐的强迫症使用。
```cs
AsyncOperationHandle<T> LoadAssetHandle<T>(string path);

Expand All @@ -169,12 +180,13 @@ HomoAddressable.InstantiateAsync
加载一个预制体所依赖的资源,并实例化之。

```cs
async UniTask<GameObject> InstantiateAsync(string path, Transform parent = null, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken token = default);
async UniTask<GameObject> InstantiateAsync(string path, Transform parent = null, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, Action failedCallback = null, Action timeoutCallback = null, Action canceledCallback = null, int millisecondsTimeout = 0, CancellationToken token = default);

async UniTask<GameObject> InstantiateAsync(AssetReferenceGameObject reference, Transform parent = null, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken token = default);
async UniTask<GameObject> InstantiateAsync(AssetReference reference, Transform parent = null, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, Action failedCallback = null, Action timeoutCallback = null, Action canceledCallback = null, int millisecondsTimeout = 0, CancellationToken token = default);
```

大部分参数都如同 LoadAssetAsync ,`parent` 则是实例化时设置的父结点。
* 大部分参数都如同 LoadAssetAsync ,`parent` 则是实例化时设置的父母结点。
* 实例化的 GameObject 存在于场景树上,所以并没有绑定 HomoBehaviour 实例。所以无法同 Asset 那样从实例中的 handle 去查找已经读取的资源,避免重复创建 handle 。我建议配合对象池来使用。

使用 InstantiateAsync 实例化资源时,如你所见,并不需要绑定一个 HomoBehaviour 实例。如果要释放这个预制体实例及其依赖的资源时,请使用如下函数:
```cs
Expand All @@ -186,23 +198,30 @@ HomoAddressable.LoadSceneAsync
加载一个场景实例,还可以将其生成到场景树上。

```cs
async UniTask<SceneInstance> LoadSceneAsync(string path, LoadSceneMode mode = LoadSceneMode.Single, bool activeOnLoad = true, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken token = default);
async UniTask<SceneInstance> LoadSceneAsync(string path, LoadSceneMode mode = LoadSceneMode.Single, bool activeOnLoad = true, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, Action failedCallback = null, Action timeoutCallback = null, Action canceledCallback = null, int millisecondsTimeout = 0, CancellationToken token = default);

async UniTask<SceneInstance> LoadSceneAsync(AssetReference reference, LoadSceneMode mode = LoadSceneMode.Single, bool activeOnLoad = true, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken token = default);
async UniTask<SceneInstance> LoadSceneAsync(AssetReference reference, LoadSceneMode mode = LoadSceneMode.Single, bool activeOnLoad = true, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, Action failedCallback = null, Action timeoutCallback = null, Action canceledCallback = null, int millisecondsTimeout = 0, CancellationToken token = default);
```

* `mode` 参数为 `LoadSceneMode.Single` 时,当你生成场景实例,将会先卸载现有的资源。效果就像通常的切换场景;
* `mode` 参数若为 `LoadSceneMode.Additive` ,则不会卸载现有资源,而是用增量的方式生成;
* `activeOnLoad``true` ,则加载后就生成场景实例,否则仅加载,需要生动生成。
* `activeOnLoad``true` ,则加载后就生成场景实例,否则仅加载,需要生动生成;
* 使用 AssetReference 读取时,无法读取已经读取过的场景,但是使用 path 是可以重复读取的。虽然不明白底层为何,但是我也不推荐重复去尝试生成 handle 来读取。若要多次生成到场景树上,请将返回的 SceneInstance 保存下来使用。

卸载并释放从 Addressable 加载的场景的函数为:
卸载并释放从 Addressables 加载的场景的函数为:

```cs
async UniTaskVoid ReleaseScene(this SceneInstance sceneInstance, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update);
```

该函数是异步的,但不提供取消信号。开弓没有回头箭,卸载了就别想整回来。

Debug.Log 提示与设置
---
本项目的 Debug.Log 提示仅在 Unity 编辑器中,或是 Development_Build 模式打包的项目中进行处理。
你可以在项目的 `Assets/Resources` 目录下点击右键 `Create/Addressables/HomoAddressableConfig` 来创建设置。该配置文件在 `Resources` 目录下存在多个时,仅会以其中一个为准(具体是哪个我也说不准)。你可以在该配置中更改各项 Debug 的警报级别,或者是干脆关闭。
当你在没有创建该设置的情况下尝试读取资源,将会自动创建该配置至 `Resources` 目录。

许可证
---

Expand Down

0 comments on commit 3b59b77

Please sign in to comment.