0

我正在尝试为 Unity 创建一个组件GameObject,我们称之为它MediaController。我希望它能够管理不同媒体(音频/视频)的时间(播放/暂停/等)。我创建了一个PlayableMedia具有基本属性/字段/方法的抽象类,并创建了 2 个类,PlayableVideo并且PlayableAudio,它们根据我们的需要继承和实现。

目的是有一个PlayableMedia可能与音频/视频无关的单一列表,允许media.Play()在特定应用程序时间进行简单(即)调用,而不管类型如何......但我的字段public List<PlayableMedia> MediaList;没有出现在编辑器中并且没有错误。

所以最终我的问题是标题所述:是否可以将PlayableMedia类用作字段的类型?

根据我的经验,我怀疑“不”,但我发现链接说“是”或“是的,有点”似乎指向自定义编辑器/检查员/抽屉,但我有 0 经验那些并且无法实现它(见下文)。

[System.Serializable]
public class RegisteredMedia
{
    public float StartTime;
    public PlayableMedia Media;
}

[CustomPropertyDrawer(typeof(RegisteredMedia))]
class RegisteredMediaDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginProperty(position, label, property);

        position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), new GUIContent("Playable Media"));

        var indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        Rect rectStartTime = new Rect(position.x, position.y, 30, position.height);
        Rect rectMedia = new Rect(position.x + 35, position.y, 50, position.height);

        EditorGUI.PropertyField(rectStartTime, property.FindPropertyRelative("StartTime"), GUIContent.none);
        EditorGUI.PropertyField(rectMedia, property.FindPropertyRelative("Media"), GUIContent.none);

        EditorGUI.indentLevel = indent;

        EditorGUI.EndProperty();
    }
}

public class MediaController : MonoBehaviour
{
    public List<RegisteredMedia> MediaList = new List<RegisteredMedia>();

    \\[...] rest of implementation
}

谁能帮我吗?要么确认这是不可能的,或者如果是的话,请帮助我实施?

另外,如果可以使用自定义编辑器/检查器/抽屉来完成,有人可以帮我在 中获取单个项目List<RegisteredMedia>以显示为Start Time ____ Playable Media [=====](附有适当组件PlayableMedia的 a 将在哪里)?GameObject

4

2 回答 2

3

小心使用“财产”一词。在 C# 中,它意味着非常具体的东西

是否可以使用 PlayableMedia 类作为属性的类型?

我想你在这里问错了问题。与其提出新的实现,不如考虑一下为什么您当前的实现可能不起作用?

首先,我会给你下面的例子:

public abstract class Car : MonoBehaviour { }

public class Jeep : Car { }

public class Ferrari : Car { }

public class CarHolder : MonoBehaviour
{
    public List<Car> Cars;
}

在此示例中,我可以使用 CarHolder 组件创建一个 GameObject,并且能够附加 Jeep 和 Ferrari 对象。需要注意的是,我定义的每个 monoBehavior 类都位于其自己的文件中,并且文件名与类名匹配。这就是 Unity 的工作原理。

因此,要回答我认为您要问的问题(假设我们将“属性”替换为“字段”),确实可以使用抽象类类型并将它们显示在检查器中。我怀疑您需要将您的类分成单独的文件。

于 2018-06-28T02:34:30.650 回答
1

自 2019.3 发布以来,它可以通过[SerializeReference]属性https://docs.unity3d.com/ScriptReference/SerializeReference.html本地实现

例如

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

[Serializable]
public abstract class AbstractExample {
    public int foo;
}

// [Serializable] not needed here
public class ConcreteExample : AbstractExample {
}

public class Consumer : MonoBehaviour {
    [SerializeReference]
    public List<AbstractExample> examples = new() { new ConcreteExample() };

    // both the list and the concrete instance visible in the editor
    // and editable without any additional editor extensions

    // note that you can't effectively add new items to the list via editor
    // since that way you create a faulty abstract-ish instances instead
    // (no actual way for the editor to know what subtype do you want)

    // if you're OK with having the base class being not explicitly abstract
    // and can provide a sensible constructor for it, just drop the abstract
    // you'll still have full polymorphism support etc. with SerializeReference
}
于 2022-01-03T19:34:25.123 回答