Unity的Resources类:从基础到高级的全面指南

这篇具有很好参考价值的文章主要介绍了Unity的Resources类:从基础到高级的全面指南。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

Unity中的Resources类为开发者提供了一个方便的方式来加载和管理运行时资源。尽管它的使用简单直观,但为了充分发挥其潜力和避免常见的陷阱,还是需要对其有一些深入了解。

Resources类简介

Resources类是Unity中的一个静态类,它提供了方法来加载存储在特定“Resources”文件夹内的资源。这些资源可以在编译时不与特定的场景或对象关联,但可以在运行时动态加载。

主要的形式写法
下面用Resources.Load来举例:

1.返回一个 UnityEngine.Object 类型的对象。根据需要,你可能会将其转换为更具体的类型。

TextAsset myText = Resources.Load("Texts/MyTextFile") as TextAsset;

2.返回一个指定类型的对象,不需要再进行转换。使用泛型方法加载资源的好处是,你不需要使用类型转换 (‘as’关键字),因为返回值已经是期望的类型。

TextAsset myText = Resources.Load<TextAsset>("Texts/MyTextFile");

 
如何使用
资源的放置:为了通过Resources类加载,必须将资源放在名为"Resources"的文件夹内。你可以在项目中有多个此类文件夹,并且它们可以在其他文件夹内。

加载资源:

Sprite mySprite = Resources.Load<Sprite>("Sprites/MySprite");

上述代码将会加载位于"Resources/Sprites/"目录下的名为"MySprite"的精灵。

卸载资源:

Resources.UnloadAsset(mySprite);

 
注意事项和最佳实践

  • 性能问题:频繁地使用Resources.Load和Resources.UnloadAsset可能会导致性能下降。应该考虑预加载重要资源或使用其他加载策略。
  • 资源组织:为了更有效地管理资源,推荐使用明确的文件夹结构,并且为资源命名时使用清晰的命名约定。
  • 资源卸载:记得卸载不再需要的资源,以避免不必要的内存使用。但是,过于频繁的卸载和加载也会影响性能。
  • 替代方案:虽然Resources类很有用,但在某些情况下,使用AssetBundles可能更合适,尤其是对于大型项目或需要更复杂的资源管理策略的项目。

接下来就是Resources类所有方法的详细用法与解释

Resources.Load: 从 “Resources” 文件夹中加载指定路径的资源
Resources.LoadAll: 从 “Resources” 文件夹中加载指定路径下的所有资源
Resources.LoadAsync: 从 “Resources” 文件夹中异步地加载资源
Resources.UnloadAsset: 卸载从 Resources 文件夹加载的单个资源
Resources.UnloadUnusedAssets: 卸载所有不再被引用的资源和对象
Resources.FindObjectsOfTypeAll: 用于查询获取所有已加载的对象(包括非激活的)的方法
Resources.GetBuiltinResource: 用于访问 Unity 内置的资源
Resources.InstanceIDToObject: 允许将给定的实例ID转换为一个对象
Resources.InstanceIDToObjectList: 用于将一组实例ID转换为Object列表

Resources.Load()

该方法从 "Resources" 文件夹中加载指定路径的资源。

定义:

public static Object Load(string path);
public static Object Load(string path, Type systemTypeInstance);

参数:
path: 资源的相对路径,不需要包含文件扩展名。
systemTypeInstance: 指定要加载资源的类型,例如 typeof(GameObject)。这是可选参数。

返回:
返回加载的资源对象,需要根据实际情况转型为适当的类型。

使用注意:

  • 要使用 Resources.Load, 需要确保资源已经被放置在名为 "Resources"的特殊文件夹内(可以有多个,可以是子文件夹)。
  • 加载的资源必须没有文件扩展名。例如,加载一个名为 “myTexture.png” 的贴图,只需要使用 “myTexture”。

示例:
假设有一个文件夹结构如下:

Assets/
│
└───Resources/
    │
    └───Sprites/
    │   │
    │   └───mySprite.png
    │
    └───Prefabs/
        │
        └───myPrefab.prefab

加载一个Sprite:

Sprite mySprite = Resources.Load<Sprite>("Sprites/mySprite");

加载一个预制体Prefab:

GameObject myPrefab = Resources.Load<GameObject>("Prefabs/myPrefab");

Resources.LoadAll

该方法从 "Resources" 文件夹中加载指定路径下的所有资源。

定义:

public static Object[] LoadAll(string path);
public static Object[] LoadAll(string path, Type systemTypeInstance);

