UnitedFailures

LD 42

What I've Learned From My First GameJam

I've decided that the best way for me to improve my game development skills is to document my takeaways from this whole experience.

For my game, Arctic Escape (https://ldjam.com/events/ludum-dare/42/arctic-escape), I came up with the idea while staring at the tiles on my ceiling and quickly scribbled down some concept art on a pad of paper.

Getting Started:

I tried to recruit some of my friends to make my art for me to no avail- so I started working on my game alone; meaning that I would end up with the overwhelming responsibility of being the game designer, the programmer, the artist, and also the "sound designer." I put sound designer in quotes because I actually was so overwhelmed with all the other aspects of the game I forgot to include any sound elements...

Schedule:

I spent Friday night coming up with the concept and mechanics for the game, Saturday into Sunday just programming the game, Monday I called out of work and created all the art for Arctic Escape in the morning and Monday evening was spent designing levels.

Things I Would Change:

Level Design - My biggest regret was doing all my level design in the final few hours of the jam. I was under a lot of pressure causing me to simply shit out some levels that I'm really not proud of. There are probably 2-3 levels that I'm actually proud of out of the 8 levels in my game.

Programming - I started off programming to make my game easily expandable/customizable in the future. Such features as varying sized levels besides my 16x16 standard level that made it into the final release. I also started working on the functionality for a level creator. As time dragged on, I realized I was wasting too much time on such expandability (like the level creator) and I was forced to scrap the project and start programming only for a single vision. Although this limited how customizable my game could be it finally allowed to buckle down and create my core game mechanics. I feel like in the future I shouldn't bog myself down with worrying about making my game infinitely expandable and customizable.

Animation - The animation is choppy and the transitions don't work correctly. If I were given more time I'm not even sure if I understand animations enough to have fixed it. I hope for my next jam I'm better at using Unity's animator.

Artwork - I dislike my style of pixelart. I hope I either adopt a new style or I try to exercise my Blender skills.

Game Ports - I really need to make my game in WebGL next time because people really don't like to download games on here.

I hope this was helpful to my future self or to some random person. If you're that random person and you want to see the game I talked about in this post, then here: https://ldjam.com/events/ludum-dare/42/arctic-escape

ArcticEscapeGameplay.png

Ludum Dare 45

Test

Test

Ludum Dare 51

The Most Important Thing I Learned This Game Jam

Event Handlers are VERY useful!

Background Flavor...

I've been programming my own games for the past ~5 years. I have six games published on my itch.io page, and countless projects I've sunk hours of development into that never saw the light of day. None of these projects I had worked on make use of custom event handlers - nor was I aware at the time what event handlers even are. Yet, looking back, I can find tons of places where they would have make my code cleaner and my life easier.

How I Used To Do Things...

Here's a rough example of how I would have managed character functionality in the past.

``` public class Character { bool movingForward; CharacterAudio audio; CharacterMovement movement;

void ManageCharacter()
{
    if(movingForward)
    {
        audio.Play(...);
        movement.MoveForward(...);
    }
}

// ...

} ```

Why Do I Not Like This?

In software development, one of the best practices you can ever learn is to keep your systems decoupled. IE: We want our systems to not be unnecesarily dependent on eachother to perform their functionality.

In the example above, I outline an example Character class to handles working with CharacterAudio and CharacterMovement components. Now I'm gonna ask rhetorical questions... - What happens if I make a NPC using the Character class - but I don't want them to make noise when they walk? Can I remove the CharacterAudio component? - In the example above, we will error out if we remove the component. Our Character class is TIGHTLY COUPLED to its respective Character... components. - What if we add logic for checking if a component is null before using it? - We can go that route, but now we have to do that for EVERY component referenced in Character.

Why is our Character even referencing its components to begin with? Every time we create and add a new Character... component - we would need to add a new reference within the Character class and plug in the respective component function calls within ManageCharacter(). Inevitably, this class becomes bloated with a thousand references and the code becomes harder to work with and read...

Now this is where Event Handlers come in.

What are Event Handlers and Why Should I Use Them

Below is an example of how I would use event handlers to improve our code (I used Unity Actions here, but you can use your preferred method of event handlers).

Essentially, the code below shows each Character... component gets a reference to the respective main Character component - and subscribes its functionality to the respective OnMoveForwardAction event.

``` using UnityEngine.Events;

public class Character { public UnityAction OnMoveForwardAction;

public void MoveForward()
{
    OnMoveForwardAction.Invoke();
}

}

[RequireComponent(typeof(Character))] // Ensures CharacterAudio's GameObject has a Character component public class CharacterAudio { public void OnEnable() { Character c = GetComponent(); c.OnMoveForwardAction += PlayWalkingAudio; }

public void OnDisable()
{
    Character c = GetComponent<Character>();
    c.OnMoveForwardAction -= PlayWalkingAudio;
}

public void PlayWalkingAudio()
{
    ...
}

}

[RequireComponent(typeof(Character))] // Ensures CharacterMovement's GameObject has a Character component public class CharacterMovement { public void OnEnable() { Character c = GetComponent(); c.OnMoveForwardAction += MoveForward; }

public void OnDisable()
{
    Character c = GetComponent<Character>();
    c.OnMoveForwardAction -= MoveForward;
}

public void MoveForward()
{
    ...
}

} ```

The Character class is unaware of who is subscribed, and simply alerts all subscribers for when the MoveForward event occurs. This successfully decouples the Character class from all subcomponents and cleanly resolves the issues discussed above. It is fine for the subcomponents to be coupled to the Character class - as this assumption has to be made for defining subcomponent functionality.

The best part of this paradigm is shown when we want to create a new subcomponent. For example, if we want a CharacterHealthOnMove component (like some special in-game buff), then we can accomplish this with the following steps 1. Create the CharacterHealthOnMove class. 2. Define the functionality for gaining health within the class in a function. 3. Subscribe the above function to the OnMoveForwardAction event.

Conclusion

Check out event handlers if you haven't used them before. It'll make it easier to organize, write, and extend your code going forward. I heavily utilized events when coding my submission BIG BLOCK MODE for this jam.

Near the end of the jam, I had events for stuff like blocks falling, game loss, row cleared, etc - and it took literal seconds for me to subscribe audio functionality to these respective events and have it all working within the game. EZ PZ.

Note

This is my first time writing an informative blog post like this. Sorry if it sucked. I'm open to any feedback: positive or negative. Also feel free to check out our submission if you're interested.

THANKS!