【问题标题】:Create a Scriptable Object Instance through a Constructor通过构造函数创建可编写脚本的对象实例
【发布时间】:2019-05-13 14:22:04
【问题描述】:

我有一个 Character Scriptable Object,其中有几个方法。像 GetDate,GetAge (我没有在这里展示)。我在那里创建了一个构造函数,但我不知道如何通过构造函数创建该 ScriptableObject 的实例。这就是我想做的。

我尝试只在检查器中输入值,但没有运行构造器中的方法。

Character.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.
    }
}

我想通过这个构造创建这个 Scriptable Object 的一个实例。类似的东西

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

或者当我在 Unity Inspector 中键入必填字段时,它将运行所有方法,例如全名 string.format

【问题讨论】:

  • 以构造函数内部的string.format函数为例。假设我只是在 Unity 中创建了一个 ScriptableObject,然后在 Inspector 中键入 firstNamelastNamemiddleName。那么,当我单击播放按钮时,它是否有可能执行 fullName = string.Format("{0} {1} {2}", firstName, middleName, lastName); 方法。它只会让我的生活更轻松。

标签: c# unity3d


【解决方案1】:

不,不是那样的。目前还不清楚为什么你必须使用ScriptableObjects 而不是有一个简单的类(we came from this question),您可以在其中简单地配置这些字符,例如在 Inspector 中或使用例如。

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来使用Custom Inspector

#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 的文件夹中。在这两种情况下,相应的代码都会在构建中被删除。


【讨论】:

  • 我想我得把这个文件放到Editor文件夹中
  • 好的,试试#if UNITY_EDITOR。就一个问题。那OnEnable()是什么意思
  • 不!如果你想使用 Editor 文件夹,那么只有 CharacterEditor 必须在其中。你可以把它放在一个完全分离的文件中
  • 您是否重命名了字符串变量?它们必须与FindProperty 中的编辑器脚本中的匹配。正如你在 gif 中看到的那样,它对我有用......
【解决方案2】:

您不能使用构造函数创建新的 ScriptableObject 实例(很像单一行为)。 所以你需要使用 Unity API 方法

我添加了一个工作示例

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

[CreateAssetMenu]
[Serializable]
public class Character : ScriptableObject
{
// 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.
}

public void Initialize(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;
}

}

这里是创建角色的类

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

public class Tester : MonoBehaviour
{
int characterCounter = 0;

// Update is called once per frame
void Update()
{
    if(Input.GetMouseButtonDown(0))
    {
        Character c = CreateMyAsset();
        c.Initialize("a", "b", "c", true);
    }
}

public Character CreateMyAsset()
{
    Character asset = ScriptableObject.CreateInstance<Character>();

    string assetName = "Assets/c" + characterCounter + ".asset";
    characterCounter++;

    AssetDatabase.CreateAsset(asset, assetName);
    AssetDatabase.SaveAssets();

    EditorUtility.FocusProjectWindow();

    Selection.activeObject = asset;
    return asset;
}


}

【讨论】:

  • 好的,谢谢你的回答(我认为这是一个完美的答案)但是有什么办法可以在检查员中完成CreateMyAsset()
  • 绝对。您可以在编辑器脚本中编写它。这是一个有点大的主题,但我会从 Unity 的编辑器脚本教程开始
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 2015-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-05
相关资源
最近更新 更多