参数:
path: 资源的相对路径。
systemTypeInstance: 指定要加载资源的类型,例如 typeof(GameObject)。这是可选参数。如果指定了这个参数,那么只会加载与此类型匹配的资源。

返回:
返回一个对象数组,包含加载的所有资源。需要根据实际情况转型为适当的类型。

示例:
假设有一个文件夹结构如下:

Assets/
│
└───Resources/
    │
    └───Sprites/
        │
        ├───sprite1.png
        ├───sprite2.png
        └───sprite3.png

加载一个文件夹中的所有 Sprite:

Sprite[] allSprites = Resources.LoadAll<Sprite>("Sprites");

Resources.LoadAsync

允许你异步地加载资源,这意味着加载过程不会阻塞主线程,从而可能避免由于加载大型资源导致的游戏卡顿。

定义

public static ResourceRequest LoadAsync(string path);
public static ResourceRequest LoadAsync(string path, Type type);

参数:
path: 资源的相对路径,相对于 “Resources” 文件夹,并且不应包含文件扩展名。
type: 指定要加载资源的类型

返回值:
返回一个 ResourceRequest 对象,它是 AsyncOperation 的子类,可以用来监控加载过程的进度、检查是否完成以及获取加载的资源。

示例:
想要异步加载一个名为 “MyTexture” 的纹理,其位于 “Resources/Textures” 目录下:

IEnumerator LoadTextureAsync()
{
    ResourceRequest request = Resources.LoadAsync<Texture2D>("Textures/MyTexture");
    yield return request;
    
    if (request.isDone)
    {
        Texture2D loadedTexture = request.asset as Texture2D;
        if (loadedTexture != null)
        {
            // 使用 loadedTexture 进行你的操作
        }
    }
}

在 MonoBehaviour 脚本的某个方法中通过 StartCoroutine(LoadTextureAsync()) 调用上述协程。

要注意的点:

  • 异步性: 由于加载是异步的,这意味着 LoadAsync方法会立即返回,而不等待资源完全加载。要监控加载状态和获取加载的资源,你需要使用返回的 ResourceRequest 对象。
  • 使用 Resources.LoadAsync的主要好处是提高了游戏性能,尤其是在需要加载大型资源时,如场景、模型或纹理,这有助于提供更流畅的用户体验。

Resources.UnloadAsset

用于在运行时手动释放从 Resources 文件夹加载的单个资源。这是一个有用的工具,尤其当你知道某个资源不再需要时,希望显式释放它以节省内存。

定义

public static void UnloadAsset(Object assetToUnload);

参数:
assetToUnload: 需要释放的已加载的资源。这通常是一个通过 Resources.Load 或其他加载方法加载到内存中的资源。

示例:
假设你有一个在游戏中加载了很多大型纹理的场景。在玩家离开这个场景后,希望释放一些纹理以节省内存。你可以这样做:

Texture2D texture = Resources.Load<Texture2D>("Textures/BigTexture");
// 使用该纹理...

// 当不再需要纹理时
Resources.UnloadAsset(texture);

注意的事项:

  • 仅针对单一资源: 这个方法仅释放单一资源,而不是整个资源包或与资源关联的所有对象。
  • 资源类型: 你只能使用 UnloadAsset 来卸载实体资源,如纹理、网格或音频剪辑。你不能用它来卸载GameObject、Component 或 ScriptableObject 实例。
  • 智能释放: 如果某个资源仍然有其他地方在引用,Resources.UnloadAsset不会真正释放资源。资源只有在不再被任何对象引用时才会被垃圾收集器释放。
  • 不是必需的: 在大多数情况下,你并不需要手动管理资源的释放。Unity的垃圾收集器和资源管理系统通常会处理大部分工作。但在某些特定的、资源密集型的情境下,显式地释放资源可能是个好主意。

Resources.UnloadUnusedAssets()

这个方法将卸载所有不再被引用的资源和对象,这包括从 Resources 文件夹加载的资源、AssetBundles、创建的实例化对象等。它返回一个 AsyncOperation,你可以使用这个对象来查询操作的完成情况或设置一个回调。它对于优化内存使用尤为重要,尤其是在移动设备上。

定义

public static extern AsyncOperation UnloadUnusedAssets();

示例:
考虑这样一个场景:你有一个大型游戏关卡,其中加载了大量的纹理、3D模型、音频等资源。当玩家完成该关卡并进入下一个关卡时,许多先前的资源可能不再需要。此时,调用 Resources.UnloadUnusedAssets() 是个不错的选择。

