I know this can be done because the amazing plugin Odin, has some epic serialization tools.
I was hoping I could do this using Odin but even their [Serialize] tag doesn't work.
I want to serialize a new instance of a script inside of a Scriptable Object.
With Odin, you can serialize dictionaries, and if you serialize a dictionary which holds instance of an interface (script) it allows you to create a new instance of that script inside the dictionary like so:
Since its possible to store an instance of a script inside of a dictionary I am curious how this can be done on its own.
The script I want to save is a generic script with only functions and an empty constructor.
Do you know a why to serialize the instance of an interface (script) inside of a ScriptableObject?
Ideally I could create an attribute some how and just force it to serialize like so:
public class MyClass: MonoBehaviour
{
[ForceSerialize]
public IScript scriptToSerialize;
}
And then in the inspector I could just click the box and create a new instance of that script to be attached to the object.
You don't need any [Serialize] tag, MyClass simply has to inherit from Sirenix.OdinInspector.SerializedMonoBehaviour instead of MonoBehaviour.
These "Serialized" class (also exists for ScriptableObjects and the likes) need to be used in order for Odin's custom serialization to work, which would make your field appear in the inspector.
This script works for me:
using Sirenix.OdinInspector;
public class MyScript : SerializedMonoBehaviour
{
public IScript scriptToSerialize;
}
public interface IScript { }
Related
I have a Serializable object that I'm trying to store a method to be called. From this object, I would like to define a method from ScriptA to be called in ScriptB from SerializableScript.
The Serializable script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "NewFieldInput", menuName = "Data/New Field Input Scene")]
[System.Serializable]
public class CallInput {
public (some type) callMethod; // this is the confusing part
}
I would then have ScriptA have a method that will be called in ScriptB by referencing the value of callMethod passed into scriptB.
There are multiple solutions to your problem and it depends on the rest of your structure what would be the best to use.
UnityEvent where you create an event and add your target methods as listeners. In all other cases I would use C# events or actions instead but UnityEvents can be subscribed in editor.
You could create a base class that implements all the methods you want to call and inherit all your classes from that.
Basically the same but you create an Interface and add that to all classes you are calling.
It comes down to whether you want to only call your own code which you can modify or external code too. If the latter is the case you should go with option 1.
There are many more ways to do this but these came to mind first.
I'm not sure how else to word this question. so I will post screenshots of my problem.
How to I make
[SerializeField] private Sprite[] m_Sprites;
show up in the inspector here
I have tried public Sprite[] Sprites; and private Sprite[] m_Sprites as well with no effect, I've seen variables appear there but I cannot seem to figure it out now that I need it. After Further Attempts I have found that a public Sprite Sprite; appears however I require it to be an array of Sprites. I also tried creating a holder class and defining the array inside there and it still doesn't appear.
The only field types allowing default references are fields of a type derived from UnityEngine.Object
... a Sprite[] is an array and does not inhertit from UnityEngine.Object.
As mentioned before you could use a ScriptableObject wrapper class such as e.g.
// this attribute adds an entry to the Asset context menu Add->SpriteCotnainer
[CreateAssetMenu]
public class SpriteContainer : ScriptableObject
{
public Sprite[] sprites;
}
then in your class use a
[SerializeField] private SpriteContainer spriteContainer;
which now is of type ScriptableObject which inherits from UnityEngine.Object so it should show up as default reference field.
So you would need to create this asset via right click on Assets → Add → SpriteContainer. Here you can reference all the sprites you need. Then drag this into the spriteContainer field of your script.
You have two options, either create a gameobject/prefab, add the script to it - and then it will appear.
Or, if it's just a data object you need to access, you can make it a ScriptableObject and create an instance of it.
Either way, you will have to create an instance; you can't assign variables to scripts, only objects with the scripts attached.
Odd question here - I have a gameobject with a class object attached. I instantiate the gameobject, and assign the class object with data from an existing class.
I then instantiate a second gameobject with the exact same class object attached and assign it the same data as the first object. If I modify the class attached to the first gameobject, it is different to the class attached to the second object, even though they both reference (or should) reference the same original class.
Can anyone think why this would happen?
if you make the variables you want to persist in the class your adding static, it will use the same instance for both cases, modifying both when you mod one.
check out this enemy class from unity3d's own dev pages
https://unity3d.com/learn/tutorials/topics/scripting/statics
using UnityEngine;
using System.Collections;
public class Enemy
{
//Static variables are shared across all instances
//of a class.
public static int enemyCount = 0;
public Enemy()
{
//Increment the static variable to know how many
//objects of this class have been created.
enemyCount++;
}
}
They are different instances of the same class, they don't reference the same class.
You should write a duplicate method to duplicate the values
I define my class with ISerializationCallbackReceiver in ScriptableObject, and write my serialized code in OnAfterDeserialize. My problem is I need to do some environment preparing before OnAfterDeserialize, but ISerializationCallbackReceiver will call when unity startup.
Is there a class or function called right before ISerializationCallbackReceiver so I can add my code before unity begins to serialize ScriptableObject. I've already tried the RuntimeInitializeOnLoadMethod Attribute but it is called after ISerializationCallbackReceiver.
Is there a class or function called right before
ISerializationCallbackReceiver so I can add my code before unity
begins to serialize ScriptableObject.
The ISerializationCallbackReceiver interface has two functions which are OnBeforeSerialize and OnAfterDeserialize.
You can use the OnBeforeSerialize function to add your code because it will be called before Unity serializes your object
I want to instantiate in a class that is not a monobevaviour.
At the moment I call a helper class to do it but I want to reduce dePendency.
You can simply do this:
MonoBehaviour.Instantiate(ObjectPrefab);
This is because Instantiate is actually static in the MonoBehaviour class.
You can instantiate GameObjects or anything that derives from GameObject. ScriptableObjects are very useful.
If you don't want the Update/Start/Awake/etc. methods that are part of GameObjects, then you can use constructors of any objects that you want to Instantiate and/or create your own Instantiate methods.