Unity3d C# 实现AA包(Addressables)资源热更新的多个包异步加载并显示加载实时进度功能(含源码)

Posted 十幺卜入

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity3d C# 实现AA包(Addressables)资源热更新的多个包异步加载并显示加载实时进度功能(含源码)相关的知识,希望对你有一定的参考价值。

前言

该功能的aa包是本地包,我这边项目的需求就是将沙盘的多场景在程序初始化的时候将所有场景实例化,不使用动态加载的方式,必然会造成程序运行的设备的负载加大,不过特定的需求就是在切换场景的过程更丝滑(如不用转圈等待)。
如果对使用统一可寻址资产系统(Addressables)还不熟悉的,可以查看我之前写的两篇博客:
Unity3d 使用统一可寻址资产系统(Addressables)入门学习保姆级教程(含工程)
Unity3d 使用统一可寻址资产系统(Addressables)实现服务器资源热更新和资源版本管理等功能(含源码)

我这边使用的版本是Unity3d 2020.3.12f1c1 和 Addressables 1.20.0。不同版本会可能会有一定的效果差异。
#效果
先来看看最终实现后的效果:

实现功能

实现过程相对比较简单的就是使用协程StartCoroutine的方式Addressables.LoadAssetAsync()加载资源包 ,资源包采用配置数组的方式进行提前配置,并实例化对象在指定节点下面。AsyncOperationHandle的PercentComplete属性来同步更新每个资源的加载进度,并将进度同步到UI的进度条图片和Text上。

UI搭建

UI的搭建较为简单,新建一个图片为进度条,将Image Type设置为Filled,FillMathod 设置为Horizontal,Fill Origin设置为 Left:

这样设置后我们只需要修改Fill Amount就是进度条的进度了。

然后再新建两个Text作为加载的提示和加载的进度即可:

AA场景包处理

关于场景包的处理,我这里是对场景的节点进行了拖拽成了预设prefab文件,然后将prefab文件添加到Addressables对应的组中,进行Addressables打包即可,这些操作已经在之前的两篇博客中有详细的介绍,这里就不介绍了。
要注意的是在Hierarchy窗口中关联的prefab节点要进行删除,为了防止误操作,最好进行版本管理(svn 或者 git)。

AA包类

这里我们新建了AA包的配置类如下:

[System.Serializable]
public class AAPack

    public string NodeName;
    public Transform ParentTran;
    public Vector3 scale = Vector3.one;

NodeName为aa包名,在Addressables Groups窗口对应填写的包名:

ParentTran为实例化到该节点的子节点,scale 为实例化后的缩放配置;可以自行添加其他配置项,如实例化的位置(position),实例化的旋转角度(eulerAngles),新增的其它配置项需要在实例化的时候新增对应参数的设置。

这里的aa包配置,我设置为数组,并将对应的需要加载的包配置如下:

加载AA包

先贴出加载和更新进度UI的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class AAPackLoader : MonoBehaviour

    public AAPack[] AAPacks;

    public Image ProcessImg;
    public Text ProcessText;

    int NowIdx = 0;
    float TotalRat = 0;
    // Start is called before the first frame update
    void Start()
    
        transform.localScale = Vector3.one;
        ProcessImg.fillAmount = 0;
        ProcessText.text = "0%"; 
        StartCoroutine(LoadAllAAPack());
    

    AsyncOperationHandle<GameObject> AO;

    IEnumerator  LoadAllAAPack() 
        for (int i = 0; i < AAPacks.Length; i++) 
            NowIdx = i;
            if (AAPacks[i] != null)
            
                AO = Addressables.LoadAssetAsync<GameObject>(AAPacks[i].NodeName);
                yield return AO; 
                if (AO.Status == AsyncOperationStatus.Succeeded)
                
                    GameObject go = Instantiate(AO.Result, Vector3.zero, Quaternion.identity); 
                    go.name = AAPacks[i].NodeName;
                    go.transform.SetParent(AAPacks[i].ParentTran == null ? this.transform : AAPacks[i].ParentTran);
                    go.transform.localPosition = Vector3.zero;
                    go.transform.localEulerAngles = Vector3.zero;
                    go.transform.localScale = AAPacks[i].scale;
                    go.SetActive(true);
                
            
        
        transform.localScale = Vector3.zero;
        Destroy(gameObject);
    

    // Update is called once per frame
    void Update()
    
        if (AAPacks.Length > 0) 
               //+1
            TotalRat = (float)(NowIdx) / (float)AAPacks.Length + AO.PercentComplete / AAPacks.Length;   //AO.GetDownloadStatus().Percent
            //Debug.Log("NowIdx:" + NowIdx + " TotalRat:" + TotalRat + "  AAPacks:" + AAPacks.Length + " Percent:" + AO.PercentComplete);
            ProcessImg.fillAmount = TotalRat;
            ProcessText.text = (TotalRat * 100).ToString("F1") + "%";
        
    

这里启动时直接开始了协程IEnumerator LoadAllAAPack进行所有包的加载,并在Update函数中对进度进行了换算和更新。在加载完成后,直接销毁了该对象,因为这个模块在程序启动时,加载了所有的场景,它的工作已经完成了,不会再执行了,所以进行了销毁。

