Implementing Swappable Key-Function Mapping in Unity

“MARS: Mayhem-Assured Rover Simulator” is a game I made in 48 hours for the GMTK Jam 2020. With this year’s theme being “Out of Control”, I decided to make a game that either makes players physically run out of fingers to control, or make controls a “limited resource” so that they eventually run out.

It didn’t take long for me to associate these features with a robot, and it was almost immediately apparent to me that I’m going to make a game about a “unfortunately poorly-designed” robot. Basically, the interaction are as follows:

  1. There should be enough functions for almost each finger.
    For example: movement / weapon controls / robotic arm / radar
  2. Each function should be intentionally separated from each other to make players busy.
    For example, movement can be separated into “gas”, “reverse”, “turn left” and “turn right”; weapon controls can be separated into “rotate cannon left”, “rotate cannon right”, and “fire”.
  3. All functions should be “hold” instead of “switch”.
    The robot arm only picks up/drops down items, but players have to hold down the key for the arm to keep the item in hand.
  4. Each key must expire after a number of uses.
    So that controls become a limited resource.
  5. Because of 4, keys to each function should be swappable.

So let’s get to some designing.

My terrible handwriting on an iPad

Figuring out the interactions

What we’re talking about here is a system in which “robustness” is a necessity. The game must react to different keys when they’re pressed; each key must function differently when assigned different features. Basically, the interaction map looks a bit like this:

No description available.

Many of the decisions that’ll be made in game are known only in run-time, which means excessive hard-wiring is not a good answer. So, we need to address this design task with flexible components.

Listening to 45 keys

In MARS, players can input using 26 + 19 keys (symbols mostly) on the keyboard. The rover itself has around 7-8 functions. Naturally, each key is a prefab, and each prefab should know what key it stands for. I could tackle this problem by including this script on every key prefab:

if Input.GetKey(KeyCode.A) {/*...*/}
else if Input.GetKey(KeyCode.B) {/*...*/}
else if Input.GetKye(KeyCode.C) {/*...*/}
...

But not only is this approach inefficient (and inelegant), statements in each brackets must perform another check on which function it is assigned to, and then call their corresponding methods. I sense a high probability of not abiding with reusable code, and I need to find another way.

Fortunately, Input.GetKeyDown() takes in not only KeyCode as arguments, but also strings. Using this, I can designate the key each prefab is representing with a public property, and use that with the Input.GetKeyDown() condition check.

Beware: using public in the beginning is a bad habit. Games written for game jams normally wouldn't encounter serious security concerns, but if you're writing for working projects, establishing a property with the public keyword is a bad idea.
[SerializeField] private string key;

private void Update()
{
    if(Input.GetKey(key)) {/*Do something!*/}
}

When each key is placed into a slot, it needs to know which exact method in the Controls Hub to call. A Listener pattern will probably suffice to implement this feature; additionally, Unity has their own Listener Event system out of the box, so I decided to take advantage of that.

I enjoy the moment when the “bridge is connected”; that is why I decided to set aside this task first, and work on completing the Controls Hub and the individual components first. The structure looks a bit like below:

public class ControlsHub
{
    public static ControlsHub Instance;
    [SerializeField] private MovementController movementControls;
    [SerializeField] private WeaponsController weaponsControls;
    /** Basically components of the rover **/

    private void Awake() { // implement singleton code here // }

    public void Gas()
    {
        movementControls.Gas();
    }
    
    public void TurnLeft()
    {
        movementControls.Turn(-1);
    }
    /** Each component's individual methods **/
}

public enum RobotFunctions
{
    FORWARD, BACKWARD, RIGHT, LEFT, BAY, PICK, CANNONRIGHT, CANNONLEFT, FIRE, BOOST
}
public class MovementController
{
    /** This is where you set up individual parameters 
        for your component.
    **/
    [SerializeField] private Rigidbody rb;
    [SerializeField] private MaxSpeed;
    [SerializeField] private MaxAcceleration;

    private acceleration;
    private speed;

    private void FixedUpdate()
    {
        speed = speed + acceleration;
        rb.MovePosition(rb.position + YOUR_FORWARD_VECTOR * speed * Time.fixedDeltaTime);
    }

