- Home /
How to create a TextAsset in a ScriptedImporter?
I'm trying to write a ScriptedImporter (the new experimental feature) that can import a third party data format into JSON. I've got all my conversion code done and working great.
But when it's time to implement the OnImportAsset() I'm stuck as to what I should provide to the ctx.SetMainAsset(). It's expecting a UnityEngine.Object so I can't just give it the string containing the JSON. So my assumption is that I should pass in a TextAsset, but its text field is read only and I have not found a way to instantiate a dynamic TextAsset by passing a string.
Should I use another asset type instead?
Answer by Bunny83 · Dec 16, 2017 at 12:59 PM
Unfortunately you can't create "TextAsset" instances manually. So if you want to just store the information as a string / text you would need to wrap it in a simple ScriptableObject
public MyImportedType : ScriptableObject
{
public string text;
}
MyImportedType inst = ScriptableObject.CreateInstance<MyImportedType>();
inst.text = yourJSONText;
// pass "inst" as asset.
I'm just wondering what type data format you're reading in. Storing the result as JSON seems a bit strange to me as JSON is also just an intermediate format. For example when importing a model you should create a Mesh right away. If you import a graphic format you should create a Texture asset.
It seems you want to use the "ScriptedImporter" not as an importer but rather a simple file converter. Just converting a file may be done outside Unity and just import the converted result.
Of course you could simply create a new text file next to the original source file and write your content to that file. This will of course create an actual TextAsset but it's of course seperate from the source file.
Well that didn't work out. Whereas I can successfully provide any other kind of assets to Set$$anonymous$$ainAsset(), trying to pass in a (valid) ScriptableObject will blow up everything (even a simple one with a single public string in it). It will silently import the resource, but if you click on it, the Editor start spam$$anonymous$$g errors indefinitely: AssetImporterEditor: assetEditor has null targets! UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr) NullReferenceException: Object reference not set to an instance of an object UnityEditor.Editor.OnHeaderIconGUI (Rect iconRect) (at /Users/builduser/buildslave/unity/build/Editor/$$anonymous$$ono/Inspector/Editor.cs:456) etc etc. Oh well, it IS an experimental feature after all :-/
Answer by $$anonymous$$ · Dec 17, 2017 at 12:49 AM
Thank you for your answer! Digging more last night I pretty much came to the same conclusion, which is fine really, and your answer helped me confirm this.
In fact that made me realize I may want to generate a ScriptedObject that is the final data object I'll use in game. My source data can target different data structures, I've had the idea to use a convention in the filename that will dictate which data class to deserialize to.
Using your MyImportedType example, I could name my data file:
hardLevels.MyImportedType.xlsx
which would look for the middle part (MyImportedType) and through reflection I'd instantiate the proper ScriptedObject class to deserialize and save my main asset with.
Anyway, I'm getting off topic, thanks again for your answer!
You can't create scriptableobjects with reflection. ScriptableObjects need to be created with ScriptableObect.CreateInstance
. There's a generic version (which i used in my example) but also a version that take a System.Type. If you don't create the scriptable object instance with CreateInstance but with "new" or the .NET Activator class, the class instance will become a fake-null instance.
Yeah I remembered that, which mean I would probably have to setup a factory ins$$anonymous$$d. But turns out it's a moot point, at least for the time being, as ScriptedImporter will crash when provided a ScriptableObject (and yes, properly instantiated through ScriptableObect.CreateInstance). Someone filled a bug report about this back in November and I voted for it, but I have no idea if that's going to get fixed anytime soon. The joys of playing with experimental features ;-)
Just in case someone else is having the same issue as I do, I've downgraded my Unity to 2017.1.2p4 and it's working great. Looks like Unity broke the ScriptableObject support to ScriptedImporters starting from 2017.2.X and upward. Hopefully someone at Unity notice it soon!
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Write data to Json database using SimpleJson.cs 1 Answer
Handling inheritance with JSONUtility.ToJSON 1 Answer
Assign public variables in design time... through code! 0 Answers