Global Game Jam 2023! - Part 4

Global Game Jam 2023! - Part 4

Final day and a bit of project feedback

Context

In the last article in this series, I went over how I created the necessary logic for our designer to place enemy wave spawn points in the level. And in the same image below, you can see the bunny attack VFX that I added to the main character whenever the player attacks the enemy beetles:

On the other hand, near the end of the post, I started working on this idea of communicating to the player that a beetle has caused damage to the bunny house.

The plan is to use the leaves on the carrot to hopefully fall off. You'll see how that went down. Also, this is the last post for GGJ 2023, and I hope you've enjoyed reading about this development story πŸ˜„.

Day 6 - Feb. 4th - Continued

Bunny House UI

So now that I added RigidBody components to all of the 5 leaves, I then created a CarrotDamageController script that will activate the Rigidbody component of a random leaf:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CarrotDamageController : MonoBehaviour
{
    [SerializeField]
    private List<Rigidbody> m_leafRigidBodies = new List<Rigidbody>();

    [SerializeField]
    [Range(1f, 100f)]
    private float m_forceIntensity = 30f;

    private void OnCollisionEnter(Collision collision)
    {
        if(m_leafRigidBodies.Count > 0 &&
            collision.gameObject.CompareTag("Beetle Enemy"))
        {
            int randomIndex = Random.Range(0, m_leafRigidBodies.Count - 1);
            var rigidBody = m_leafRigidBodies[randomIndex];
            m_leafRigidBodies.RemoveAt(randomIndex);

            rigidBody.useGravity = true;
            rigidBody.AddForce(GetRandomForceVector(m_forceIntensity));
        }
    }

    private Vector3 GetRandomForceVector(float intensity)
    {
        var forceVector = new Vector3(
            Random.Range(0f, 1f),
            Random.Range(0f, 1f),
            Random.Range(0f, 1f));

        forceVector.Normalize();

        return forceVector * intensity;
    }
}

As you can see, it's a very simple script. All it does is activate a random leaf's RigidBody component, and then apply some force in a random direction. And check it out:

Cooler Enemy Beetles!

While I was working on code, and our designer was making cool UI, our 3D artist made some awesome new textures for the enemy beetles:

I had to re-create the prefabs since he also made new 3D models for each of them, but it didn't take too long. Here they are in-game:

Last Enemy Behavior Change

So our game needed some variety in enemy behaviors because all of the beetles do the same thing. We quickly discussed the idea of one of the beetles moving at a quicker pace, but zig-zagging in between a few spots before heading toward the bunny house. It was just something easy to implement and quickly add to the game.

Note: You'll notice that by the end of a week-long game jam, the quality of a code script will usually decline quite fast jajaja πŸ˜‚.

In general, the purpose of game jams is to make a prototype of a game.

Given the description of our fast and quick new enemy behavior, I quickly created this code script called ZigZagTowardsTarget :

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UIElements;

public class ZigZagTowardsTarget : MonoBehaviour
{
    [SerializeField]
    private Transform m_target;

    private Stack<Vector3> m_positionsToChase = new();

    [SerializeField]
    [Min(0f)]
    private float m_speed = 2f;

    private Vector3 m_direction = new();
    private Vector3 m_position;

    private float m_speedTimesDeltaTime;

    bool m_isRotationNonZero;

    public void SetNewTarget(GameObject newTarget)
    {
        m_target = newTarget.transform;
    }

    private void Start()
    {
        m_position = GetSpecialRandomTargetPos();

        // Inserting the final target first, since a stack is a FI-LO
        // container (First in, Last out)
        m_positionsToChase.Push(m_target.position);

        m_positionsToChase.Push(GetSpecialRandomTargetPos());
        m_positionsToChase.Push(GetSpecialRandomTargetPos());
    }

    void Update()
    {
        if(m_target == null)
            return;

        if((m_position - transform.position).magnitude < 0.5f)
        {
            UpdateTargetPosition();
        }

        m_direction = m_position - transform.position;
        m_direction.Normalize();

        m_speedTimesDeltaTime = m_speed * Time.deltaTime;

        transform.position += m_direction * m_speedTimesDeltaTime;

        m_isRotationNonZero = !Mathf.Approximately(
            (m_position - transform.position).sqrMagnitude,
            0f);

        if(m_isRotationNonZero)
            transform.forward = m_direction;
    }

    private Vector3 GetSpecialRandomTargetPos()
    {
        return new Vector3(
            Random.Range(-7f, 7f),
            .5f,
            Random.Range(1f, 5f));
    }

    private void UpdateTargetPosition()
    {
        if (m_positionsToChase.Count <= 0)
            return;

        m_position = m_positionsToChase.Pop();
    }
}

And since we now have 2 possible enemy behavior scripts, we need to add this small change to BeetleWaveManager, so that it can react accordingly when it spawns a new enemy with the ZigZagTowardsTarget behavior attached to it:

using System.Collections.Generic;
using UnityEngine;

public class BeetleWaveManager : MonoBehaviour
{
    ...

