Welcome back to the Little Squid Dev Blog!
Get it?
So what was it that we made progress on this week? ...B-Side(s) our comedic timing? (I could keep going here).
That third bullet point is what we'll be talking about in a little more detail today. We think this is a super important task and it's one that we've actually spent almost 2 weeks on at this point, which is a bit unheard of for our little team of two trying to make a game by the end of the year.
What exactly is being reworked?
...what?
It might help to very briefly explain how Unity works and show a picture or two.
The main functionality of Unity revolves around the use of what it calls "GameObjects". These make up almost everything that is in a game built with Unity. By themselves they are nothing, literally, but when you attach things like 3D models, animations, sounds, etc to them, they can be characters, items, scenery, or props. Each character or prop or whatever can be made up of a bunch of different, smaller GameObjects each with its own models, animations, effects.
You can also attach "scripts", or chunks of code, to these GameObjects and those scripts let you or the player do what is intended with that Object. You want the player character to jump when the player presses a button? Attach a script to the character GameObject that has the code for "when player presses button, character jumps".
There's a common practice, regardless of game engine, where developers make important scripts that help manage game states like what level the player is on, what the player's score is, what the player can/can't do at this moment. These are usually called "manager" objects/scripts.
All of these GameObjects end up going into "Scenes", which can most closely be related to what's traditionally called a level. How a developer handles Scenes is up to the type of game they are making - Scenes can hold a specific puzzle, they can be a particular section of a larger level, they could be an entire world if desired (but that would usually be unreasonable).
So for B-Side, up to this point we had all of the game's core functions operating from Manager GameObjects that were placed into individual Scenes, with each Scene being one level or puzzle. When a level ended, the next Scene would load and so would that Scene's instances of the Manager GameObjects.
This worked totally fine! It was actually kind of nice and efficient to not need to worry about any kind of game state transferring over from level to level. Every state just got "refreshed" at the beginning of each new level and anything that seemed to transfer over was really just set to that specific state within that particular Scene. It also allowed for really quick testing and iteration since I could load any level and know that it would be handling itself and not relying on anything outside of that level.
The problem arose when the game's design evolved. To tell a better story, the levels couldn't be so separated.
So began an arduous process of disconnecting the Game Managers from their specific levels, making them stop relying so much on each other and the other Objects in a Scene, and making it so they can exist on their own regardless of a level. The Scenes now have one specific object in them that passes some important info relating to that Scene into these Managers when the Scene is loaded, and gone are the days of fading in and out to black. So far it's working as intended!
What's it look like?
I know that was pretty dense stuff. Sorry, I got carried away. But if you stuck with it, here's some more visuals!
Anyone who has tested B-Side will have an idea of what the behavior used to be between levels, but here's a look at it. Pay attention to where the player character is when a level switches.
Now this is a little taste of what it looks like with the reworked code. If it's done right, you shouldn't actually be able to tell that anything is happening.
Why go through the trouble?
This comes down to a design decision more than anything else. It definitely wasn't an engineering or performance issue (at least at this point), and in fact may be creating performance issues that will need to be addressed.
But it came to a point in the game's design that we wanted each level, and the paths within it, to connect directly to the next level and its paths. That way it's always a continuous path that the player is moving through (you can see it in action in the gif above).
For us, the implications of one continuous path through every level is worth the trouble of rewriting a bunch of code and breaking other things along the way. In the end we think it'll make a much better player experience and it really supports the story we're telling within the game.
- 🦑