    public void Gas
    {
        acceleration = MaxAcceleration;
    }
    // so on so forth 
}

You may have noticed that the implementation of these methods don’t really work with how Input.GetKey() works — GetKey() is fired every frame the key is being pressed, but if that’s the case then the MovementController.Gas() method would be repeatedly called, resulting in a robot moving in impossible speeds.

This is because we need to consider other functions of the robot and how they operate as well. An immediate example would be the robotic arm that picks up items when the key is pressed down. It is not a continuous action like speeding up a car, but rather one with 2 states (pick/loose). While Input.GetKey() detects if a key is pressed down, but it doesn’t detect when a key is let go.

This is why we need to refactor our methods to work with the Input.GetKeyDown() / Input.GetKeyUp() pair, which leads to the eventual implementation of our key controller:

public class KeyController
{
    public string Key;
    private UnityEvent enterEvent;
    private UnityEvent exitEvent;

    private void Update()
    {
        if(Input.GetKeyDown(Key))
        {
            enterEvent.Invoke();
        }
        else if(Input.GetKeyUp(Key))
        {
            exitEvent.Invoke();
        }
    }
    
    // Invoked when key is placed in slot
    public SubscribeToComponent(RobotFunction component)
    {
        switch (component)
        {
            case RobotFunction.FORWARD:
                enterEvent.AddListener(ControlsHub.Instance.Gas);
                exitEvent.AddListener(ControlsHub.Instance.StopGasBrake);
                break;
            //...
        }
    }
}

Conclusion

So, how did we solve our problems?

