Reputation: 105
I have a Character Scriptable Object and I have several methods in it. Like GetDate,GetAge (which I am not showing here). I have created a Constructor there, but I don't know how to create an instance of that ScriptableObject through the Constructor. That's what I want to do.
I have tried to just type the values in the inspector but that did not run the methods in the Constructor.
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.
}
}
I want to create an instance of this Scriptable Object through this Construction. Something like
Character char("x", "y", "z", true);
or when I type the required fields in the Unity Inspector, then it will run all the methods like that full name string.format
.
Upvotes: 2
Views: 13665
Reputation: 90580
No, not like that. It is still unclear why you have to use ScriptableObject
s
instead of having a simple class (we came from this question) where you would simply configure those Characters e.g. in the Inspector or use eg.
new Character("abc", "xyz", "kfk", true);
You could however have some kind of factory method like e.g.
[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);
return character;
}
}
or alternatively do it e.g. in
private void OnEnable()
{
fullName = $"{firstName} {middleName} {lastName}";
}
so it is there when the game starts.
If you really want to have it while typing those names in the Inspector you won't come around using a Custom Inspector by implementing 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
alternatively to using #if UNITY_EDITOR
you can ofcourse have the CharacterEditor
in a complete separate script and put that one in a folder named Editor
. In both cases the according code is stripped of in a build.
Upvotes: 6
Reputation: 66
You can't create a new ScriptableObject Instance using a constructor (much like a monobehaviour). so you need to use Unity API methods
I have added a working sample
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;
}
}
and here is the class that creates the Character
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;
}
}
Upvotes: 3