NodeCanvas Forums › Support › [Bug] Graph OnEnable() fires on Load, causes errors
I’ve been getting some errors on builds only (not in the editor). The error reported is…
TargetException: Non-static field requires a target
at System.Reflection.MonoField.SetValue (System.Object obj, System.Object val, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Globalization.CultureInfo culture)
…
at ParadoxNotion.Serialization.JSONSerializer.TryDeserializeOverwrite[T] (T instance, System.String json, System.Collections.Generic.List
1[T] references)
at NodeCanvas.Framework.Graph.Deserialize (System.String serializedGraph, System.Collections.Generic.List1[T] references, System.Boolean validate)
at NodeCanvas.Framework.Graph.UnityEngine.ISerializationCallbackReceiver.OnAfterDeserialize ()
After discussing on Discord, I figured out that Graph.cs
(a ScriptableObject) has an OnEnable()
function that is called immediately upon load. The key here is that scriptableObjects are enabled on LOAD, not on instantiation, so this happens before objects are in the scene.
During OnEnable(), it attempts to validate the graph – which fails if you are using reflection, since this is happening on Scene Load, not on my AI object isn’t in the scen yet.
You can recreate this — just throw a Debug.Log in Graph.OnEnable():52, delete everything in your scene, and hit play. You’ll see the debug log pop up once for each Graph object in your project.
Hey,
Yes, scriptable object OnEnable is called when the object is loaded. This is a known fact and the code is designed around this, thus OnEnable and as a consequence Validate should be called when the graph loads (deserializes) :). The error you posted above however does not really have anything to do with OnEnable as far as I can see, but rather has to do with the OnAfterDeserialize call.
Thanks!
Join us on Discord: https://discord.gg/97q2Rjh
Sure, here’s the error I’m getting:
TargetException: Non-static field requires a target
at System.Reflection.MonoField.SetValue (System.Object obj, System.Object val, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Globalization.CultureInfo culture) [0x00000] in <00000000000000000000000000000000>:0
at System.Reflection.FieldInfo.SetValue (System.Object obj, System.Object value) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.Internal.fsReflectedConverter.TryDeserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Object& instance, System.Type storageType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.fsSerializer.Internal_Deserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Type storageType, System.Object& result, System.Type overrideConverterType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.fsSerializer.TryDeserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Type storageType, System.Object& result, System.Type overrideConverterType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.Internal.fsReflectedConverter.TryDeserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Object& instance, System.Type storageType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.fsSerializer.Internal_Deserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Type storageType, System.Object& result, System.Type overrideConverterType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.fsSerializer.TryDeserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Type storageType, System.Object& result, System.Type overrideConverterType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.Internal.fsReflectedConverter.TryDeserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Object& instance, System.Type storageType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.fsSerializer.Internal_Deserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Type storageType, System.Object& result, System.Type overrideConverterType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.fsSerializer.TryDeserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Type storageType, System.Object& result, System.Type overrideConverterType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.Internal.fsListConverter.TryDeserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Object& instance_, System.Type storageType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.fsSerializer.Internal_Deserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Type storageType, System.Object& result, System.Type overrideConverterType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.fsSerializer.TryDeserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Type storageType, System.Object& result, System.Type overrideConverterType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.Internal.fsReflectedConverter.TryDeserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Object& instance, System.Type storageType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.fsSerializer.Internal_Deserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Type storageType, System.Object& result, System.Type overrideConverterType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.FullSerializer.fsSerializer.TryDeserialize (ParadoxNotion.Serialization.FullSerializer.fsData data, System.Type storageType, System.Object& result, System.Type overrideConverterType) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.JSONSerializer.Internal_Deserialize (System.Type type, System.String json, System.Collections.Generic.List1[T] references, System.Object instance) [0x00000] in <00000000000000000000000000000000>:0
at ParadoxNotion.Serialization.JSONSerializer.TryDeserializeOverwrite[T] (T instance, System.String json, System.Collections.Generic.List1[T] references) [0x00000] in <00000000000000000000000000000000>:0
at NodeCanvas.Framework.Graph.Deserialize (System.String serializedGraph, System.Collections.Generic.List1[T] references, System.Boolean validate) [0x00000] in <00000000000000000000000000000000>:0
at NodeCanvas.Framework.Graph.UnityEngine.ISerializationCallbackReceiver.OnAfterDeserialize () [0x00000] in <00000000000000000000000000000000>:0
UnityEngine.Logger:LogException(Exception)
ParadoxNotion.Services.Logger:ForwardToUnity(LogType, Object, String, Object)
ParadoxNotion.Services.Logger:Internal_Log(LogType, Object, String, Object)
ParadoxNotion.Services.Logger:LogException(Exception, String, Object)
NodeCanvas.Framework.Graph:Deserialize(String, List1, Boolean)
NodeCanvas.Framework.Graph:UnityEngine.ISerializationCallbackReceiver.OnAfterDeserialize()
This error pops up immediately upon play, basically on the first frame of the app running (before any Start() functions get called anyway).
I’m on Unity 2020.1.1f1, with the latest NodeCanvas in the PackageManager: 3.0.9
My graph is fairly simple, but it does contain some reflection references (execute function on local script) that show up as red in the behaviour tree if I don’t have the prefab selected;
I’m guessing this is what the error is in reference to.
everything works fine and is error-free once the prefab is instantiated.
Bah, your forum doesn’t seem to have code tags, but editing them in breaks the image embeds. here’s that image again:
Hello again and thanks for the extra info and the log. (albeit its format the info is there)
As far as I can see, this error is totally irrelevant from the fact that you are using a reflection-based task (like execute function), since the error stack roots from the graph deserialization itself (which is using reflection as well). That is weird.
Is there the possibility at all for you to please send me the project (or a similar reproduction project). I’ve tried replicating this in various setups, but none of the tests yielded any apparent and similar errors.
If that is possible to send to ‘support_AT_paradoxnotion.com’ , that would be very helpful!
Please let me know,
Thank you!
Join us on Discord: https://discord.gg/97q2Rjh
Email sent with repro project!
Is there any result with this?
I got exactly same issues when I build on XBOX scarlett
Hello,
What version are you using please?
Do you have the exact same issue, or something else but related?
Thanks.
Join us on Discord: https://discord.gg/97q2Rjh
Node Canvas Version: 3.2.1
Unity Version: 2020.3.14 lts
Background:
1. Created simple script to add all scripts under Assets folder to type prefs editor. And then used it to collect all possible types.
2. Create AOT.cs, link.xml.
3. Launch game in XBOX Scarlett (the new xbox series)
4. Got an errors when load Player object that has FSM. then game crashes.
5. Works fine if i get rid of player. (no errors appear)
Error:
TargetException: Non-static field requires a target at System.Reflection.MonoField.SetValue (System.Object obj, System.Object val, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Globalization.CultureInfo culture) [0x00000] in <00000000000000000000000000000000>:0 at System.Reflection.FieldInfo.SetValue (System.Object obj, System.Object value) [0x00000] in <00000000000000000000000000000000>:0 at ParadoxNotion.Serialization.FullSerializer.Internal.fsReflectedConvert
n.JSONSerializer.TryDeserializeOverwrite[T] (T instance, System.String json, System.Collections.Generic.List1[T] references) [0x00000] in <00000000000000000000000000000000>:0 at NodeCanvas.Framework.Graph.Deserialize (System.String serializedGraph, System.Collections.Generic.List
1[T] references, System.Boolean validate) [0x00000] in <00000000000000000000000000000000>:0 at NodeCanvas.Framework.Graph.UnityEngine.ISerializationCallbackReceiver.OnAfterDeserialize () [0x00000] in <0000000000000000000000 ………………
—-
Are their any possible errors in AOT Platform even if I have created AOT Classes?
I wonder why that error has appeared. and how snugglepilot have managed to fix this.
I think I found the cause and a solution. I will post it after I check it works. 🙂
Hello.
I have managed to solve this problem for our own, we got some result that we want to share, and want to get some advise from you.
What we did:
1. We have assumed the errors are from ‘Reflection’ features of node canvas. such as – ‘Check C Sharp Event’, ‘Check Property’.. etc.
2. There were too many scripts that used by our team (up to 10 – 12 people), So it seems too inefficient to manually add ‘Preferred types’.
3. So I have have created custom script to ‘Collect all possible scripts in projects except the ones in ‘excluding list”, and then created AOT Classes, Link.xml again. (shown as below)
Result
1. Many of errors have been actually removed and game has became playable for some point…! but still some of them remains, causing few buggy-situation in game..
Problem
1. It is too difficult to point out which script or which Nodecanvas graph is causing problem.
What I Want:
1. I want to address which script or nodecanvas graph is causing problem!
2. Is there any way to specify the origin of the error? (TargetException: Non-static field requires a target at System.Reflection.MonoField.SetValue)
Node Canvas Version: 3.2.1
Unity Version: 2020.3.14 lts
Developing for: XBOX Scarlett
Hello again,
Within the Unity Editor, the Graph Console window will allow to point you to the graph-node that causes the exception, however if the exception only occurs in build then it is not possible. With that said you could add a debug log to help pinpoint at least the name of the object failing (in this case the graph’s name). Please open up “Logger.cs” and change the “ForwardToUnity” method to be like this:
1 2 3 4 5 6 7 8 9 10 11 12 |
private static void ForwardToUnity(LogType type, object message, string tag, object context) { if ( message is System.Exception ) { UnityEngine.Debug.unityLogger.LogException((System.Exception)message); if ( context != null ) { UnityEngine.Debug.unityLogger.Log(LogType.Error, tag, string.Format("Exception Occured on Object: {0}", context.ToString()), context as UnityEngine.Object); } } else { UnityEngine.Debug.unityLogger.Log(type, tag, message, context as UnityEngine.Object); } } |
This should log the name of the graph right after the exception. Please let me know if that helps.
Having said all the above, this exception is usually because something used (serialized) in NodeCanvas has been code-stripped away (this is where the link.xml file comes into play to avoid such code-stripping). Your method of adding all scripts should have fixed this, however if you are using some type from a DLL library, Unity Package Library, or something that is not defined in a “monoscript”, then it may be getting code-stripped away. Can you please confirm whether there is a possibility of a type being used in NodeCanvas that is from some non- “monoscript” library like a DLL, or maybe even from with a “plugins” folder and there is the possibility that such a type is not included in the Preferred Types Editor (and thus possibly being code-stripped away)?
Thank you!
Join us on Discord: https://discord.gg/97q2Rjh
Hi.
Thank you for your detailed suggestion. I will try that out and tell ya later.
1. I will fix Logger code as you suggested.
2. I will examine if there are any graphs using DLL or pacakages.
Thank you. 🙂
Hi.
Right now I have fixed all primary issues with porting NodeCanvas into XBOX.
I want to share what I tried from your last answer.
Background:
– I have edited Logger.cs but nothing have been different.
How I have solved the problem:
– According to the lines of the exception, error was occurred from ‘OnAfterDeserialization’ Method and it was in GraphOwner.cs.
– But I couldn’t know which line of it exactly occur the error, so I have applied try-catch block like below.
– But it was not much effective so far because I couldn’t know which GameObject or Graph is causing error. So I added little trick like below.
– From this, I was able to know which graphs are causing error, and which Exposed Parameter is causing Error
– Surprisingly, the errors was from Double parameters.
– Double was not in the default type, so It wasn’t in AOTClass.cs or link.xml.
– So I have added double or any other types that I think it as a essential.
– Generate AOTClasses and link.xml again, then it solved.
Conclusion:
– I think error logs when deserialization or when using reflection feature need to be more effective. Like how I did above.
I feel so happy this finally got nearly end. Thanks for the help. 🙂
Hello again,
Thank you for the details and I am really glad that you found the culprit and got it solved!
I will look into adding some logging (or other solution) to handle these situations.
Thanks!
Join us on Discord: https://discord.gg/97q2Rjh