public IEnumerator LoadNextLevel()
{
    // 加载下一个关卡
    SceneManager.LoadScene("NextLevel", LoadSceneMode.Single);

    // 卸载不再使用的资源
    yield return Resources.UnloadUnusedAssets();
}

注意的事项:

  • 异步操作: 由于这是一个可能需要较长时间的操作(尤其是当存在许多资源需要检查时),因此它是异步的。你应该使用返回的
    AsyncOperation 对象来跟踪它的完成状态。
  • 引用计数: Unity 使用引用计数来确定哪些资源是“未使用”的。只有当没有任何对象引用特定资源时,该资源才会被视为未使用并被卸载。
  • 可能的延迟: 由于资源的释放依赖于垃圾收集,即使你调用了Resources.UnloadUnusedAssets(),实际的内存释放也可能会有所延迟。
  • 避免频繁调用: 不建议你经常或在不必要的时候调用这个方法,因为它可能会产生性能开销。

Resources.FindObjectsOfTypeAll

一个用于查询所有已加载的对象(包括非激活的)的方法,这些对象是特定类型或派生自特定类型的。这与 GameObject.FindObjectOfType 和 GameObject.FindObjectsOfType 不同,后者仅查询当前场景中的活动对象。

定义

public static Object[] FindObjectsOfTypeAll(Type type);

参数:
type: 要查找的对象的类型。

返回值:
返回一个包含所有找到的对象的数组。

示例:
1.查询所有摄像机:

Camera[] allCameras = Resources.FindObjectsOfTypeAll(typeof(Camera)) as Camera[];

2.查询所有的 Material:

Material[] allMaterials = Resources.FindObjectsOfTypeAll(typeof(Material)) as Material[];

注意的事项:
1.编辑器运行和打包后运行时差异:

  • 在编辑器运行时,Resources.FindObjectsOfTypeAll会返回包括项目资产和层次结构中的对象在内的所有对象,即使这些对象没有被加载到当前场景中。
  • 在打包后运行时,这个方法只返回当前加载的对象。它不会返回项目资源或其他没有加载的对象。

2.性能开销: 这个方法可能会有一些性能开销,尤其是当有大量的对象需要查询时。建议不要在经常调用的代码(如 Update 方法)中使用它。
3.返回非激活的对象:与 GameObject.FindObjectOfType 和 GameObject.FindObjectsOfType 不同,这个方法会返回所有对象,包括那些在层次结构中被禁用的对象。
4.返回的对象范围:在编辑器中,这个方法还会返回像 Inspector 面板中的隐藏对象等其他不常见的对象。因此,需要谨慎处理返回的对象。


Resources.GetBuiltinResource (比较难理解用处的方法)

用于访问 Unity 内置的资源。这些资源不包括在您的项目中,但它们是 Unity 引擎的一部分,因此您可以随时访问它们,无需导入或包含在项目资产中。

定义

public static T GetBuiltinResource<T>(string path) where T : Object;

其中,T 是您要加载资源的类型,path 是该资源的路径。
使用这个方法,您可以访问例如内置的材质、shader等资源。

示例:
假设你想加载 Unity 内置的“Standard” shader。你可以这样做:

Shader standardShader = Resources.GetBuiltinResource<Shader>("Standard.shader");

这将会返回一个指向内置“Standard” shader 的引用。

注意事项:

  • 当使用这个方法时,确保你知道资源的确切路径和名称,因为如果资源不存在或路径错误,该方法会返回 null。
  • 尽管此方法提供了访问内置资源的能力,但在大多数情况下,你仍然希望在项目中使用自定义资源,以便完全控制和自定义游戏的外观和行为。
  • 仅当你确定所需资源是 Unity 内置的,并且不希望将其作为项目资产导入时,才使用此方法。

看到这里,你可能会有疑问
如果我的材质球使用unity自带的shader,导入时unity会自动识别到并且为我的材质球赋值相应的shader啊,还要去用Resources.GetBuiltinResource的必要吗?

没错!当你在Unity中创建一个材质球并为其分配一个内置的shader,然后在另一个Unity项目中导入该材质球,Unity会尝试为这个材质球分配同样的shader(只要这个shader在导入的项目中是可用的)。
但Resources.GetBuiltinResource的主要目的不仅仅是处理材质球和shaders。它可以处理Unity的任何内置资源,例如纹理、meshes、预制体等。

