We generally store JSON objects at Application.persistentData path when constructing our frameworks. No problem…until I was thinking about loading from the built application on a user that just installed it. I was thinking along the lines of grabbing all the JSON objects from that directory and placing them in the Resources or StreamingAssets folder and at first runtime install them in the users persistentData path directory. I am not sure if this strategy is fraught with perils or snags. Another strategy would be to use some installer routine but I am near clueless if that can be done. Anybody have a working and tested strategy they want to share?
((this is an opinion.
Doing that would allow the user to mess up their installation in an epic way. Basically, your idea is to have the application contain “unmodified” configuration and upon first run let the user make their local copy. However, if the user screws a few files very badly there, they’ll have a broken configuration which may persist through reinstall of the game.
If you played Neverwinter Night 1/2 games, they had an interesting strategy. Application data files were stored in application folder (and it was stored within archives), but user has “Override” folder within his documents directory, and whatever was placed within the override had higher priority than data in game folder. I think Bethesda games use something similar, where you can place a file and have it override contents of a *.bsa.
The last question to consider is - what are you trying to achieve here and why.
Regarding installer… I would say if you’re distributing off-steam (or if you’re distributing for free), the preferred form of a game would be a zip or 7zip archive without any installer. It should work once unpacked. The reason for that is that an installer may request admin privilegies and do something unpleasant to your system. As a result it is preferable to have a game that doesn’t need an installer.
How about placing the content of those jsons in ScriptableObjects? That would keep the data nicely within the build.
Or do you have a native plugin or something which reads the json files?
They’ll stop being json if he does that.
Json can be included into the project as TextAsset.
If this is truly just a compile (or build)-time thing, then I would write a postprocessor and convert all of those to serialized objects (preferably ScriptableObjects) and load them runtime normally like any other unity object.
Tooling is about this: provide the most comfortable developing/editing experience for people who are making the game and convert the data to the closest format to what the engine can read so it will be the most performant and handling the data will be the most natural inside the engine.
ps: for any considerable sized dataset, I would avoid any kind of Resources folder. Put them in asset bundles instead.
The JSON objects hold the runtime edited by user parameters to perform procedural non-keyframed IK animation that are triggered during Natural Language Processing. Scriptable Objects are where the data is stored during runtime and to to restore edits to them after the app quits and restarts loses any changes made to the SO’s. There is a library of float lists and names per asset types. They pull from those JSON objects when loading the libraries into the SO’s at startup. The user cannot save a JSON into the StreamingAssets or Resources folder during runtime so the obvious choice is Application.persistentDataPath which just happens to be tailor made for storing data at a path for an application across devices and platforms. So, regardless of AssetBundles or what have you I need the JSON data to end up at the persistentDataPath…ergo I thought of just loading them to that path on first runtime by user. It seems to be an either or situation that needs a workaround. Being lazy…heh…and KISS dictated that was the best/simplest method so far…searches yielded not much except endless parroting of the manual and API code.
It is for storing and editing configs for a built application for automobile dashboards and self driving cars using conversational AI and data will need to be persistent from power down to power up. We have all the tooling we need as devs. We build libraries of config assets for a few dozens subsystems and of course they work when built to our desktops as the application persistentDataPath remains the same. It needs to be portable so the asset libraries are loaded and configured at install in the automobile or ran on the companies workstation using their I/O simulator. These config library assets will store the user defined changes in the JSON objects during power on changes and load into the Scriptable Objects at vehicle startup next time. While the vehicle is powered on the changes made will stick op the SO’s. It is the power off then power up where SO’s revert to their default config…kind of a a factory reset in a manner of thinking.
See my replies to the thread for better understanding of the domain/s this application is in and the why’s behind my thinking and strategy. Always appreciate your input…thx
In the scenario you described, the approach is sensible, but you’ll obviously want some sanity check and a fallback in case files are corrupt or has been corrupted by the user. It is also worth keeping in mind that you’re not restricted to using persistentDataPath and can pull data from anywhere, depending on the OS used. The reason for that is that persistentDataPath can be in a very inconvenient location, depending on the platform, and honestly the implication is that this folder is supposed to go when the application is removed.
Last time I needed a user-visible config on a test android app, I went with a folder internal storage and a json file, like you suggested. The json file was generated if it is missing, and it also generated documentation for its parameters in a companion *.txt (where documentation strings were stored as attributes on config fields). The awkward thing about this approach is that Android at api level 30 tightened up security a lot, so in the end I decided to stick with API level 29 and legacy storage access.
Also keep in mind that json is not your only option. Depending on data type, yaml can be less annoying to alter by hand. Although can’t say I’m a fan of “meaningful whitespace”