Game & Developer Intro
Hello everyone! My name is Cristiano. I’m a developer relations engineer with a specialization in games & graphics performance and a pipe dream to make a game completely on my own. For the last 8 or so years I’ve completely immersed myself in all things gamedev, learning all the boring bullshit while trudging through the necessary evils required to put something somewhat decent together. I still have a long way to go, as I suspect new areas of exploration will present themselves to me as I make progress but I feel like I am in a comfortable place to put myself out there and start. For the duration of this project, I am going to try and Twitch stream as much of the development work as I can. Please follow my pages if you’re interested in watching, as I will be posting streaming times & progress to those outlets. Shown in the stream will be Unity game programming / design, stippling, animating, composing, etc.. I will try to be clear on which streams will involve what ahead of time so that only those interested in certain subjects can attend and not be bored out of their skull.
The game I’m working is centered around something I am extremely fascinated by and passionate about… health. Well, more specifically, gut health. It’s been known for quite some time that our guts contain trillions of tiny organisms that help facilitate vital functions of the human body, but only recently has light been shined on exactly what and how. Many sciences are beginning to call our gut the second brain, as recent findings show that the state of our gut can determine and contribute to certain ailments such as depression, acid reflux, weight issues, anxiety, constipation, and many more. Gut health depends on many factors, many of which are in our control. The game is fittingly titled GUT.
In GUT you will play a microorganism who must turn the tide in the war against bad bacteria. The player of the game takes control of 2 characters. The host (human), tentatively named Bob, who intermittently gets challenged to mini-games (think Warioware) where difficulty is determined by cravings generated by the state of his gut. The game will have a sort of feedback system between the internal gut gameplay mode and the external human world. The interior gut play style is a Metroidvania type game with elements of Pikmin / Lemings sprinkled in. Difficulty fluctuates in both play styles depending on your choices & skill completing levels and challenges in the form of sugar cravings, which feed bad bacteria and change the tide of war, spawning more enemies that need to be dealt with. If you win challenges as your host (causing him to demonstrate the willpower to choose healthy probiotics/prebiotics for dinner over sweets) you get the benefit of more minions to help you fight your way through the gut. Similarly, the more you destroy in the gut, the more the good bacteria cause a positive hormone balance in your host to help him make more responsible choices (easier minigames). Of course, wildcards will be thrown in to keep things interesting with bonuses to stop the game from getting too easy.
Art Style
I am aiming to hand-draw the whole thing in a style called stippling. Stippling is such a huge pain in the ass in that it can take hours to draw even the simplest things, but I think it looks cool, so it needs to be done. I will also be doing streams showing how to stipple and process in photoshop to make things animatable in Unity. Here is some concept art to show where I am going:
Enemy animated in first stream
Simple tiles, enemy, and helper bird-terium
Negative food choice = demonic burger
Code, Stream, and State Machine
First Twitch stream for Dev on GUT
I’ve uploaded the video of my first stream (above)to YouTube for those interested. I apologize for the garbage sound, as I’m still figuring out what I’m doing. In the future, I will program without music to avoid copyright stuff & drowning out my voice. To make up for it, I’ll explain what I did here for those interested. In the first video, I cover git basics, state machine basics, project organization and some animation. In the rest of this article, i’ll cover the state machine and a bit about my art pipeline, which isn’t as much of a pipeline as it is a jank but effective 2-step process.
STATE MACHINE
A state machine in games is basically a way to keep track of game flow and compartmentalize things. For instance, my SICK™ splash screen doesn’t need to listen for events trigger by collecting coins or killing enemies, it just needs to wait a few seconds so the player can check it out before proceeding to the next screen. Instead of making one massive main function where I do everything top to bottom, I can make the code modular and have relevant segments bound to their own warm and cozy homes. Ahhhh, just writing that makes me feel good :). Anyway, I like the idea of having tested state machines for my projects. I always use this kind of flow for game jams and other projects and I plan to do it here. For the main game state machine, I have a few states & I used an enum (GLOBAL_GAME_STATES) to easily pass them as parameters & ID them:
public enum GLOBAL_GAME_STATES
{
SPLASH_SCREEN = 1,
INTRO = 2,
MAIN_GAME = 3,
CUT_SCENE = 4,
END_OF_GAME = 5,
TOTAL
}
Each of these states will have their own sub-states, and even sub-states will have sub-states down the line. For instance, SPLASH_SCREEN could have 3 sub-states including FADE_IN, FULLY_SHOWN, and FADE_OUT that I can specify to occur over the course of different times to have more fine-grained control over how SIIIIIIIIIIICK my splash screen is. As for maintaining an idea of what each state does, I need some sort of a manager with an update loop, a variable to keep track of the current state, and logic within each state. In my first stream, the only logic I provided for each state was to load the corresponding scene. So, I put together the splash, an intro, and main game scenes to test my functionality. Here is my code for the manager:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GlobalGameStateManager : MonoBehaviour {
public GLOBAL_GAME_STATES CurrentState = GLOBAL_GAME_STATES.SPLASH_SCREEN;
private static GlobalGameStateManager globalGameStateManager;
public static GlobalGameStateManager instance
{
get
{
if(!globalGameStateManager)
{
globalGameStateManager = FindObjectOfType(typeof(GlobalGameStateManager)) as GlobalGameStateManager;
if(!globalGameStateManager)
{
Debug.LogError("There needs to be one active GlobalGameStateManager script on a gameobject in your scene");
}
else
{
globalGameStateManager.Initialize();
}
}
return globalGameStateManager;
}
}
void Awake()
{
Debug.Log("In Awake (" + gameObject.name + ")");
if(!globalGameStateManager)
{
globalGameStateManager = this;
globalGameStateManager.Initialize();
}
else
{
DestroyImmediate(this);
}
}
void Initialize()
{
DontDestroyOnLoad(globalGameStateManager);
StartCoroutine(Co_Update());
}
IEnumerator Co_Update()
{
Debug.Log("In in Co_Update (" + gameObject.name + ")");
while (true)
{
switch(CurrentState)
{
case GLOBAL_GAME_STATES.SPLASH_SCREEN:
SceneManager.LoadSceneAsync((int)GLOBAL_GAME_STATES.SPLASH_SCREEN);
while(CurrentState == GLOBAL_GAME_STATES.SPLASH_SCREEN)
{
Debug.Log("Current state is " + CurrentState);
yield return new WaitForSeconds(4.0f);
break;
}
SceneManager.UnloadSceneAsync((int)GLOBAL_GAME_STATES.SPLASH_SCREEN);
CurrentState = GLOBAL_GAME_STATES.INTRO;
break;
case GLOBAL_GAME_STATES.INTRO:
SceneManager.LoadSceneAsync((int)GLOBAL_GAME_STATES.INTRO);
while (CurrentState == GLOBAL_GAME_STATES.INTRO)
{
Debug.Log("Current state is " + CurrentState);
yield return new WaitForSeconds(3.0f);
break;
}
SceneManager.UnloadSceneAsync((int)GLOBAL_GAME_STATES.INTRO);
CurrentState = GLOBAL_GAME_STATES.MAIN_GAME;
break;
case GLOBAL_GAME_STATES.MAIN_GAME:
SceneManager.LoadSceneAsync((int)GLOBAL_GAME_STATES.MAIN_GAME);
while (CurrentState == GLOBAL_GAME_STATES.MAIN_GAME)
{
Debug.Log("Current state is " + CurrentState);
yield return new WaitForSeconds(3.0f);
break;
}
SceneManager.UnloadSceneAsync((int)GLOBAL_GAME_STATES.MAIN_GAME);
CurrentState = GLOBAL_GAME_STATES.SPLASH_SCREEN;
break;
case GLOBAL_GAME_STATES.CUT_SCENE:
while (CurrentState == GLOBAL_GAME_STATES.CUT_SCENE)
{
Debug.Log("Current state is " + CurrentState);
yield return null;
}
break;
case GLOBAL_GAME_STATES.END_OF_GAME:
while (CurrentState == GLOBAL_GAME_STATES.END_OF_GAME)
{
Debug.Log("Current state is " + CurrentState);
yield return null;
}
break;
}
yield return null;
}
}
}
I use a singleton design pattern (sue me, nerds) to make sure only one of these objects exists instantiated at a time and then kick off my loop in the Init function. I keep this script alone on an empty game object in my “master scene” which is never unloaded on start. For each later scene I create, I can always assume this global game state manager exists & call into it to transition to another state. This manager will be responsible for loading and unloading scenes / resources to keep everything consolidated. As an example, if the main game ever completes, I can have the main game state manager (not created yet), call a function in the GameStateManager instance similar to public void TransitionGameState(GLOBAL_GAME_STATES stateToChangeTo) that will unload main game and do whatever it needs to do to safely transition to the next game state. For my main game loop and most other things, I love to use coroutines as I find them to be very intuitive for state management and makes sequences involving timing extremely easy to create. For more info on coroutines, check out the Unity docs as any explanation I would give on them would pale in comparison. You don’t need to use coroutines if you don’t want to, as a normal update loop would work just fine, but for this sort of thing, I love them. This is my basic global game state system – feel free to hit me up with questions at any time.
Art & Animation
In the stream, I also did a bit of work in the art area. Specifically, I imported one of my hand-drawn enemies, used a threshold tool to make it a uniform shade of black / clean it up, put each movable limb on a separate layer, and filled in potentially occluded areas where animation would cause a disconnect. I then exported each limb and loaded them into Unity to animate (which is where I got the .gif above!).
Let me know what you think! And if you’d like to support the project, please follow any of my pages I reference at the beginning of the article… Hell, here they are again:
Website
FaceBook
Instagram
Twitter
SoundCloud
<3 Thanks for checking out my DevLog! More to come. <3
0 comments