DVNC is participating in a 90 Day Indie Game Challenge. The goal is to make a game and try to release it within 90 days of starting the project. The game I’m (Vince, programmer for DVNC) is working on is titled Magigunner (for now). Below you can read about each day so far. My plan is to write updates every 3–6 days until the challenge is complete!
90 Day Challenge Started: Tuesday, March 19, 2019
To start Magigunner was designed to be a VR Shoot ’Em Up where the player casts spells through their guns. My goal was to give the player the ability to hold 4–6 guns, one of which had to contain a movement spell (such as teleport, dash, portal, etc). After setting up their build the player would enter an instanced-zone where they would run through killing any enemies in sight. The objective is to kill a certain number of specific enemies and on each “mission” there would be at least one bonus objective which involved killing a slightly harder enemy. After completing the mission the player would get customizable parts for their guns which they could use to create more variations of spells (Chain Bullet + Lightning Magazine = Chain Lightning).
On the first day of the challenge, I definitely thought the game was going to be more similar to Gorn a VR Beat ’Em Up. To start I began setting up an arena-style environment with assets that I got from the Unity Asset store (I’m not an artist other than knowing a bit about shaders and materials). Once I had set up the environment using assets from Synty Studios I began setting up my player infrastructure.
Note my any code theory could be horrible, but with this challenge, I’m focused more on getting the game running and out than on completely perfect code. With that in mind here’s an overview of how I set up my player. Also, note I’m making this game in Unity 2018.
Code Overview (Day 1)
I imported the SteamVR plugin and then watched a quick tutorial on how to get player input from the new SteamVR 2.0 plugin. After setting up a PlayerInput class and attaching it to the CameraRig game object. I added pistol models as children to the player’s controller parent objects. This made it so that when the game ran the pistols spawned on top of the player’s controllers. Next, I added basic shooting functionality to the PlayerInput Class inside of the trigger functions. After adding a bullet prefab to the PlayerInput Class and a spawn point in front of the gun I was able to shoot at the wolf in the scene. From here I created a special bullet prefab which teleported the player to its location after X seconds. This “Teleportation Shot” allows the player to move around the scene.
Going into the second day of the challenge I decided I wanted to create more of an environment than an arena. From dragging assets around and scaling them I learned that the pack I got wasn’t the best to make an arena (or at least I was wasting too much time figuring out how). I decided to change the environment from a coliseum-like arena to a mushroom forest. I had found pretty cool mushroom assets inside the pack. For some reason, I really wanted to use them. I started creating another level which focused more on a mushroom forest aesthetic. I had to make the mushrooms huge so that the player could move around and dodge enemies. Then for more “effect”, I decided to create a small lake in the center of the new area.
Code Overview (Day 2)
Before setting up the new mushroom forest styled area I had already created the Wolf enemy. I did this by importing Behaviour Designer (along with their Movement and Tactical packs), a Unity asset that can be used to create behavior trees. I’m definitely still at the beginning of my game AI programming journey, but behavior trees are a slightly more “advanced” game AI programming pattern. Finite state machines are a way to control the “state” of an object to limit what action the object is able to take (such as an idle state enemy switching to a pursue state after seeing the player).
My basic explanation of behaviors trees is that unlike finite state machines, in general without getting fancy, behavior trees allow for more “thought-like” behavior from AI. In a state machine, you are directly controlling the AI’s behavior based on its state (which requires a decent amount of hard code and thinking through a programmatic structure of organization for extension). Behavior trees create a more hierarchical structure that doesn’t limit the AI’s behavior based on the idea of “states”. Finite state machines could be used for menus and Final Fantasy 1, turn-based, style fights whereas behavior trees are more for Dark Souls and Warframe style AI. If you know more about behavior trees or finite state machines please comment!
After creating a basic behavior tree for the Wolf that allowed him to walk up to, chase, and attack the player I added a health manager to the player so they could take damage and die. This made me want to give the player the ability to defend themself. So I added a health manager to the Wolf and made it so that the player’s bullets could damage it. With the Wolf and player able to hurt and kill each other I switched back to focusing on the environment.
After doing some research on Day 2 I found out that there is already a VR game out (Blasters of the Universe) that has more than a few of the core design pillars I was thinking of. I decided to switch my idea, but this also had a small impact on the scope. Blasters of the Universe focuses on customizable guns and gameplay that has the player move in the real world. Instead, Magigunner will focus on movement abilities that move the player’s camera/character and mid-dungeon pseudo-customization (similar to Enter the Gungeon, Dead Cells, and Wizard of Legend).
After beating a “floor”, by surviving until they find stairs, they will unlock another gun mod which they may see on their future runs. Prior to entering the dungeon, the player may choose one movement-focused bullet and one attack focused bullet. During gameplay, the player must maintain at least one type of each bullet.
Coding Overview (Day 3)
Since the game had now switched to more of a rogue-like game I knew that would I have to create a dungeon for the player to run through. A basic implementation of procedural generation could solve the problem of player options, variety, and zone management and creation. To implement this I watched the Random Dungeon Generation — Easy Unity Tutorial by Blackthornprod on Youtube. This allowed me to create a basic system that would generate the first floor of the dungeon when the scene was started. However, this also caused an issue with my Wolf AI.
Unity’s native NavMesh feature allows AI to walk and find paths. The NavMesh requires NavMesh Data which is baked in Unity before the game is run. By creating the procedural sections after the game had started running the NavMesh Data wasn’t baked on the new sections and the Wolf’s AI didn’t allow it to follow the player into sections of the dungeon that wasn’t the entry section. After googling around I found out Unity had been developing and updating a NavMeshComponents package on Github which extends the functionality of the NavMesh. It took a while to figure out how to connect the dungeon’s other sections to the entry section, but after adding a NavMeshSurface and NavMeshPrefabInstance to the top level game object of the prefabs and settings up NavMeshLinks where needed I was able to get the wolf chasing the player into the procedurally generated parts of the dungeon.
Looking ahead I will definitely be studying what makes rogue-likes fun. I’ve been doing a decent amount of research into ideas core to FPS design (enemy attribute and functionality differentiation, defining strategic possibility, etc), and can’t wait to learn more about rogue-likes. On the development front, I’m going to stop with environment design for now and try to get lost in defining the core loop for the player. The game’s core design loop is key to a fun player experience. I have a rough framework of a loop that seems fun, but I won’t know till it’s implemented