有没有办法让脚本将对象作为字段引用?

问题描述

我在四处寻找时遇到了麻烦,并且可能严重误解了 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,我可以将脚本放在那里,但这似乎是我不想要的。

解决方法

我猜想,除了在编辑器中,您不希望这些脚本公开,因此您可以使用名为 SerializeField 的属性。它将向编辑器公开该字段,以便您可以拖入引用,但其他脚本将无法访问您放入的字段。

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

[SerializeField] private YourScriptName scriptReference = null;

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

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

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

public YourScriptName GetYourScript(){ return scriptReference;}

Unity 不能序列化的字段很少,所以一般来说,如果你想拖入对组件、脚本、对象等的引用,你需要做的就是让它成为 SerializeField 或public 后跟要拖入的任何类型。

来自文档,序列化系统

不能序列化静态字段。

不能序列化属性。

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

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

它可以序列化的字段如下

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

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

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

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

Unity: Now You're Thinking With Components