考虑以下使用场景:

  1. 动态赋值:在某些情况下,你可能需要在运行时动态地为材质分配不同的shaders,例如根据特定的效果或性能需求。你可以预先为这些shaders创建一个数组或列表,并在需要时使用Resources.GetBuiltinResource动态加载和应用它们。
  2. 缺失资源的容错:假设你有一个工具或插件,并希望确保它在其他开发者的项目中也能正常工作,即使他们没有导入某些必要的资源。你可以使用Resources.GetBuiltinResource来加载一个默认的内置资源作为后备。
  3. 创建通用工具/插件:当你创建一个供其他开发者使用的通用工具或插件时,可能不希望这个工具/插件依赖于特定的资源。使用Resources.GetBuiltinResource,你可以确保工具/插件总是有一个默认资源可用,不论它被导入到哪个项目中。

总的来说,虽然在许多常规开发任务中你可能不需要手动使用Resources.GetBuiltinResource,但在某些特定情境和高级应用中,它可以非常有用。


Resources.InstanceIDToObject

允许你将给定的实例ID转换为一个对象。在Unity中,每个游戏对象、组件或资产在其生命周期中都有一个独特的实例ID。

定义:

public static extern Object InstanceIDToObject(int instanceID);

参数:
instanceID: 要转换的实例ID。

返回值:
返回与提供的实例ID关联的对象。如果没有找到对象,则返回 null。

何时使用:
该方法在某些情况下可能会有用,特别是当你知道一个对象的实例ID,但不知道它具体是什么的时候。
但在大多数常规的开发情境中,你可能不会经常使用这个方法。它更常见于高级的工具开发或某些特定的编辑器脚本任务,其中你可能需要从其他数据源或工具中获得实例ID,然后需要获取到实例ID对应的实际对象。

注意:

  • 实例ID在对象的生命周期中是唯一的,但如果对象被销毁,它的实例ID可能会被回收并在未来分配给另一个对象。
  • 此方法不会返回尚未加载的资源,因为它不会触发资源的加载。

示例:
假设你有一个工具,它从外部源获取实例ID,并且你想找到与该ID关联的对象。

int myInstanceID = 123456; // 这只是一个示例值,实际上你会从某个地方获取它
UnityEngine.Object obj = Resources.InstanceIDToObject(myInstanceID);
if (obj != null)
{
    Debug.Log("找到具有实例ID的对象:" + obj.name);
}
else
{
    Debug.Log("没有找到该实例ID的对象。");
}

总的来说,除非你正在处理特定于实例ID的工作需求,否则你可能不会经常用到这个方法。但了解它的存在和用途仍然是有益的,特别是对于高级开发和工具创建。


Resources.InstanceIDToObjectList

用于将一组Instance ID转化为Object列表

定义

public unsafe static void InstanceIDToObjectList(NativeArray<int> instanceIDs, List<Object> objects);

使用NativeArray来传递Instance IDs,这是一个Unity的结构,用于在C#和原生代码之间传递数据而不产生垃圾。
这个方法有几个关键点:
1.安全检查: 在转换前,方法会检查NativeArray是否已经被初始化,并确保提供的objects列表不为null。
2.清除对象列表: 如果提供的instanceIDs为空,它将清空objects列表。
3.转换: 如果提供了Instance IDs,它会调用内部的extern方法来进行实际的转换。

示例:
假设我们有一个场景,其中包含多个对象,我们想通过它们的Instance ID获取这些对象的引用。

void Start()
{
    // 为简化起见,我们在这里使用了假的Instance IDs。
    // 在实际应用中,你会从某些来源获得这些IDs。
    NativeArray<int> sampleInstanceIDs = new NativeArray<int>(3, Allocator.Temp);
    sampleInstanceIDs[0] = 1;  // 假设的ID
    sampleInstanceIDs[1] = 2;  // 假设的ID
    sampleInstanceIDs[2] = 3;  // 假设的ID

    ConvertInstanceIDsToObjectList(sampleInstanceIDs);
    sampleInstanceIDs.Dispose();
}
public void ConvertInstanceIDsToObjectList(NativeArray<int> instanceIDs)
{
    List<UnityEngine.Object> objectList = new List<UnityEngine.Object>();
    Resources.InstanceIDToObjectList(instanceIDs, objectList);
    // 打印转换后的对象名称
    foreach (UnityEngine.Object obj in objectList)
    {
        Debug.Log(obj.name);
    }
}

在这个简化的例子中,我们会假设已经有了这些IDs,并且将它们存储在NativeArray中。
使用Resources.InstanceIDToObjectList方法将这些IDs转换为实际的对象。