接下来直接将需要关联的节点拖拽进入对应的框内:

并运行即可。

调试位于 nuget 包中的 C# 接口实现

【中文标题】调试位于 nuget 包中的 C# 接口实现【英文标题】:Debug C# interface implemenation located in nuget package 【发布时间】:2019-05-07 06:15:25 【问题描述】:

我有 3 个项目:

项目 A 是主项目(.NET Core Web 应用程序) 项目 B 是 NuGet 包中包含接口的类库 项目 C 是 NuGet 包中实现接口的类库

我设法构建了包含 pbd 符号和源代码的 NuGet 包。 NuGet 包是在发布模式下构建的(这可能是问题吗?)

我的调试设置如下

Just My Code 未勾选 我正在加载两个 NuGet 包的符号

我可以进入所有“常规”方法,例如包含的扩展方法。

但是当我到达接口时,我无法让它进入实现接口的类。但是我可以从这个 NuGet 包的常规方法中单步执行代码。

任何提示,如果这是不可能的,或者我错过了调试设置中的其他内容。

【问题讨论】:

这可能很棘手,如果最糟糕的情况变得更糟,只需手动引用它们,当你真正开始工作时,你可能已经解决了 20 次错误。总之祝你好运 是的,这 20 次是正确的(现在尝试了几天)。但是,如果我引用它们,我的 .csproj 文件会被修改,而构建系统不喜欢这些文件。有没有办法让 2 个 .csproj 文件并排并相互同步(一个用于构建服务器,一个用于开发)? 您特别提到您在发布模式下构建 NuGet 包,但您是否尝试在开发模式下构建它们?我至少会对其进行测试,看看它是否有任何不同。 【参考方案1】:

您可能有几个选择:

尝试构建 NuGet 包的调试版本,看看是否有帮助 或者,删除对 NuGet 包的引用,并直接包含和引用它们的项目,至少是暂时的;这应该可以让您直接调试它们。

如果没有其他办法,还有第三种选择:记录。

这可能不是您想听到的确切答案,但根据我的经验,解决此类问题的最佳方法可能是添加一些可根据需要配置为启用或禁用的日志记录。

很多错误往往是由缺失值、缺失引用或其他一些错误配置引起的。找到它们后,修复它们可能很简单,但由于实现“隐藏”在这样的接口后面,因此很难找到它们。

找到某种方法将输入值公开给您的逻辑,无论是通过登录到数据库还是仅将纯文本日志写入文件,我敢打赌您会节省一些时间下一个错误会出现,如果不是之前的话。

...请记住在进入生产模式时禁用日志记录,尤其是在记录的数据可能包含任何敏感信息的情况下。

【讨论】:

正如你所建议的,我尝试在调试模式下构建它们以进行测试(仍然包括源代码和所有内容,只是将配置从发布更改为调试。哦,嘿,我可以进入执行界面。 天哪,.NET Core 的那一部分和 nugets s__k 为 h__l。具有讽刺意味的是,ASP.NET Core 的建议是将所有内容都放在接口后面(用于单元测试)。然后“引入一个像 nugets 这样的系统”,你不能调试它,因为你不能进入接口实现。似乎您不能使用 nuget 服务器来并排部署 Release & Debug,因为协议不包含配置模式 & VS2017 不允许您定义从服务器 X 加载 Release 和从服务器 Y 调试。使用他们说的 nugets .这是他们所说的 .NET Core 方式。他们说让我们玩得开心。 在将 SharedProjects 迁移到 nugets 后,我花了一个多星期的时间来弄清楚如何再次开发,我想我可以写一本书,或者至少写一篇关于“如何设置 .NET Core”的很长的博客文章使用 nugets 时的开发环境”。结果它似乎没有像应有的那样顺利。 @monty 很遗憾您在使用 .NET Core 时遇到了问题。很高兴听到您的直接问题得到了解决。如果您确实写了一篇博客文章或任何关于此体验的其他内容,您可以考虑在您的 OP 中链接到它,或者在它下面的评论中链接到它。以后可能会对其他人有所帮助。 Ps:如果这解决了您的问题,请考虑将检查作为您问题的“已接受答案”。 ;) 与 nugets 相关的编码环境结构比一般的 .NET Core 更麻烦。 :-) 好吧,我从 6 个有机增长的共享项目开始相互引用,今天结束了 25 个以上的 nuget 包项目,每个项目都有 2 个 .csproj 文件(一个用于构建服务器引用 nugets,一个用于开发直接引用项目)。让我们看看它是如何工作的 :-) 至少编码和调试似乎再次感觉很棒。我当然会接受你的回答并感谢你的帮助。

以上是关于Unity3d C# 实现AA包(Addressables)资源热更新的多个包异步加载并显示加载实时进度功能(含源码)的主要内容,如果未能解决你的问题,请参考以下文章

Unity3D 调用相机

unity3d实现ios界面ui滑动效果, C#脚本

Unity3D 接口使用

unity3D用C#脚本如何实现给物体添加力,望详细

Unity3D,导入包的代码未显示在 Visual Studio 中

Unity3D读取之——读取Excel文件内容