【问题标题】:Is there a way to have a script reference an object as a field?有没有办法让脚本将对象作为字段引用?
【发布时间】:2021-05-26 19:03:43
【问题描述】:

我在四处搜索时遇到了麻烦,可能严重误解了 Unity 希望您如何构建项目,但这是我的情况:

我的游戏中有角色,想在编辑器中配置它们。我制作了代表不同行为类型和可以执行的动作的类。 我有没有办法在为这些类键入的脚本上创建一个字段,以便我可以使用检查器拖放来配置不同的预制件?

这里有一些代码演示了这种情况:

Unit.cs

// A unit on the board.
public class Unit : MonoBehaviour
{
    public UnitAction action;
}

UnitAction.cs

// A unit on the board.
public class UnitAction : MonoBehaviour
{
    // Does things
}

一旦将此脚本应用于预制件,这些字段就会显示在检查器中,但没有填充默认字段值的选项。如果我将字段类型设为UnityEngine.Object,我可以将脚本放在那里,但这似乎是我不想要的。

【问题讨论】:

  • 那么问题是什么?您需要为您的公共字段设置正确的类型,例如,如果您想添加一个 GameObject 预制件,请将其声明为 public GameObject go 或转换/脚本或您需要的任何内容。
  • 我遇到的问题是我在类中有这些字段并且它显示在检查器中,但我无法将任何 UnitBehavior 或 UnitAction 脚本应用于该字段。它不允许我将它们从资产中拖过来,当我单击浏览时,列表中没有任何内容。我可以将此脚本应用到与预制件上的单元脚本相同的级别,但不能作为单元脚本上的字段。我需要将这些脚本附加到某些东西上,然后才能将它们应用到该领域吗?在这种情况下,UnitBehavior 和 UnitAction 都继承自 MonoBehavior。
  • @TylerHackbarth 你想在编辑器中的脚本上有默认字段吗?要实际填充这些字段,它们必须位于场景中的对象上或作为预制件。
  • @TEEBQNE 是的,就是这样。我想使用编辑器来配置具有不同动作集或其他任何东西的不同单元。谢谢!是否存在与为此目的可能拥有许多游戏对象相关的开销?我的直觉是在 Unity 编辑器中进行配置,而不是代码,但我不知道执行此操作的“Unity 方式”。
  • 您将引用此类“脚本”的 instances .. 不是 脚本文件本身 ...

标签: unity3d unity3d-editor


【解决方案1】:

听起来您正在尝试序列化对脚本本身的引用,而不是那些脚本的实例。您可能希望通过以下几种方式执行此操作:

  1. 您可以将 UnitAction 脚本作为 GameObject 的组件附加到您的“Unit”对象可访问的上下文中(在同一场景中,“Unit”对象的子对象,或者 - 可能是最常见的情况 - “单位”对象本身)。然后,您将能够将这些实例化的组件序列化到 Unit 类中的字段中。这是最常见的用例。

  2. 您可以为每个 UnitAction 组件创建一个预制件,然后将这些预制件序列化到您的 Unit 类字段中。然后,您将在运行时实例化一个 UnitAction。根据您的描述,这似乎并不适合您的情况,因为 UnitAction 可能不是需要动态实例化的东西,但要注意这一点很重要。本文有一个使用这种方法为单位提供法术列表的示例(并且还提供了一些关于如何考虑使用可能对您有价值的统一组件的良好背景):

Unity: Now You're Thinking With Components

【讨论】:

    【解决方案2】:

    我猜你不想让这些脚本暴露在编辑器中,所以你可以使用一个名为SerializeField 的属性。它将向编辑器公开该字段,以便您可以拖动引用,但其他脚本将无法访问您放入的字段。

    如果您希望特定脚本出现在编辑器中,只需编写

    [SerializeField] private YourScriptName scriptReference = null;
    

    由于列表是通用结构,如果你愿意,你也可以用类似的方式制作一个脚本列表

    [SerializeField] private List<YourScriptName> scriptListReference = new List<YourScriptName>();
    

    由于我认为您不会再次分配这些引用,因此如果您想在任何时候获取引用,您可以创建一个 getter 方法。

    public YourScriptName GetYourScript(){ return scriptReference;}
    

    Unity 无法序列化的字段很少,所以一般来说,如果您想拖入对组件、脚本、对象等的引用,您只需将其设为SerializeField 或 public 跟随根据您要拖入的任何类型。

    来自文档,序列化系统

    不能序列化静态字段。

    不能序列化属性。

    可以序列化公共非静态字段(可序列化类型)

    可以对标有 SerializeField 属性的非公共非静态字段进行序列化。

    它可以序列化的字段如下

    • 从 UnityEngine.Object 继承的所有类,例如 游戏对象、组件、MonoBehaviour、Texture2D、AnimationClip。
    • 所有基本数据类型,例如 int、string、float、bool。
    • 一些内置类型,例如 Vector2、Vector3、Vector4、Quaternion、Matrix4x4、Color、Rect、LayerMask。
    • 可序列化类型的数组 可序列化类型
    • 枚举
    • 结构

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-15
      • 1970-01-01
      • 1970-01-01
      • 2011-04-07
      • 2020-01-09
      • 1970-01-01
      • 2023-03-17
      相关资源
      最近更新 更多