    private void SpawnBeetleEnemyFromWave(
        int enemyIndex,
        List<TimeBeetleEnemyPair> m_timeBeetleEnemyPairs)
    {
        GameObject newBeetleEnemy = 
            Instantiate(
                m_timeBeetleEnemyPairs[enemyIndex].m_enemyBeetleToSpawn,
                gameObject.transform.position,
                Quaternion.identity);

        if(newBeetleEnemy.TryGetComponent(
            out MoveStraightTowardsTarget moveStraightTowardsTarget))
        {
            moveStraightTowardsTarget.SetNewTarget(m_carrotHouse);
        }
        else if(newBeetleEnemy.TryGetComponent(
            out ZigZagTowardsTarget zigZagTowardsTarget))
        {
            zigZagTowardsTarget.SetNewTarget(m_carrotHouse);
        }
    }

    ...
}

And with those simple changes, we have some variety in our enemies! Look at how different the red beetles are from the green ones:

LOL! Don't ask me why I decided to leave the mouse on-screen when recording this small clipπŸ˜‚... whoops!

Not gonna lie, I did a lot for the game on this day so by the end, I was super tired. This meant that this was my last effort to improve the game. The rest is just preparation for project submission.

Day 7 - Feb. 5th

πŸŽ‰The final day is here! πŸŽ‰

If anyone tells you that they've never had some stress in the final moments of a game jam, they're either lying or maybe just abandoned their team! πŸ˜‚

As I've mentioned in the previous posts, the game jam organizers were very helpful and also gave a stream on how to prepare a game's submission. We were able to quickly build our game, and add the necessary files.

Here's our game submission page!

πŸŽ‰And that's it! Another game jam is done! πŸŽ‰

As part of the tradition, there was a showcase of all of the participating games! ATM of writing this post, the Puerto Rico chapter removed their stream from their Twitch channel, but for you to get an idea of other games made during this week, here's Unity's own twitch stream where they played a good amount projects made with the Unity engine:

Lessons learned - Team edition!

Instead of just talking about lessons I learned during this awesome week, I decided to also extend 3 questions to each of the teammates, and here are some answers I got:

Sergio - Composer

Did you like participating in the game jam?

This is my 4th game jam since I started composing for video games in 2020. It's always thrilling those first days of getting to know your teammates, seeing how they work and learning from them. My favorite part of those first jam hours is seeing what we come up with and researching so that I can find and get into the right mood for the game.

What did you learn while working on the project?

This jam was a bit challenging for me because I'm more of a story-driven fantasy type of composer, and I wanted to break that shell a bit and do something more band-based, with fewer instruments, and more ambiance. More as if it were a live band playing.

I was also very happy because I finally got to use FMOD in an actual game jam. On past jams, I've had issues synching it to the engine. But this was the first time I've been in a Jam got it to work. Unity already has a plugin in their asset store for implementation, so it was pretty easy to set up.

I learned a few things on how to add sound and music in Unity, and I got to use the spacializer so that the SFX sounded from where the player was in the game.

What would you do differently in your next game jam project?

One thing I would do differently is try to learn a bit more about how programming or visual scripting works. Because I tend to want to help more on the development side of things, but because of my lack of knowledge in those areas, I can be of little help on the side that the team could need.

Dennis - 3D Artist

Did you like participating in the game jam?

I liked the approach and different views of all my team members and how our different ideas led us to a unique yet approachable game that we could design and create.

What did you learn while working on the project?

I learned more about how to structure a pipeline for the art department that adheres more to Unity's unique way of creating and implementing assets.

What would you do differently in your next game jam project?

For my next game jam, I would try to go back to Unreal Engine if I'm going to focus on art again since Unreal, in my opinion, is way faster and more structured in the art implementation aspect.

If I were to use Unity again, I would focus on a new art pipeline of fully completing an asset before implementing it in the game; focusing on the assets that will be programmed first and getting those out of the way so that there's no going back and forth between prefabs and other things like that which complicated the project in this particular game jam and left assets without being used.

Some of the art assets Dennis mentioned that couldn't make it into the game:

Esteban - Programmer

Did you like participating in the game jam?

I enjoyed this game jam, and it was awesome to meet Dennis, Sergio and Neftali! I was quite impressed with our level of art, sound, and great attitude from Neftali who was a living example that you can contribute to a project if you just try, and dare to step out of your comfort zone.

What did you learn while working on the project?

I learned that it's much tougher than previously thought to work with custom 3D assets made by artists, it seems that Unity is somewhat limited when you want to switch a prefab's 3D mesh.

What would you do differently in your next game jam project?

I feel that on this game jam, we put too much effort into visual quality, too quickly. I believe we should've solidified our gameplay even more, and spent more time in the earlier sketching stages until we were all 100% in agreement.

Unfortunately, since I was the only programmer, I didn't have time to focus on as many new things as I'd liked. I practiced skills, more than learned new ones.

Please let me know what you think!

  • What did you think about the journey of our project?

  • What do you think of the team's lessons?

  • Did you play any other GGJ games?

πŸŽ‰πŸŽ‰πŸŽ‰ Happy building! πŸŽ‰πŸŽ‰πŸŽ‰

Β