Unity Resources.load() won't work with externa

2019-06-08 08:31发布

问题:

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?

回答1:

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;