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.
Related
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 { }
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 found a way to get around this issue in the code, but I would like to understand why this is happening because I want to learn C# well. I´ve searched a lot and could simplify the problem, here's the simplified code:
/*MyCustomComponent.cs, this is attached to a game object in the scene*/
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MyCustomComponent : MonoBehaviour {
void Start () {
Test testInstance = new Test();
Debug.Log (testInstance);
Debug.Log (testInstance == null);
Debug.Log (testInstance.Equals(null)); //Also tried the same with Equals()
Debug.Log (testInstance.value);
}
}
/*Test.cs*/
using UnityEngine;
using System.Collections;
public class Test : Object {
public int value = 7;
public Test(){
}
}
Console Output:
null
true
7
Why is this happening? How can be possible an Object is null but returns a property value?
Because Unity.Object works in a very peculiar way, basically it contains data regarding the managed object while pointing to the native object (crudely speaking).
Let's make an example: you create a new object inheriting from MonoBehaviour. Now you have two objects, one on the native side and one on the managed side. You can access the instanceID propriety of the managed object thanks to the fact that MonoBehaviour inherits from Unity.Object. Basically, the latter is used to show all the relative data of the object in the Inspector.
Now, you want to Destroy this game object by calling the same named method. The native object is actually destroyed, but the managed object is not, since all managed objects can only be destroyed by the garbage collector. It's at this point that Unity.Object becomes null: it's a trick of the Unity engine uses in order to avoid that you try to access a native object which doesn't exist anymore. Eventually, when the GC is called, this Unity.Object will be destroyed too.
And this is why you should never create an Unity object which inherits directly from Unity.Object, but only from MonoBehaviour or ScriptableObject.
I only have a small experience in Unity3D, but I noticed that classes that derive from MonoBehaviour may contain functions with predefined signatures that will be called in a special way. For instance, if I write:
void Update()
{
//some code
}
this method will be called every frame.
I imagine that inside Unity there is some sort of an endless loop that calls the Update method every frame for each object on the scene. But how does it know that the object actually provides the Update method implementation? It would have been clear if Update was an override for a method in the MonoBehaviour class, but judging by the syntax (and the fact that you can implement such methods with any access modifier) it's not. Is there some reflection magic happening there?
http://blogs.unity3d.com/2015/12/23/1k-update-calls/
No, Unity doesn’t use System.Reflection to find a magic method every
time it needs to call one.
Instead, the first time a MonoBehaviour of a given type is accessed
the underlying script is inspected through scripting runtime (either
Mono or IL2CPP) whether it has any magic methods defined and this
information is cached. If a MonoBehaviour has a specific method it is
added to a proper list, for example if a script has Update method
defined it is added to a list of scripts which need to be updated
every frame.
During the game Unity just iterates through these lists and executes
methods from it — that simple. Also, this is why it doesn’t matter if
your Update method is public or private.
In Unity3d you have the MonoBehaviour class, which is the normal base class for all scripts. When implementing a script, one has to implement the methods such as Awake() or Start() or Update().
However, These methods are not implemented as virtual or abstract in the MonoBehaviour class so that one could easily override them; in fact they are not implemented at all. The method one writes at the Moment is a new method that the class did not have beforehand.
Why are these methods not implemented as virtual or abstract in the base class (MonoBehaviour)?
If you check the documentation you will see that all those 'functions' are listed in the 'Messages' section; MonoBehaviour Doc.
So that means that 'functions' (like Start, OnEnable or Awake), they are not implemented as methods but as messages.
Now, MonoBehaviour inherits from Behaviour, which inherits from Component which has the SendMessage method. That method basically calls a message/method with the option to report an error if the message/method exists or not. The parameter of the name message/method is a string, /~~so they are using reflection there.~~/ Check Update!!
Seems like Unity behind the scenes determines if those messages were implemented to see if it has to call them or not. According to this UnityAnswer:
Unity is mainly written in c++ and therefore most magic happens in
native code. Unity uses reflection to determine, after your scripts
have been compiled, what of those "events" you've implemented and
remember that for this class. Unity only calls Update / LateUpdate /
OnGUI when it has been implemented.
So, the short answer is, they are not 'real' methods that you have to override, they are messages that are called only if they were implemented.
Update;
As #Raining noted, I was wrong in the way that Unity obtains the messages to call.
Unity doesn't use reflection to do this.
According this 1k-update-calls (also provided by #Rainin) scripts are inspected to check if they contain some of those 'magic methods'. If so, they are added to lists that will be executed accordingly.