Unity Resources.load() 不适用于外部 dll

Posted

技术标签:

【中文标题】Unity Resources.load() 不适用于外部 dll【英文标题】:Unity Resources.load() won't work with external dll 【发布时间】:2018-12-29 21:37:20 【问题描述】:

我正在尝试使用 Resources.load() 加载资产,但它总是返回 null。

这是我的文件夹结构:https://imgur.com/a/z8KObW1

当我在我的统一项目中使用 Resources.load() 时,它可以正常工作。 但是,当我在 Visual Studio 中使用 unityengine dll 创建一个单独的项目,并在 Source 文件夹下的一个 .cs 文件中使用 Resources.load() 时,无论我尝试什么,它似乎总是返回 null。

当我将 Assets 文件夹放在 Source 文件夹中时,它返回 null,当我将 .cs 文件放在 Asset 文件夹中时,它也返回 null。我似乎无法弄清楚为什么。我还尝试获取 Resources.load() 开始的路径,但我似乎无法弄清楚。是从.dll开始还是从Source下的.cs文件开始?

public static void Create_Manager() 
    GameObject networkManagerObj = new GameObject();
    networkManagerObj.name = "_NetworkManager";
    networkManager = networkManagerObj.AddComponent<NetworkManager>();

    networkManager.playerPrefab = Resources.Load("Player") as GameObject;

    networkManager.dontDestroyOnLoad = true;
    networkManager.runInBackground = true;
    networkManager.autoCreatePlayer = true;
  

我只需要让 Resources.load() 与我的单独项目/dll 一起工作。有谁知道怎么做?

【问题讨论】:

你不能像这样从 dll 中加载资源。 Unity 中的资源文件夹具有与之相关的特殊 Unity 魔法。要从 DLL 中获取资源(甚至从 DLL 中),您必须使用 Streams。我无法访问我的同事编写的某些代码,我会在星期一的某个时间回复您。 @Draco18s 感谢您的回复!很高兴听到你能在星期一帮助我。与此同时,我将自己看看流。 嘿@Draco18s 我给你写信是为了告诉你我一直在研究流但没有走得很远。我尝试在统一中编写自己的资产处理程序,这很有效,但是这种方法在统一之外也不起作用。我希望你能用代码回复我。提前致谢! 路径从Assets 开始,因此您不能使用外部文件。但也许您可以使用Application.persistensDataPath + fileName 并将文件移动到目标设备上的according path 【参考方案1】:

这是我的一位同事编写并主要向我解释的代码。我省略了很多处理这个类的用途的代码(处理触摸输入),只留下与加载图像相关的部分(用于在屏幕上显示触摸点)。

using System;
using System.IO;
using System.Linq;
using System.Reflection;

using UnityEngine;

using HedgehogTeam.EasyTouch;

namespace TouchControls

    /// <summary>Helper to control touch-based input.</summary>
    public static class Utility
    
        const string imageNamespace = "TouchControls.";
        const string imageResourceFolder = "TouchControls/Images/";

        /// <summary>Static helper to contain texture resources.</summary>
        public static class Texture
        
            /// <summary>The texture used to represent a second finger when simulating touches.</summary>
            public static Texture2D SecondFinger
            
                get
                
                    if (null == secondFinger)
                        secondFinger = LoadImage(secondFingerFilename);

                    return secondFinger;
                
            
            static Texture2D secondFinger = null;
            const string secondFingerFilename = "secondFinger.png";
        

        static Assembly ExecutingAssembly
        
            get
            
                if (null == executingAssembly)
                
                    executingAssembly = Assembly.GetExecutingAssembly();
                
                return executingAssembly;
            
        
        static Assembly executingAssembly = null;
        static Stream GetImageStream(string imageName)  return ExecutingAssembly.GetManifestResourceStream(imageName); 

        static Texture2D LoadImage(string filename, TextureWrapMode wrapMode = TextureWrapMode.Clamp, FilterMode filterMode = FilterMode.Bilinear, bool useMipMaps = true, TextureFormat format = TextureFormat.ARGB32)
        
            Texture2D texture = Resources.Load<Texture2D>(imageResourceFolder + Path.GetFileNameWithoutExtension(!string.IsNullOrEmpty(filename) ? filename : string.Empty));
            try
            
                // Didn't find it in resources in the project so try to find it in the library manifest....
                if (null == texture)
                
                    using (Stream stream = GetImageStream(imageNamespace + filename))
                    
                        texture = new Texture2D(0, 0, format, useMipMaps);
                        if (!texture.LoadImage(GetImageBuffer(stream)))
                            throw new NotSupportedException(filename);

                        texture.wrapMode = wrapMode;
                        texture.filterMode = filterMode;
                    
                
                else // ensure it is read/write enabled...
                
                    Texture2D invertedTexture = new Texture2D(texture.width, texture.height, texture.format, 1 < texture.mipmapCount);
                    invertedTexture.SetPixels32(texture.GetPixels32());
                    invertedTexture.Apply(true);
                    texture = invertedTexture;
                
            
            catch
            
                // Something went wrong so make a magenta 4 pixel texture.
                texture = new Texture2D(2, 2, TextureFormat.ARGB32, false);
                texture.SetPixels(0, 0, 2, 2, Enumerable.Repeat(Color.magenta, 4).ToArray());
            
            texture.Apply(true);

            return texture;
        

        static byte[] GetImageBuffer(Stream stream)
        
            stream.Seek(0, SeekOrigin.Begin);
            byte[] buffer = new byte[stream.Length];
            stream.Read(buffer, 0, (int)stream.Length);

            return buffer;
        
    

它首先尝试在给定位置从 Resources 文件夹(如您所熟悉的那样)加载图像:如果需要,这允许本地项目覆盖该图像。如果找不到该图像,则它会从 DLL 中加载一个。我不确定这张图片的位置,但由于路径引用在代码中,我确信它的效果足够好(他告诉我的关键部分是如何确保文件被包含在 DLL 中,而不是 它所在的位置)。

从 DLL 中加载它的重要块是这部分:

static Stream GetImageStream(string imageName)  return ExecutingAssembly.GetManifestResourceStream(imageName); 
//...
using (Stream stream = GetImageStream(imageNamespace + filename))

    texture = new Texture2D(0, 0, format, useMipMaps);
    if (!texture.LoadImage(GetImageBuffer(stream)))
        throw new NotSupportedException(filename);

    texture.wrapMode = wrapMode;
    texture.filterMode = filterMode;

//...
texture.Apply(true);

return texture;

【讨论】:

哇,非常感谢!明天或后天我会看看它,让你知道它是否有效。 我一直在努力让这段代码工作大约一天,我已经走了很远但遇到了一个问题。此代码使用字节数组加载图像。我无法使用字节数组加载对象,所以我又被卡住了。我已经尝试更改代码 a 但仍然无法正常工作。我确实看到我可以使用字节加载 AssetBundle,但我仍然无法让它工作。感谢您的帮助。 唉,抱歉对你没用。我猜纹理是唯一会以这种方式加载的东西。

以上是关于Unity Resources.load() 不适用于外部 dll的主要内容,如果未能解决你的问题,请参考以下文章

Unity 读取调用资源 Resources.Load(详细+示例)

Unity中 动态加载 Resources.Load()和Asset Bundle 的区别

unity中gc.collect和resources.unloadunusedassets功能有啥异同

Unity——资源文件夹介绍

Unity3D 4.x C#脚本如何读取Resources目录下所有文件的文件名

全面理解Unity加载和内存管理