Let’s talk gameplay. What’s the difference between, say, ‘gameplay’ programming and other programming? If you are developing a game, you might need to make lots of things: shaders, engine, lighting, modeling, animation, in-app purchases, banhammers, web sites, the list goes on.
But these things do not a game make. Gameplay makes a game.
Gameplay is what you get when you combine all the things above and make a cohesive experience that people want to play. When prototyping this is the essential focus of your code. When I put on my gameplay hat and start a project, I ask myself:
- What kinds of things are in this game? Units? Modifiers? Scoring? Is it level-based? What are the win and lose conditions?
- Are these things sufficiently understood to start coding something?
- If I were to give this game to someone else, could they build content in the game?
Variety is the Spice of Life
Gameplay can also encompass AI, pathfinding, collisions, and much more. And doing things like applying AI to a game is definitely part of gameplay. But what I’m talking about here is that after coding a weapon or skill system, I make sure these systems allow for creation of weapons and skills, not a specific weapon or skill. If I spent all my dev time ‘all in’ on one concept, it is entirely possible my concept is not fun. But if the system was designed differently, I might find that I was just shy of the target, and a couple tweaks was all I needed, if I had tools & time to explore them.
StarterProject
I have created a small game project to more concretely illustrate these concepts (and others that I will be writing about soon™).
This game is a simple physics-based shooter. You shoot down the ‘Baddies’ in ‘Waves’. There is currently no win/lose condition or buffs, and only two baddies. But it does have a basic gameplay concept and that concept can be tweaked in order to see what works.
Exposing the Core Design
And this is key to gameplay. I want to translate the game’s design into tweakable parameters. With these basic building blocks:
- I can spawn elements at various spawn points in various directions. Are spawn points better farther away? Closer?
- I can create waves of units to attack at various intervals. How fast should the waves go? How does this interact with the speed of units?
- I can chain and re-use waves in different ways. What kind of progression and difficulty curve can I get with the tools at hand?
- I can change the timing and placement of these units. Does this make the game funner? More difficult? More eye candy?
- I can create more units of various sizes, hit points, colors, and speeds. How small is too small for a unit? What colors flavor enemies and the landscape best?
Most importantly, all of the above can be done without coding anything. I could potentially hand this project off to someone else with some basic instruction and see what they come up with.
Making Tools Makes Time
Game programming is very frequently tools programming. I once worked on a small commercial game that had no good tools. It took ages to make content. It was tedious, partially because of the need for so much manual data entry. Artists and designers would add stuff, and a developer would have to patch it together. Worst of all it was my fault because I didn’t have the forethought to focus enough on tools. I wonder how much time we wasted, and what ideas we could’ve made if only we made better tools.
I want freedom in the content creation process to explore the core game concept. I also want to do so quickly and efficiently so I can explore a lot of ideas. So how do I do that?
Designing Knobs
In the shooter, I’m using Unity and so I’m designing content using the Unity Editor. The editor provides hooks to display and edit data, and leveraging this functionality is the best thing you can do as a gameplay programmer. What do these knobs look like:
Additionally the level contains a number of spawn points that define the position and rotation of how things spawn:
(baddy placed inside empty spawn point for illustration purposes).
Spawn points contain an array of waves. This spawn point contains two waves:
And waves? They are Monobehaviours on Prefabs.
The code for waves is important because it provides an important intermediary step for creating units within our scene. Waves can be used on any spawn point. Waves are simply data, read by spawn points to build live units in the game.
public class BaddyWave : MonoBehaviour { public int repeatAmount = 1; public BaddyWaveItem[] items; }
The waves contain wave items, which includes additional data for how the units should be built:
[System.Serializable] public class BaddyWaveItem { public Baddy baddyPrefab; public Vector3 posDelta; public float speedModifier = 0.0f; public float spawnTime = 1.0f; }
By providing these simple knobs, we can easily spawn items faster, slower, nudge the position, and feel out the progression.
Architecture and Design
Data Reusability
The data of what to spawn and how to spawn it are separated. Baddies are their own prefabs. Waves are their own prefabs. And SpawnPoints are defined within a scene with references to Waves in the project, and as arrays of Waves. This allows for waves to be smaller patterns, and then assembled and re-used across all spawn points.
Sensible Defaults and Overrides
In general the Baddy class provides ‘sensible defaults’ for what you would expect, and then you can tweak things by providing overrides in the wave item. When doing this its useful to consider the values as ‘deltas’ or differences to the original values. For example ‘speedModifier’ is a number added to the initial speed of the baddy, instead of overwriting it.
baddy.speed += item.speedModifier;
Other options
You can use Json, or Google Sheets or stone tablets to store the content. I am using MonoBehaviours on prefabs.
I have a feeling some people may mention ScriptableObject. Personally I feel Monobehaviours provide more flexibility, and allow for multiple items on one object. At the end of the day its about finding a format that works for your team.
Room For Growth
The starter project is quite unfinished. Especially since you can’t win or lose anything, and there is only one level. But because of the focus on gameplay, I can do a lot to that one level. Check out the project, and see if you can make something better with the tools given!