I'm trying to write a tool that scans through our Unity (2017.4.22) prefabs and scene files to look for Monobehaviour properties that don't exist in a release build. I've created a c# console project (incorporating YamlDotNet 6.1.2), and from this project I refer to Unity's 'Assembly-CSharp-firstpass.dll' and 'Assembly-CSharp.dll' dlls.
I was wondering if anyone has been able to configure YamlDotNet to parse any given prefab/scene file into a generic key/value data structure (with an arbitrary number of nested levels) in memory, so I can iterate it and use reflection to determine if fields exist.
If you're wondering why I need to do this manually, it's because I'm scanning for fields that don't exist in release builds. The only way to do that is to recompile 'Assembly-CSharp-firstpass' and 'Assembly-CSharp' with UNITY_EDITOR removed (and all code from files within a 'Editor' subfolder) culled. I can't do this in-editor (obviously) so that's why this has to be a standalone tool.
Everything I've tried has resulted in crashes. Here's what I tried:
I downloaded the YamlDotNet 6.1.2 source
Tried to deserialize a prefab using Deserialize(...). Received this error: "Encountered an unresolved tag 'tag:unity3d.com,2011:1'"
I then found this custom Type resolver, which I integrated: https://gist.github.com/derFunk/795d7a366627d59e0dbd
I then started receiving this exception: "Exception during deserialization ---> System.InvalidOperationException: Failed to create an instance of type 'UnityEngine.GameObject'"
I'm guessing this is is happening because I'm trying to instantiate a GameObject in an environment that doesn't fully support GameObjects (I am in a standalone C# project after all).
But I don't actually need to instantiate any GameObjects. I just want to parse the values. Does this make sense to anyone? I found a few other questions here but they don't seem to handle YAML files that are at the same complexity as Unity's prefabs.
Thanks in advance,
Jeff
Your guess is correct. Because you are resolving the tag:unity3d.com,2011:* tags to UnityEngine.GameObject and related types, then the deserializer attempts to create an instance of the corresponding type when it encounters the tags.
You could opt to always resolve the tag to Dictionary<string, object> (or Dictionary<object, object> if the keys are not always strings). Then always get dictionaries.
In your case it is probably simpler to load the YAML stream using YamlDotNet.RepresentationModel.YamlStream. This will give you a representation of the YAML document that will be more suitable for your use case.
Here's the official example on how to do it: https://github.com/aaubry/YamlDotNet/wiki/Samples.LoadingAYamlStream
// Load the stream
var yaml = new YamlStream();
yaml.Load(input);
// Examine the stream
var mapping = (YamlMappingNode)yaml.Documents[0].RootNode;
Related
So I was reading Odin's docs and from there I noticed mentions that the serialization system is needed in the compiled build. AFAIK, Serialization is used for scene saving and inspector stuff - none of this is needed in the game-ready compiled build.
Then what's the purpose of serialization system in a compiled build?
In general serialization means nothing more than storing certain values serialized into a file e.g. the Unity scene or any Assets like Prefabs or ScriptableObjects. You can basically open all of them in a texteditor and see their serialized version.
In general everything serialized means you can configure it in the Inspector and on runtime/in a build the instances will be generated using the serialized (stored) values for their fields instead of default ones.
Basically e.g. any serialized field like
[SerializeField] private float value;
or
public string someString;
works like this and ofcourse requires at least some kind of deserialization system on runtime and in a compiled build.
It is further possible to also use serialization and deserialization on runtime /in a build for e.g. converting classes from and to JSON or XMl or other formats or load and create assets or AssetBundles.
Therefore it makes completely sense to have (de)serialization systems in a build and it is very unlikely to find a system that has the serialization isolated from the deserialization.
Specific for the Odin Inspector: It uses the serialzation system to - how they say - serialize everything. This even allows you to store scene references in prefabs so the prefab once instantiated can restore the according references from the scene.
I have successfully compiled several MIBs into JSON using PySMI with JsonCodeGen and CallbackWriter (which uploads the parsed JSON to cloud storage). Now I am trying to build an index using freshly compiled JSON MIBs in combination with already-compiled JSON files.
From the documentation, it looks like I need to pass all of these files to mibCompiler.compile() function, even though most of them have already been compiled, so that I can run mibCompiler.buildIndex() after compiling.
From what I understand, I need a searcher to exclude the already-compiled JSON MIBs...is this the case? All I see in the current code are PyFileSearcher, StubSearcher, and AnyFileSearcher. I 'm not sure what to do from here to ignore my JSON files.
I'm also not sure buildIndex() will even accept JSON files as input, so I'm hoping this is the right approach.
Thanks in advance!
I'm also not sure buildIndex() will even accept JSON files as input, so I'm hoping this is the right approach.
Actually, no! Present day PySMI compiler can only parse ASN.1 MIBs, it will fail on JSON input.
Probably the simplest solution would be to just load JSON MIBs and existing JSON index into Python as dicts, walk the dicts updating one another. Here is the code that builds JSON index dict out of some internal objects (which carry pieces of MIB data).
From PySMI perspective, the best course of action would probably be to introduce a JSON MIB compiler which would turn JSON MIB into the abstract syntax tree from which JSON MIB index could be build...
I'm trying to Save/Serialize a GameObject and its components (with their current values), but I don't think it's possible, any ideas ???
Keep in mind that I don't wanna use an asset from the assets store, I wanna code it myself.
Thanks in advance :)
Sorry I dont have the rep to make a comment. I use two methods to acheive this save state.
First is what programmer seems to suggest, make a class that hosts the property's needed to recreate the object. Component names can be saved as strings, then fetched using
gameObject.AddComponent(Type.GetType(componentName));
If you are doing this alot it may be worth checking out this forum first.Here
You can serialize these classes using the unity serializer(the string names of types will serialise. You may have to make a sub class to handle the values in each object of different type.
This can be a fairly complicated approach so I prefer a file path serialized for a prefab in the resources folder. Any values that need saving can be saved in a serializable class like first approach which is referenced in a script on the saved prefab. This script has a method to apply all details saved in the deserialized class to the prefab when it is created. The details are captured by the script,added to the class and serialized whenever the object state should be recorded.
The exact way this is managed may vary but I have done this myself with he ability to store any values I could need. Even if you use a third party serializer from the asset store you will still have trouble saving entire objects, but you will be able to get enough info to recreate.
I've managed to save the components I want (custom scripts) by saving them in a json file, then serializing them with binary so they can be more secure.
Thanks to everyone who tried to help tho...
After migrating to Play-2.1 I stuck into problem that routes compiler stopped working for my routes file. It's been completely fine with Play-2.0.4, but now I'm getting the build error and can't find any workaround for it.
In my project I'm using cake pattern, so controller actions are visible not through <package>.<controller class>.<action>, but through <package>.<component registry>.<controller instance>.<action>. New Play routes compiler is using all action path components except for the last two to form package name that will be used in managed sources (as far as I can get code in https://github.com/playframework/Play20/blob/2.1.0/framework/src/routes-compiler/src/main/scala/play/router/RoutesCompiler.scala). In my case it leads to situation when <package>.<component registry> is chosen as package name, which results in error during build:
[error] server/target/scala-2.10/src_managed/main/com/grumpycats/mmmtg/componentsRegistry/routes.java:5: componentsRegistry is already defined as object componentsRegistry
[error] package com.grumpycats.mmmtg.componentsRegistry;
I made the sample project to demonstrate this problem: https://github.com/rmihael/play-2.1-routes-problem
Is it possible to workaround this problem somehow without dropping cake pattern for controllers? It's the pity that I can't proceed with Play 2.1 due to this problem.
Because of reputation I can not create a comment.
The convention is that classes and objects start with upper case. This convention is applied to pattern matching as well. Looking at a string there seems to be no difference between a package object and normal object (appart from the case). I am not sure how Play 2.1 handles things, that's why this is not an answer but a comment.
You could try the new # syntax in the router. That allows you to create an instance from the Global class. You would still specify <package>.<controller class>.<action>, but in the Global you get it from somewhere else (for example a component registry).
You can find a bit of extra information here under the 'Managed Controller classes instantiation': http://www.playframework.com/documentation/2.1.0/Highlights
This demo project shows it's usage: https://github.com/guillaumebort/play20-spring-demo
I'm trying to work through groovy's Implementing Local AST Transformations tutorial, but whenever I clean my project I get this error in each file that has the #WithLogging annotation in it:
Groovy:Could not find class for Transformation Processor AC.LoggingASTTransformation declared by AC.WithLogging
So you have a package named "AC" that contains both "WithLogging.groovy" and "LoggingASTTransformation.groovy" classes? Does it also contain any classes that implement the "WithLogging" interface?
If so, I'd suggest you move the class(es) that use your annotation to a location outside of the annotation defining package (the default will suffice, for diagnostic purposes) - Order of compilation matters with transformations. See this post on the groovy users mailing list for more on that.
Also try changing the annotation from #WithLogging to #AC.WithLogging.
As far as cleaning with Eclipse is concerned, I had a similar issue and found that I had to make a trivial modification after a clean to any file that contained my annotation. IE, add a space somewhere. Then save the file. This should rebuild everything properly.