Are ScriptableObjects good for non-visualised models?

Hi, I want to create a game using only GUI (panels, texts, buttons only), but there will be some models like heroes, monsters, items etc.
I have hard time to decide how to code them, thinking about SO or plain class objects. GameObjects with MB seems to be way too overwhelming.
I know that SO would make serialization way more easy with it references management, so I did some research about it and found their main use case is holding config-like data (like monster types, item types etc) - but not for instances of them (because thats the job for GO in regular unity3d games) - now I am a bit confused.
In my case would it make sense to instantiate new SO each time i want to create new hero, new monster, new item etc, or should I rather use plain object for them?

That’s completely up to you. Usually if an object (object as abstract concept) has any user interactions or visualization you would need a gameobject. However for pure business logic objects using ScriptableObjects is fine. Also if you use an MVC (model view controller) pattern you can represent your (abstract) model as ScriptableObject while the view and the controller can be gameobjects.

If the general question is: “Can ScriptableObjects be used to represent runtime data” then the answer is Yes.

If the question is if you should do it, that’s a question we can’t answer. It depends on many factors. What exact properties / values does your (abstract) runtime model contain? GameObjects have a position, rotation and scale for free. Do you need to store / save / serialize your data? If so for what purpose?

For large scale simulations it’s common to decouple the visual representation from the logical representation of an object. This adds some overhead since you have to manually link the visual representation to the logic model. However the advantage is that you can easily exchange the visual representation while keeping the logic representation the same. The simulation works soley on the logic model. For example for a large city simulation you may simulate pedestrians and cars. However depending on the zoom level you may represent certain objects just with a simple “dot” or with an actual 3d model.

The great thing about seperating the business logic from the visual representation is that the actual simulation can run standalone. This makes it easier to use multithreading. However the down side is that you have more overhead for communicating external events based on Unity events to your internal model and to actually visualize your model. If you use gameobjects you have everything in one object. That means you can directly react to Unity events and you can directly visualize the object. Though this coupling usually prevents you from using multithreading. It also might complicate serializing / saving the state of your model which is only a part of your object.

you could create something like a “Settings” ScriptableObject and instantiate an instance of it in your project files (e.g. a Resources folder). inside the SO class you can then hold a List etc. if the Enemy class then is a MonoBehaviour that is attached to a GameObject in a scene, serialization should still work.

on load you could then iterate through the List and compare the states, delete killed enemies / spawn new instances of enemies if needed and set their HP etc. accordingly.