  1. There should be enough functions for almost each finger.
  2. Each function should be intentionally separated from each other to make players busy.
    These design questions are achievable through our robust implementation.
  3. All functions should be “hold” instead of “switch”.
    We used Input.GetKeyDown() and Input.GetKeyUp() to achieve similar effects of Input.GetKey(). This implementation allows state-and-stateless functions to operate through the same interface.
  4. Each key must expire after a number of uses.
  5. Because of 4, keys to each function should be swappable.
    To achieve expirable keys, we just need to add in a few statements in KeyController that ignores input if the key has expired; for swappable keys, we avoided hard-wiring keys to each function through using the overload of Input.GetKeyDown().

Notes

You can play the game here!

Note: the implementation here is most likely not the optimal way; after all, it is a jam game!

This game jam has deeply educated me of my physical age — I’m 25. When I was 20, I could stay up all night and hack through the entire game without rest. Now I feel dizzy already at 1AM.

Moreover, I started this game alone, but it could never be completed without the help of Joey Yeo and her awesome pixel art. Thank you!

ETC 2020 Museum — Diving Deep Into A VR Graduation Event

Over the past few days I have been working on the ETC 2020 Museum, a Virtual World for my grad school’s (unofficial) virtual commencement. The world was built on the VRChat platform, and had a maximum attendance of around 32 people. Before we dive into the details, here’s a little digest video I made:

Looks pretty simple, but a lot of work has been done in the background to ensure a satisfying experience and technically optimal execution. Here’s a little write-up to detail these features.

Continue reading ETC 2020 Museum — Diving Deep Into A VR Graduation Event

Taking Bell Investments To the Next Level: Brainstorming Financial Products in Animal Crossing

First, there was a stalk market — a simple system that allows Animal Crossing players to benefit from buying and selling turnips. To put simply, it’s a form of investment;

Then, there is Warren Turnip, a Discord bot I wrote that helps me and my friends keep track of our selling prices every day so we can benefit the most from each other.

My Warren Turnip in action.

At perhaps the same time (even earlier), came Turnip.exchange, a website that lets everyone on the internet post about their islands and set queues for investors to wait in. It is a beautiful system!

Finally, someone was smart enough to make priority queues for those who joined their Discord servers…

Continue reading Taking Bell Investments To the Next Level: Brainstorming Financial Products in Animal Crossing

Camera Controls while Parachuting in Unity (Rotating Around a Sphere)

Abstract

This article takes record of my attempt into creating a camera controllers suitable for free-looking when parachuting. A practical use of this controller is recreating the free-looking camera during the dropping phase in typical Battle Royale games. This controller takes the camera motions in Apex Legends as reference.

Continue reading Camera Controls while Parachuting in Unity (Rotating Around a Sphere)

Little Talks: Diablo, Dungeon-crawling and Open-world Design

When we look at Diablo, we don’t really see it as a game under the open-world genre. Rather, it is has its own genre (although scarcely defined on Wikipedia as dungeon-crawler). Why is that?

Note: While this article may reference other material, it mainly focuses on the Diablo series, and especially Diablo 3. Also, I’m just a casual player, so my experience with the game may largely differ from others.

Attempts and Obstacles

I want to start by attacking straight on point: the world.

The world is basically how the game’s levels are structured. Wikipedia crowns the world of Grand Theft Auto III as the prime example of modern open-world games. If we look at the game, plus a few other titles that are more often regarded as open-world games (such as Breath Of the Wild, Skyrim, Red Dead Redemption), we’ll easily notice that all these games share a common feat: it’s main level is a seamless map. I used the term “main” for players spend the majority of their time on it. Meanwhile Diablo, Path of Exile and other dungeon crawling games, the loading in between levels are simply obvious.

But seamless map design is not the criterion here, or at least it doesn’t stand as a deciding factor alone. I’d argue Super Mario 64 (and Odysssey) are open-world games; the key factor here, I think, is what exists in the “unimportant” areas. These areas can include space that has been visited already, or in a large open world, space that has absolutely no reason to visit (i.e. no quests) in order to finish the game. In Breath of the Wild, you visit different locations to get Korok seeds, which has been proven not required to save Hyrule; similarly, you don’t need to deliver pizzas to protect New York City in Spider-man 2. When compared to the main objective (saving Hyrule, protecting NYC), these content are additional and irrelevant to the main plot, but adds flavor and breadth to the experience.

I don’t think many people realize that the pizza meme song came from this video game.

If games are “voluntary attempts to overcome unnecessary obstacles“, then I argue that open-world games are collections of “voluntary attempts to overcome unnecessary obstacles and attractions“.

Looking back at Diablo and Path of Exile, one will immediately understand that these two games (and perhaps the genre itself) stands at the opposite end of the spectrum. In both of these games, each act is a series of maps of similar aesthetics and minions, and these maps all serve to convey a single plot, which translates into a single objective. When the plot in the area is completed, the game prompts you to move on to the next act, and there is no reason for you to revisit the area anymore. In other words, there are no attractions. While this allows writers to develop stories easier, it also results in a lot of the map’s potential to go into waste.

That being said, I must add that Path of Exile actually has unnecessary attractions, namely the Blight and Vaal Chambers. The blight is especially interesting since it adds an additional layer of tower-defender on top of the core dungeon-crawling gameplay.

Image result for poe blight
You must build towers that deal different types of damage to fend off enemies in the Blight in Path of Exile.

This also reminds me of one particular game: Sonic Adventure (1998). It features open areas where players can explore, but there’s hardly anything else that could be recognized as unnecessary attempts (except Chao Garden and Twinkle Circuit). It may have a large map, but I wouldn’t call it an open-world game.

「Chao garden sa1」的圖片搜尋結果
At the time of playing I was 4. I didn’t really care about chao(s) and I thought tossing them around was a fun thing. You can call this open-world; you can also call me a horrible person.
Source: https://www.deviantart.com/xmilesprower/art/Sonic-Adventure-DX-Chao-garden-692311415

One may argue that players must travel around the city to gain certain key upgrades, such as the keystones to Windy Valley or the Light-speed Shoes upgrade (required to enter Casinopolis); while it is true that players have to traverse the map, they are all necessary effort as you need these items to proceed / clear the next stage. Once these items are obtained, most of the map goes to waste.

You will need the light-speed shoes to proceed to Casinopolis.

Now I must ask myself: how do I make a dungeon-crawling experience more open-world-like (pardon the word chains)? The problem here is that if we were to take out the world structure of Diablo, then it loses its signature; so, we must consider keeping the structure as a design restriction.

I wonder if any games can provide inspiration?

Daily Quests in MMOs: Reusing Space As An Additional Advantage

In my experience with open-world MMORPGs: Blade and Soul, Black Desert Online, World of Warcraft and such, daily quests are mainly tools to keep the players in the game, but they are also great opportunities for players to revisit areas.

Image result for blade and soul 殭屍 轉盤
In Blade and Soul, if you complete enough daily quests, you’ll have enough tokens to play this gigantic roulette, which grants you better gear or items.

The problem here is that daily quests feel pretty much the same, and can easily drain players’ interests. I like to play MMORPGs because I can explore the world and try out different subsystems in the game (like cooking and such), but I never bothered grinding on daily quests; that being said, I believe the success of such design largely depends on how the game (including maps, combat, encounters) are designed to handle daily quests, but that’s a branch of story for another time.

If Diablo decides to implement such quest system, I would consider it as a “direct approach” to add attractions to the playground.

NieR: Automata and Undertale: Reusing Space as Instrument of Narrative

The title pretty much says it all — both of these games re-use their levels to tell a different story. In NieR: Automata, you revisit the abandoned cities as you unravel the cruel fact behind humanity’s disappearance; in Undertale, you revisit the world with a different approach in order to navigate yourself into a different branch of story.

Image result for Undertale 999999
I’m just going to put this here. Go play the game.

This may sound interesting, but writing great stories just for the sake of using levels in a new way is unsustainable, especially for a live-service game. I would argue that if a team were to implement this strategy, they would need an infinite amount of Toby Fox’s to pull it off, for obvious reasons.

But what if the world in which Diablo takes place works in a particular way that requires players to find things?

The Flowering Nose in Slugland: Mechanisms That Maximizes Use of Maps

The Flowering Nose is a 2004 browser game by Seth Fisher and Omar Waly. It features a similar level layout to Diablo, especially the use of isometric projection.

The fun thing about this game, however, is how the world defines the process of going to another level: players must put an object on a receiver tile; the portal then opens a gateway to a corresponding level. This means that players will go to levels like “strawberry level” or “cake level”.

On we go to the Cherry Level!

If you fall down a hole, you don’t die — instead, you go to level hell.

Then, the story requires you to go to all these different levels, and figure out a way to open the locked door seen on the first level you enter. Here, the objective is clear, but the world itself is a huge attraction for players to explore and experience.

Image result for the flowering nose in slugland
The locked door presented to you at the beginning.

What if Diablo takes a similar approach?

I Am Legend: Diablo

Here’s an idea I think Diablo (or any other suitable game) can work on. This idea is first seen, by me, in a long-forgotten game called I Am Legend: Survival.

I Am Legend: Survival is a 2007 online multiplayer game hosted on Second Life, presumably used as a marketing boost for the actual movie. Players pick one of the two factions (humans and zombies). While the goal of the zombie faction is obvious — eliminate humans — humans must work through the entire city and find the ultimate cure.

What’s special about this cure is that it’s the combination of several unknown objects in the world. It can be anything. To validate the results, labs are established scarcely across the huge map, and zombies can temporarily take down these locations. The key point here is that players must travel the world, collect items, combine them, and validate the results to win the game. The world, again, is an attraction. Additionally, players had competed against each other to be the first to the cure, even if the game did not specify such rule.

In other and short words, this is a great competitive multiplayer idea that incorporates map usage and attractions. It is also a competitive multiplayer that requires more of the players’ uptime than their skills.

Here’s my imagination if Diablo III draws from this design (note that these are just concepts and thus doesn’t attempt to align with the Diablo Lore):

