1. ホーム
  2. c#

[解決済み] コンストラクターによるスクリプト可能なオブジェクト・インスタンスの作成

2022-01-30 04:33:32

質問

キャラクターのスクリプト可能なオブジェクトがあり、その中にいくつかのメソッドを持っています。GetDateやGetAgeのようなものです(ここでは表示していません)。そこにコンストラクタを作成しましたが、コンストラクタを通じてそのScriptableObjectのインスタンスを作成する方法がわかりません。それは私がやりたいことです。

インスペクタに値だけを入力しようとしましたが、それではコンストラクタのメソッドが実行されません。

キャラクター.cs

[CreateAssetMenu]
[Serializable]
public class Character : Scriptable Object
{
    // Attributes
    public string firstName;
    public string middleName;
    public string lastName;
    public string fullName;
    public bool isMale;

    // Constructor
    public Character(string _firstName, string _middleName, string _lastName, bool _isMale)
    {

        firstName = _firstName;
        middleName = _middleName;
        lastName = _lastName;

        // All The Functions 
        fullName = string.Format("{0} {1} {2}", firstName, middleName, 
        lastName);

        isMale = _isMale;

        // and all the other functions like date calculator.
    }
}

このConstructionによって、このScriptable Objectのインスタンスを作りたいのです。以下のような感じ。

Character char("x", "y", "z", true);

とか、Unity Inspectorに必須項目を入力すると、そのフルネームのようなメソッドが全て実行されます。 string.format .

解決方法は?

いいえ、そんなことはありません。なぜ ScriptableObject s の代わりに、単純なクラス ( 私たちはこの質問から来ました そこで、例えばインスペクタで文字列を設定するか、あるいは以下のような方法で文字列を設定します。

new Character("abc", "xyz", "kfk", true);


しかし、例えば次のようなファクトリーメソッドを用意することができます。

[CreateAssetMenu]
[Serializable]
public class Character : Scriptable Object
{
    // Attributes
    public string firstName;
    public string middleName;
    public string lastName;
    public string fullName;
    public bool isMale;

    // Constructor
    private void Init(string _firstName, string _middleName, string _lastName, bool _isMale)
    {
        firstName = _firstName;
        middleName = _middleName;
        lastName = _lastName;

        // All The Functions 
        fullName = string.Format("{0} {1} {2}", firstName, middleName, lastName);

        isMale = _isMale;

        // and all the other functions like date calculator.
    }

    public static Character CreateCharacter(string firstName, string middleName, string lastName, bool isMale)
    {
        var character = ScriptableObject.CreateInstance<Character>();

        character.Init(firstName, middleName, lastName, isMale);
    }
}

または、例えば、次のようにします。

private void OnEnable()
{
    fullName = $"{firstName} {middleName} {lastName}";
}

というように、ゲーム開始時に存在するようにします。


どうしても欲しい場合 間に インスペクターにこれらの名前を入力すると カスタムインスペクター を実装することで Editor

#if UNITY_EDITOR
    using UnityEditor;
#endif

    public class Character : Scriptable Object
    {
        ...
    }

#if UNITY_EDITOR

    [CustomEditor(typeof(Character))]
    public class CharacterEditor : Editor
    {
        private SerializedProperty firstName;
        private SerializedProperty middleName;
        private SerializedProperty lastName;
        private SerializedProperty fullName;

        // called once when the Object of this type gains focus and is shown in the Inspector
        private void OnEnable()
        {
            firstName = serializedObject.FindProperty("firstName");
            middleName= serializedObject.FindProperty("middleName");
            lastName= serializedObject.FindProperty("lastName");
            fullName= serializedObject.FindProperty("fullName");
        }

        // kind of like the Update method of the Inspector
        public override void OnInspectorGUI()
        {
            // draw the default inspector
            base.OnInspectorGUI();

            serializedObject.Update();

            fullName.stringValue = $"{firstName.stringValue} {middleName.stringValue} {lastName.stringValue}";

            serializedObject.ApplyModifiedProperties();
        }
    }

#endif

を使用する代わりに #if UNITY_EDITOR もちろん CharacterEditor という名前のフォルダーに置いてください。 Editor . どちらの場合も、ビルドの際にそれに応じたコードが取り除かれます。