Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How do you approach game design in Unity? WYSIWYG Principal?

Discussion in 'Scripting' started by timfrombriz, Mar 14, 2021.

  1. timfrombriz

    timfrombriz

    Joined:
    Jun 23, 2014
    Posts:
    30
    Im prototyping a game and I am stuck with what the right approach to the game design within Unity is.

    I come from a non Unity background, and Im trying to wrap my head around serialization and how to approach building the game within Unity.

    My original Main() thinking is to have a near empty scene that populates on "Play" of the scene, with some basic persistent gameobjects like a game manager and a blank core UI canvas. The game is not visible during Editor mode and only comes to life into scene view when you Press Play, where it either runs a new/load saved game state function which populates the scene from Prefabs.

    I view many tutorials online and this generally is the approach taken, where the world generally spawns into visual view upon Play execution, but I feel this is the wrong approach given the WYSIWYG design of Unity.

    Lets say for instance, you were designing a game like Parkitect, where you have a terrain mesh, a bunch of gameobjects in the world representing People, scenery and rides.



    Would you design your game so your game manager inspector within the editor has executable New, load and save buttons that execute in edit mode, so you can import and export the state of gameobjects in the editor and code your awake/start events to populate the non serialized data upon clicking Play to effectively resume execution of the state of the (new/loaded) game?

    If you do approach to develop in Unity with a paused game state in Editor mode, do you generally aim to serialize as much as the internal game state as possible?

    For example, consider if you had 300 people in the game world. You would want a centralized list<gameobjects> to be able to manage them. Do you serialize this list, in addition to the gameobjects in scene or do you design a Awake() event to populate the list based on gameobjects already existing in the scene.

    Id imagine where non-serialization occurs, there is a risk of data inconsistency and thus bugs. For example, loading a filestream from disk to populate a List<> vs executing code to build a list of matching gameobjects found in scene would yield different sort orders of the list generated. If the index of the list was important, this would introduce bugs and require additional layers of design. Where do you draw a line with serialization?

    What is the right approach to game design in Unity?
     
    Last edited: Mar 14, 2021
    dan-oak likes this.
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    Gosh there's so many ways to go about it, and they all have plusses and minuses. Regardless of the path you choose, you want to iterate, and not be afraid to massively change stuff early on, or even later on. Refactor when needed.

    Also, additive scene loading may give you a big bang for the buck organization-wise.

    Here's my blurbs about them:

    Additive scenes are one possible solution:

    https://forum.unity.com/threads/right-way-for-performance-divide-scene.1023673/#post-6630961
    https://forum.unity.com/threads/right-way-for-performance-divide-scene.1023673/#post-6754330

    https://forum.unity.com/threads/problem-with-canvas-ui-prefabs.1039075/#post-6726169

    A multi-scene loader thingy:

    https://pastebin.com/Vecczt5Q

    My typical Scene Loader:

    https://gist.github.com/kurtdekker/862da3bc22ee13aff61a7606ece6fdd3

    Other notes on additive scene loading:

    https://forum.unity.com/threads/removing-duplicates-on-load-scene.956568/#post-6233406

    Timing of scene loading:

    https://forum.unity.com/threads/fun...ject-in-the-second-scene.993141/#post-6449718
     
  3. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,887
    The more I've used Unity the more I go with an empty scene that spawns everything in, not including some game managers and UI, as you mentioned. I also use very few Awake/Starts due to potential execution order issues, instead going with custom Init()'s that get called at a controlled time.

    It can ruin prototyping because of things not having Init called, but on the flipside, a prefab doing something on Awake could break the game in some way. I just use
    [ContextMenu("Init")]
    so I can call functions by right-clicking on the component.

    In my colony management game they are picked up by certain managers on Init/Awake, so you can put prefabs in the scene.
     
    Kurt-Dekker likes this.
  4. timfrombriz

    timfrombriz

    Joined:
    Jun 23, 2014
    Posts:
    30
    So scenes are a seperated collection of gameobjects. In the editor, references can not exist between scenes and the scenes show seperate in the hierarchy but show in sceneries together. Until they are loaded additivity in play mode and become a single scene you can't reference objects. Is this correct?

    How would you implement a load saved game function, say you had a terrain scene, a peep scene and a scenery prop scene. Where's the entry point for execution?
     
  5. timfrombriz

    timfrombriz

    Joined:
    Jun 23, 2014
    Posts:
    30
    This is my thinking as well, but I think this design methodology is wrong. Its counter intuitive to the design of Unity being a WYSIWYG editor and taking advantage of that.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    It doesn't change much. At some point there are variables set up that say "I need this terrain scene, these enemies, and this is any other state of the game, go start 'er up."

    Whether that happens from the main menu or after you load that state out of some persistent storage doesn't really change it logically, although obviously it flows through different code paths.
     
  7. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    The WYSIWYG approach is good for things that are definitely going to exist from the very beginning.
    Suppose you were to start an RPG. What you really wanna do is to put the world together with everything that exists without state. You can also add stuff to the scenes that is affected by state, e.g. NPCs. You'll need to update those when the game has loaded and the save game is applied.

    Putting a scene together just by code or anything else can be very messy.


    Really depends on the number of objects, and how frequently it changes.
    I'd never recommend to maintain such a long list manually. Whenever you see a tutorial or anything alike where people start to populate long arrays/lists manually - forget about it. This is going to get you into trouble sooner or later.

    If you need to build the list at editor time, add extensions that automate it if you really need it. Put all the work you'd do manually to register it here and there behind an editor extension.

    Still, there can be problems:
    You might lose the one or the other reference under certain circumstances - now find that one... You might encounter a very annoying (but meanwhile rather rare editor behaviour) which makes you lose all editor references - waste of time, and extremely annoying.

    If you have tons of objects that need to be tracked, find a way to register them via code. They can still exist at design time, but the registration to some manager component would then be done at runtime - code won't disappear, it'll work reliably if done correctly and there are good patterns for it.

    That's something you should generally avoid at all costs. The sheer amount of objects in that list can already get you into trouble if you set it up manually. And if also you rely on indices on top of that, it's going to be extremely error prone. Who's going to remember the indices, what's going to happen if you insert something at index 100 and who's going to make sure the indices are kept "in sync" (object's position in the list, order/indices in code) ?

    Dedicated Identifiers would be more appropriate. One could say indices can be used as an ID as well, but insertion in an array-like/list-like collection type would change these kind of implicit IDs, which renders them useless for many purposes. Instead, if you had IDs that are defined explicity and are not inferred by storage type and location, you'll be able to do consistent and reliable lookups (e.g. using dictionaries).

    Perhaps I'm missing the point though, since there's so concrete example that explains as to why one would rely on indices in such a large list of objects.