如何在统一中获得对预制资产的引用

How to get a reference to a prefab asset in unity

我有以下class

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class PixelSystem
    {
        public GameObject pixelPrefab;
        public Texture2D[] style;
        public List<Chunk> chunks;
        public GameObject mGameObject;
        public PixelSystem(GameObject _mGameObject)
        {
            mGameObject = _mGameObject;
            chunks = new List<Chunk>();
        }
    }

ChunkPixel 是结构,但我认为它们不相关。

我希望将 pixelPrefabstyle 序列化,但似乎无法实现。此脚本未附加到游戏对象。

我研究过使用 ResourcesAddressables 在运行时获取资产,但我希望能够从编辑器中设置这些字段。

我尝试让 class 继承自 MonoBehaviour 并具有 [SerializeField] public GameObject pixelPrefab;[SerializeField] public Texture2D[] style;,但结果是 pixelPrefab 是可设置的来自编辑器但不是显示 style 它显示 mGameObject,出于某种原因...¯\_(ツ)_/¯ 编辑: 结果是 [SerializeFields] 在这里什么都不做,没有它们结果是一样的。

我也试过将 [System.Serializable] 放在 class 之前,但据我所知这根本没有任何作用。

有人请帮助。

编辑:

由于一些误解,我想澄清一些事情:

  1. 我已经有了预制资产,它在我的资产文件夹中而不是在我的场景中,创建资产不是问题。
  2. pixelPrefab 可以像 static 属性 一样正常工作,但是,style 不会。
  3. 样式只需要为默认值序列化,因此不是优先级。
  4. 此代码非常不完整,构造函数不完整,在我花时间编写可能无法使用的代码之前,我想得到这个问题的答案。
  5. 我要select编辑器中的资产
  6. 我不想有一个必须在使用 classes 之前调用的函数,以便加载资产
  7. 我不想每次引用资源的时候都加载,所以没有get {load();}

这是我在 select 我的脚本时希望在编辑器中看到的内容:

这是目前最接近我想要的东西:

我通过将 class 设置为从 MonoBehaviour 继承得到的,我宁愿不从任何东西继承,如果你打算拥有 MonoBehaviour classes 没有附加到游戏对象,但如果这是必要的,那就这样吧。

complete .cs file here

这里有几件事。我假设这一点是最重要的:

  1. I want to select the assets in the editior

因此,为了能够做到这一点,您想要看到的每个字段都必须能够被 Unity 序列化,并且 Unity 还需要能够为那个东西绘制 GUI。你说,

I would like pixelPrefab and style to be serialized but cannot seem to be able to make that work.

在这里,我再次使用“序列化”来表示您只希望在编辑器中公开这些字段,以便您可以将内容粘贴到其中。因此,当您给我以下代码片段时,我会立即看到几个问题:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PixelSystem
{
    public GameObject pixelPrefab;
    public Texture2D[] style;
    public List<Chunk> chunks;
    public GameObject mGameObject;
    public PixelSystem(GameObject _mGameObject)
    {
        mGameObject = _mGameObject;
        chunks = new List<Chunk>();
    }
}

首先是 PixelSystem 本身没有序列化。您要么需要使用 [System.Serializable] 标记 class 以使用 Unity 的序列化程序,要么您需要继承 Unity 已经知道应该序列化的内容,例如 ComponentMonoBehaviour (MonoBehaviour 继承 Component)。 Component 和 subclasses 的问题是它们需要存在于 GameObject 上,所以你不能 new 一个 Component,你必须 .AddComponent<YourComponent>().

现在正如您所发现的,当您让脚本继承 MonoBehaviour 时,您会看到

that pixelPrefab is settable from the editor but instead of showing style it shows mGameObject, for some reason... ¯\_(ツ)_/¯

它显示 mGameObject 的原因可以在你的 class' 成员变量中看到:

public GameObject pixelPrefab;
public Texture2D[] style;
public List<Chunk> chunks;
public GameObject mGameObject;

你可以看到 pixelPrefab 是一个 public GameObject。伟大的! (1) 你的 class 继承了 MonoBehaviour,所以 Unity 知道要序列化它,(2) pixelPrefabpublic,所以编辑器知道要显示它,并且 GameObject 本身是 Unity 知道如何绘制的可序列化对象,因此最终结果是 Unity 将 pixelPrefab 添加到您的 class.

的编辑器 GUI 中

然后您到达 style,即 public,因此编辑器知道它应该显示它,但它是一个 数组 而 Unity 不会不知道如何为数组绘制编辑器 GUI。它是一个 Texture2D 的数组,它 确实 知道如何绘制,但它不知道如何处理数组方面,所以它没有添加 style 到您的 GUI。

然后您到达 chunks,即 public,因此编辑器知道它应该显示它,它是 List,Unity 知道如何处理,但它是 Chunk 的列表,我打赌它不会继承 MonoBehaviour 并且也没有用 [System.Serializable] 标记,所以 Unity 不会知道它应该是序列化 Chunk。这意味着它确实知道它应该绘制一个列表,但它认为它不应该为列表绘制任何内容,所以它完全跳过列表。

最后你到达了 public GameObject mGameObject,它被绘制的原因与 pixelPrefab 被绘制的原因相同,最后你得到了你在最后一个屏幕截图中在编辑器中看到的内容:只有 pixelPrefabmGameObject 在你的 class GUI 中绘制:

那么,如果您想在编辑器窗格中查看 class 并且还想查看 pixelPrefabstyle 怎么办?

  1. 有一些可以序列化的东西,比如 MonoBehavior,持有对 PixelSystem 的引用,或者让 PixelSystem 继承 MonoBehavior.
  2. 如果 PixelSystem 不是 MonoBehavior 那么它需要在 public class PixelSystem.
  3. 上面的行上有 [System.Serializable]
  4. 做你已经做过的事情并获得 public GameObject pixelPrefab.
  5. style 从数组转换为列表,以便 Unity 知道如何绘制它。

您应该得到以下结果:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]    
public class PixelSystem
{
    public GameObject pixelPrefab;
    public List<Texture2D> style = new List<Texture2D>();
    public List<Chunk> chunks;
    public GameObject mGameObject;
    public PixelSystem(GameObject _mGameObject)
    {
        mGameObject = _mGameObject;
        chunks = new List<Chunk>();
    }
}

如果您使用 [System.Serializable] 标记 class,您还可以将 Chunk 序列化并显示在您的编辑器窗格中,并且您只需要 [SerializeField] 标记尚未 public 的字段。您仍然可以将该标签添加到 public 字段,就像您可以将 [System.Serializable] 添加到 MonoBehaviour 一样,但这是多余的。不需要。