  1. Each season marks a new beginning of the hunt for a “key” — forged to open a door, which leads to victory.
  2. The recipe for the key is unknown, but a device is created to vaguely verify the results. Imagine Bulls and Cows, especially where the Bs only tell you that there is a correct number in the wrong position.
  3. Each player who decides to enter the game must pay a LOW entrance fee. This entrance fee builds up in the end and becomes the prize for whoever enters the door first.

Of course, this would possibly prompt for a total redesign of the item system in Diablo (in which the only items are equipment). Nevertheless, this may transform the Diablo game into a more open-world experience, without hurting the main game loop and story much.

Anyways, thanks for reading all this babble! Let me know what you think.

Little Apex Talks #1: Knockdown Shields

I’ll cut right to the point — I think knockdown shields are nearly unusable.

Not saying that it’s a meaningless design, though — it does its job as titled: fending off bullets zipping toward my poor Bangalore. One would assume that its purpose is to keep you alive for as long as possible; the reality is that, whatever the quality of the K.O. shield you possess, you can still be erased from World’s Edge in a matter of seconds.

Speaking of seconds, let’s do some math and see how a shield performs against gunfire.

From A Statistical Perspective

Here’s a table that lists out the statistics for every tier of the knockdown shield.

Resource: https://www.rockpapershotgun.com/2020/02/07/apex-legends-armor-and-gear-season-4-helmet-backpack-knockdown-shield-body-shield/#bodyshields
(Seriously, someone should make a database that keeps track of all the items and all the changes.)

Also according to this website, the gun with the highest DPS up-to-date is the Devotion (255). Take this gun, spray it all on the shield, then give it a few taps on the victim’s hitbox on the head, you’ll end up with a most-efficient time to kill (TTK) of 0.64 ~ 3.19 seconds, depending on the quality of the shield; swap out Devotion with the gun that has the worst DPS, you’ll find that the charge rifle will take 4.75 ~ 25.72 seconds to kill (the drastic raise is predictable — top-level knockdown shield has health 6.5 times larger than your basic white plate).

So, a “standardized kill” — draining the shield before actually hitting the flesh — will take from 0.64 seconds (Devotion, all headshots) to 25.72 seconds (Charge Rifle, all torso shots). If we treat the center of this margin as the average time for one to take out a foe, it’ll take an average player at most 13.18 seconds to complete the job. Yes, at most — in reality, an average player might “miss” a few shots; some pellets may reach the flesh before they meet the barrier.

Note: I must clarify that this number model is inaccurate, as it does not take drop rates of loot into account; rather, this number assumes that all weapons and knockdown barriers have the same drop rate. Unless Respawn publishes an official stat table of loot drop rate, the best we can do as players is to approximate the table by playing and recording. If you ask me to take a guess, it’d be around 7-8 seconds at maximum.

What does 13.18 seconds mean? In Apex Legends, every hero moves in the same speed — 7.4m/s. This means that within this length of time, enemies can travel around 97.5m in distance. To give you a better sense of how that distance feels like in World’s Edge, I tried to calculate myself running for 13 seconds.

The blue line indicates the approximate distance. Thanks to my two unknown teammates who disconnected at the beginning so I can bring out my tests?

Note that this is purely running — there’s no sliding down the hills, grappling or ballooning. This means that an opponent can cover even longer distance than this within 13 seconds.

Why am I covering all these numbers? Right. Let’s talk about gameplay.

Gameplay

To your teammates, 13 seconds is already a short time since they have to sprint to your location, and depending on the location, they might need to navigate through the building or run in zig-zags — not the most efficient way — to avoid taking damage.

To the enemies, 13 seconds is long because their gunfire attracts nearby teams who wants to third-party. It’s actually more efficient if they use the time to knock out the last man standing; but a finishing move takes 5-6 seconds to complete, and normally a kill doesn’t take longer than that. Practically speaking, the shield doesn’t really stop your enemies too much, but indeed gives them a decent time pressure.

To you, however, the shield grants almost no advantage, unless you happen to carry a golden one. You function the same as every knocked-down player in any other Battle Royale title, and the shield’s design is hardly a subtle one. From my experience, its usually better for me not to open my shield, unless I want to become a glowing target in my foe’s viewport.

So, How Do We Fix It?

The question here is functionality — the knockdown shield doesn’t provide much help to its user. The most direct way to address this problem is to make the shield do something more, i.e. add powers to it. In fact, the Golden Shield is a great example, but it’s too rare to be found in the fields of World’s Edge. If a shield also takes different attachments that yields different abilities upon knockdown, it would allow more interesting dynamics towards middle – the end of a gunfight.

However, this could create an extra problem — every fight can include too many surprises. In a life-threatening brawl, players expect faithful outcomes. Attachments to other weapons such as scopes, chokes and add-ons only grant the user a minimal amount of advantage. A player isn’t necessarily at a disadvantage even if they don’t know what attachments their opponent has. Since we’re talking abilities, they might drastically change the status of either themselves, their teammates, their enemies, or even the environment itself. These changes, if not done with extensive playtesting and validation, might bring too much variables to the attacking player.

Alternative Solution

Let’s not think about knockdown shields — or assume that the results of a fight changes little, with or without it. What is a way to introduce interesting end-fight development without surprising players too much?

Think about Mirage’s ability: Encore. Makes him almost invisible when he is downed for a few seconds. It’s not the strongest passive of the roster, but it’s a great inspiration for knockdown abilities. Since every hero has their own fixed ability, it introduces more possible outcomes, and because abilities are tied to characters, they yield less surprising factor to the match.

Think about this (they might be terrible ideas, but hey, they’re ideas)