Resources类为Unity开发者提供了一个强大而灵活的工具,但是要确保正确并且高效地使用它。当正确使用时,它可以成为你的工具箱中的重要工具,帮助你创建更加动态和响应迅速的应用和游戏。文章来源地址https://www.toymoban.com/news/detail-728458.html

到了这里,关于Unity的Resources类:从基础到高级的全面指南的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity 之 Addressable可寻址系统 -- 将Resources加载资源方式修改为Addressable加载 -- 实战(一)

    加载方式: Resources 使用同步加载方式;Resources 加载资源时,应用程序将会被阻塞,直到资源加载完成,这可能会导致应用程序出现卡顿或挂起的情况。 Addressables 使用异步加载方式。这意味着使用 Unity 而使用 Addressables 加载资源时,应用程序可以继续运行,而不会出现卡顿

    2024年02月05日
    浏览(44)
  • Rust 全面指南:从基础到高级,一网打尽 Rust 的编程知识

    因为在学习Rust过程中,因为代码量不是太多,所以有一些学完就忘了,特此记录一些Rust知识点 Rust是什么? Rust是一种现代的、强类型的、系统级编程语言。它被设计用于编写高性能、并发、安全的系统,并且可以避免常见的内存安全问题,如空指针和数据竞争。Rust的特点包

    2024年02月08日
    浏览(50)
  • 后门攻击 & 对抗攻击 resources

    后门攻击 知乎问答 公众号: 后门学习(Backdoor Learning)介绍及资源汇总 浅谈深度学习后门攻击 Backdoor Learning: A SurveyAI中的后门攻击及防御-实战篇 如何攻击深度学习系统——后门攻防 毒墨水:一种隐蔽且鲁棒的后门攻击 深度学习中的后门攻击综述【 信 息 安 全 学 报】 对深度

    2024年02月09日
    浏览(43)
  • cocosCreator 之 resources(一)

    版本: 3.4.0 语言: TypeScript 环境: Mac 在cocosCreator中,我们所有的资源都是放在 assets 目录下, 只有放在该目录下的资源,编译器才能使用。 该目录下的所有资源均继承于 Assets ,我们简单看下继承结构: 更多参考: cocosCreator 之 通过cc.d.ts了解Assets资源 在 assets 目录下的资

    2024年02月14日
    浏览(31)
  • Spring Resources资源操作

    Java的标准java.net.URL类和各种URL前缀的标准处理程序无法满足所有对low-level资源的访问,比如:没有标准化的 URL 实现可用于访问需要从类路径或相对于 ServletContext 获取的资源。并且缺少某些Spring所需要的功能,例如检测某资源是否存在等。 而Spring的Resource声明了访问low-leve

    2024年02月09日
    浏览(35)
  • Java获取resources下文件路径

    获取resources目录下某文件路径并返回 此处也能获取到文件路径 仅限本地 当jar包时 是无法获取到该文件具体的路径的 我的解决方案如下: 从流中获取

    2024年02月03日
    浏览(52)
  • spring6-资源操作:Resources

    1、Spring Resources概述 Java的标准java.net.URL类和各种URL前缀的标准处理程序无法满足所有对low-level资源的访问,比如:没有标准化的 URL 实现可用于访问需要从类路径或相对于 ServletContext 获取的资源。并且缺少某些Spring所需要的功能,例如检测某资源是否存在等。 而Spring的Reso

    2024年02月08日
    浏览(33)
  • java获取resources路径的方法

      我们在写程序的时候,有时候会发现代码不能正常运行,出现提示异常的问题,这就说明我们的代码没有执行完,也就是没有 resource,其实遇到这种情况,我们只需要把代码重新执行一遍即可。 在 java中是可以实现 resource的获取和使用的, java提供了两个方法: 第一个方法

    2024年02月06日
    浏览(38)
  • Awesome 3D Gaussian Splatting Resources

    GitHub - MrNeRF/awesome-3D-gaussian-splatting: Curated list of papers and resources focused on 3D Gaussian Splatting, intended to keep pace with the anticipated surge of research in the coming months. 3D Gaussian Splatting简明教程 - 知乎 

    2024年01月20日
    浏览(56)
  • 云原生周刊:DevOps-resources

    推荐一个 GitHub 仓库 “DevOps-resources”。这个 GitHub 仓库包含了学习和实践 DevOps 所需的资源列表。它包括涉及云计算、容器化、微服务、自动化和安全问题的文章、书籍、课程和工具。资源按最佳实践、代码基础设施和安全性等类别进行排序,使得用户可以更轻松地找到与他

    2024年02月09日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包