I digged about how to link Ink from Inkle to AC.
So far, may be a nice way would be to be able to make an external JSON "adapter" (being able to read JSON from AC, adapt Ink and paste back to create a list of linked actions).
So first step would be to be able to copy and paste ActionList as JSON.
I don't want to hack AC but here's a preview


Do you think this would be valuable for AC? (I do)
Comments
Apart from the Inspector changes, I don't think there'd be another need for any hacking to be involved. Aside from the convenience, it'd be possible to do via another script.
Here's a test script for you to test out:
http://pasteall.org/962253/csharp
It'll make a new "Test" menu item in the "Adventure Creator" top toolbar. It only works for scene-based ActionLists, but replace with ActionList with ActionListAsset
and it should work for assets instead.
Thank you for providing such a great and detailed answer!
I really appreciate
I didn't know how to "piggy back" the menu and you provide a great solution.
I replaced ActionList with ActionListAsset thinking that it will collect all actions present in the asset, but it only gives the root level and points to instanceID for actions:
But, I can see actions are present in the .asset file.
- messageText field is the most important for Ink.
- constantID would be great to fill in based on Unity constantID assignment (prior to Paste).
Since we can "Add/Insert" a new action, I guess we could "insert using JSON" multiple actions?I guess skipActionActual with fileID are out of scope and it means we'll have to wire actions within Unity (or else?). On forums, this fileID/instanceID seems to be a pain to develop external tools.
It's level 0 of the asset. No sub-levels (actions).
It looks like array is the problem. Both for copying and pasting.
I tried to crawl the forum without luck.
Which leads to questions:
What is expected when clicking "Add new Action"?
Could we create multiple actions at once?
Filling them with Json array content?
I'm slow, partially because I suck at coding (hence me buying AC) and partially because JsonUtility sucks too (big time).
In the end I added JSON .NET from asset store (Newtonsoft.Json) because it serializes "everything" then I tried:
dataString = JsonConvert.SerializeObject(actionList);
But when I try to get the JSON, I get an error about ActionSpeech (within AC?):
What's up with ActionSpeech?
(Or may be another solution would be to foreach each action, but it doesn't recognize ActionList as a valid type.
To help, most useful posts I found were: https://stackoverflow.com/questions/36239705/serialize-and-deserialize-json-and-json-array-in-unity/...
and https://blog.csdn.net/xdestiny110/article/details/79596953 (end of the page))
I can't do more but wait for your yoda's vision on it
My mistake about assets being as simple - ActionListAssets actually hide their Actions sub-assets within them, so in hindsight I don't know how possible it can be. I shall to some further testing, however.
Copy/pasting individual Actions as Json data is risky, because of their inderdependency. You could likely make an "insert after", but don't expect them to connect with each other all as intended. AC's ActionListEditorWindow does a lot of heavy lifting to have each inserted Action connect automatically. But if you want to give it a go, it's really just a case of modifying the internal "actions" List.
A few other thoughts:
1) Since scene-based ActionLists seem to be OK, bear in mind that ActionLists can be converted between scene-based and asset files via the cog icon at the top of their Inspector.
2) If you're mainly interested in transferring speech lines, it might be easiest to have your "dialogue sequence" as a separate ActionList, and then call upon from a separate one with ActionList: Run - that way you can leave other Actions that you don't care about editing in Ink out of the process.
3) I'm fairly sure Dialogue System, which has a robust AC integration, has Ink/Json support - though you'll need to contact the developer for confirmation. It would be worth looking into as an alternative.
1:30AM, you're passionate!
"My own testing found no issue with a scene-based ActionSpeech"
Do you mean you get the actions details (not fileID or instanceID) in the JSON string?
I get the same error about headClip.
Sideline, I had to re-import the package, I had error:
Assets/AdventureCreator/Scripts/ActionList/ActionListAsset.cs(31,15): error CS0101: The namespace `AC' already contains a definition for `ActionList'
File has been modified ("public class ActionListAsset : ScriptableObject" to "public class ActionList : ScriptableObject") but I didn't.
"it's really just a case of modifying the internal "actions" List"
How?
"You could likely make an "insert after""
How?
1) yes. I focused on asset to avoid breaking embedded actions (I made a copy of asset file)
2) totally!
3) Out of budget and limited import. I prefer JSON to really see the limitations.
So it's a question of wrapping (and unwrapping) the nested action inside the actionList.
I don't get how to use ISerializationCallbackReceivers to parse/serialize on the fly so I'm going the ugly regex way on the string:
dataString = Regex.Replace(JsonUtility.ToJson(actionList),"\"actions.+?],","");
dataString = Regex.Replace(dataString,"}", ",\"actions\":[");
var i = 0;
foreach (var item in actionList.actions)
{
item.id = i;
dataString = dataString + JsonUtility.ToJson(item) + ",";
i++;
};
dataString = Regex.Replace(dataString, "(.+),$", "$1]}");
which is a valid (complete?) JSON string to work on.
But how to "paste" this as actions? Would it work?
What's the best approach to serialize/deserialize these nested actions?
No it doesn't:
NullReferenceException: Object reference not set to an instance of an object AC.ActionsManager.GetActionTypeIndex (AC.Action _action) (at Assets/AdventureCreator/Scripts/Managers/ActionsManager.cs:614) AC.ActionListAssetEditor.OnInspectorGUI () (at Assets/AdventureCreator/Scripts/ActionList/Editor/ActionListAssetEditor.cs:111) UnityEditor.InspectorWindow.DrawEditor (UnityEditor.Editor[] editors, Int32 editorIndex, Boolean rebuildOptimizedGUIBlock, System.Boolean& showImportedObjectBarNext, UnityEngine.Rect& importedObjectBarRect) (at C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:1295) UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
- 1:30AM, you're passionate!
I'm afraid the post time is local to the viewed, not the author.- Do you mean you get the actions details (not fileID or instanceID) in the JSON string?
I was mistaken - I was just getting the instanceID. I didn't pick up on this because if the ActionList being read is still present in the scene, then deserializing the Json data somehow re-links to its Actions. So, if you refresh Unity or delete the original ActionList, that data is then gone.- What's the best approach to serialize/deserialize these nested actions?
This is pretty complicated, because of the nature of Actions: subclassed ScriptableObjects living as child assets within a larget asset. No Action in an ActionList is actually an instance of the "Action" class - only a subclass, e.g. "ActionPause" (for Engine: Wait).What you essentially need to do is store each Action as an individual Json string, and also record its class type so that you can then create the correct class type before serialization. To also save e.g. the properties of the ActionListAsset itself, that too will need to be in a separate Json string.
In the specific case of ActionList asset files, you also need to use Unity's AssetDatabase methods to import each new Action as a separate asset, and merge it with the ActionListAsset itself.
Here's an example script. Unlike the last one, this is a component that goes on an empty GameObject in your scene. When you run the scene, however, you'll see two buttons in the top-left corner to copy/paste ActionListAsset data. Because it's in the Inspector, it will also display the recorded Json data neatly in the component.
http://pasteall.org/964800/csharp
- How?
A List type can be modified using the .Add, .Insert .InsertAt methods. This isn't a coding forum, but you can find plenty of info on them on e.g. https://msdn.microsoft.com/en-us/library/6sh2ey19(v=vs.110).aspxThe above script shows how an entire ActionList asset can be serialized/deserialized, but it should be possible to take the same principle and apply it to individual Actions, however. See if the script works first, though.
If I can help, let me know.
I understand more about coding mechanic (I still don't get why it has to be playing though), it's not my cup of coffee.
I would love something visual tool (flow diagrams, blocks, ...) to grasp the what-where-when-why of C# (if you know any, I'm all ears, I tried quick diagramming in VS but it's limited to class hierarchy).
I learn code better with blocky (you see all possibilities of a class or function at once). AFAIK, It doesn't exist for C#.
I tried Dialogue System demo but didn't find a tutorial about linking ink->DS->AC to work together (AC oriented).
I suss DS will come with limitations about ink because it's not the primary goal of DS (almost a competition), hence me trying to get JSON format and start from here (I guess I can adapt JSON export format from ink (JS) for my need, maybe I'm wrong).
I understand how to write the json strings and class names to a file but I'm scratching my head about parsing correctly all this back to a Unity ScriptableObject ("from Json" is re-using the formatted object). I'll try and may come back to ask help on this detail
It may interest others to extend and share this WIP and we could collectively get some nice external scripting tool for narrative. It's not my call to make/sell/support a Unity Asset or plugin though (future reader, please don't contact me for this).
In addition, if you feel this post is turning to competing another solution (future AC, DS, ...), feel free to delete it.
The author of Dialogue System, Tony, is very approachable - I'm sure he can advise you on how appropriate using DS/Ink/AC all together are.
Yes, it does work when JSON object is "exported" (to memory) then "re-imported" using existing actionJsonData frame.
Importing a JSON file from scratch is another story (parse className from within the file, create an empty frame from ... nowhere(?)), there are details I don't get yet.
It's close, but it's far
May be Dialogue is the way to go. I'll ask Tony.