  • Octane: When downed, begins running with an increased speed by 200% for 4 seconds.
  • Caustic: When downed, drops a capsule.
  • Crypto: When downed, reveals killer’s location on map and outline in view.
  • Wraith: When downed, drops all items immediately, but teleports to the nearest beacon.
  • Lifeline: When downed, grants all remaining teammates a health boost.
  • …And many more.

Anyways, that’s the end of my “rant”. I still like Apex Legends! It has great dynamics, interesting abilities and genuinely the flow of the game is very smooth, compared to PUBG or Fortnite.

I’m Brian. A game designer from Taiwan.

Trying to Design for Overwatch

I love Overwatch. I am fascinated by how took the role-playing shooting genre to the next level with so many different heroes and abilities to choose from; I’m also amazed by how they did so well in telling background stories of the roster with so little effort. In a role-playing competitive game, stories are clearly not the most important, but yet I find myself deeply invested into the universe.

As a game designer and a fan, I often think about the current state of Overwatch, and how to improve the experience and bring more fun to the players. So in January 2019, I’ve started a little project called “Notice me Papa Jeff”. I gathered a few of my friends, who are also game designers, and started brainstorming ideas on a new hero. We had a few meetings, and came up with a list of abilities that we’d like to mix-n-match.

Unfortunately, as we all attend the Entertainment Technology Center, our schedules were swiftly populated by project meetings, assignments and work deadlines, and so we had to put this project aside from our queues; nevertheless, I really liked what we were doing, and especially what I was doing: designing for a game that I love.

So I kept working on it as a side-project on my own, using all the spare time that I have; and now, as the basic have been established, I feel like it is a good time to open it up to the public and receive some feedback.

So here it is! Ranyatta, or, at least for now. 

From the name you could tell that the character is a derivative from Zenyatta. He is a support class, like his twin, but does not focus on healing or individual assists; he is focused on toppling teamfights and reversing the odds at clutch situations. Ranyatta is a hero that requires extensive knowledge and observations to play with, but is very rewarding for the whole team once his abilities are executed correctly.

You can read the document by clicking me! Let me know what you think.

“Mind Game” Postmortem: Lessons Learned From My First Public Project

For the past few months my classmates and I were working on a project in collaboration with Carnegie Mellon University CyLab. This project aims to create a game interface that wraps around picoCTF, an international cybersecurity competition for middle/high school students. We worked to provide an alternate means of participating in the event that would appeal to the more general public (i.e. people who have some interest in the topic but little to no prior knowledge).

Continue reading “Mind Game” Postmortem: Lessons Learned From My First Public Project

Bakery Rivalry: A Game Concept Aimed To Simulate Real-World Trading Scenarios

I started playing RuneScape in 2005, shortly after it’s second version just launched. My experience with MMORPG was very little, and the only other MMORPG I played was Maple Story (when online games are deemed “useless, harmful and cost unnecessary cash” by my mother, which are all painfully true). After completing all the free missions and countless hours of grinding I made myself a “considerable” fortune; the problem was that this fortune was barely usable, since at that time the only ways to spend that money were either purchasing items from NPCs or trading with random players, who will probably only accept the request if you offer ridiculously more than expected.

Then in 2007, a new feature was implemented in to the game — the Grand Exchange. Essentially it collects all the needs and offers across all servers, and let’s players to purchase items through a price decided by the market. This allows players to get what they want for a reasonable price, and also allows sellers who want really wanted to sell items an easier way to find the correct customers instead of wandering around in the world inefficiently.


MMORPGs nowadays all have similar trading systems. For example, Blade and Souls has the exactly same market system that allows players to put their items on sale for the entire community.

Continue reading Bakery Rivalry: A Game Concept Aimed To Simulate Real-World Trading Scenarios