Unity Resources.load()无法与外部dll一起使用 [英] Unity Resources.load() won't work with external dll

查看:145
本文介绍了Unity Resources.load()无法与外部dll一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用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一起工作.有人知道怎么做吗?

解决方案

以下是我的一位同事编写并向我解释的代码.我已经省略了很多处理此类的目的的代码(处理触摸输入),只剩下与加载图像有关的部分(用于在屏幕上显示触摸点).

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;
        }
    }
}

它首先尝试在给定位置从资源"文件夹中加载图像(如您所熟悉的那样):这允许图像被本地项目覆盖(如果需要).如果找不到该映像,则它将从DLL中加载一个.我不确定该图片的位置,但是由于路径引用位于代码中,因此我确信它的作用足够合理(他告诉我的关键部分是 how ,以确保文件包含在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;

I'm trying to load an asset using Resources.load() but it always returns null.

Here is my folder structure: https://imgur.com/a/z8KObW1

When I use Resources.load() in my unity project, it works without any problem. But when I create a seperate project in visual studio with the unityengine dll's, and use Resources.load() in one of the .cs files under the Source folder it always seems to return null, no matter what I try.

When I placed the Assets folder inside of the Source folder it returned null and when I placed the .cs files in the Asset folder it also returned null. I can't seem to figure out why. I also tried to fetch the path that the Resources.load() starts at, but I can't seem to figure it out. Does it start from the .dll or from the .cs file under the Source?

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;
}  

All I need is for the Resources.load() to work with my seperate project/dll. Does anyone know how to do so?

解决方案

Here's the code that a coworker of mine wrote and mostly explained to me. I've omitted a lot of the code that dealt with what this class was for (handling touch input), leaving only the sections related to loading an image (used to display a touch point on screen).

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;
        }
    }
}

It first attempts to load an image out of the Resources folder (as you're familiar with) at a given location: this allows the image to be overridden by the local project, if desired. If that image isn't found, then it loads one out of the DLL. I am not sure where this image is located, but as the path reference is in the code, I'm sure it works out sensibly enough (the key part he had informed me was how to insure that the file got included in the DLL, rather than where it was located).

The important chunk for loading it out of the DLL is this section:

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;

这篇关于Unity Resources.load()无法与外部dll一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