Rival Megagun - PVP Battle Shmup

Unity C# Online Multiplayer Steam PS4 Xbox One Nintendo Switch


The Game

Rival Megagun is a split-screen PVP battle shmup (or shoot ‘em up, shooting game, STG) where you transform into a huge boss ship - your “Mega Gunship” - to invade your opponent’s screen.

Released November 29, 2018 on PC, PS4, Xbox One, and Nintendo Switch.

History

In 2014 I started building a simple prototype written in Java called Project Rival. I worked on Project Rival in my spare time on evenings and weekends. As the game started to take shape it was moved to Unity to reduce development time.

Project Rival - Java prototype Project Rival - Java prototype

Rival Megagun - First day in Unity Rival Megagun - First day in Unity

In 2017 I began working full time on Rival Megagun. Shortly after that, I partnered with Japanese publisher Degica. Quickly Rival Megagun transformed from a cool idea into a full-fledged project. Over the next two years I built Rival Megagun with the help of a small team: Jordan Ivey, sound designer; Brooke Fargo, narrative designer; Aarne Hunziker, artist; and Dominic Ninmark, musician.

Rival Megagun now Rival Megagun now

Events and Travel

In 2018 I met with Yoshiyasu Matsushita in Tokyo, Japan. He is the creator of Twinkle Star Sprites, the original game that sparked inspiration for Rival Megagun. As you can imagine this was very exciting for me.

4Gamer interviewed us together. Check it out here (Japanese).

Meeting with Yoshiyasu Matsushita Meeting Yoshiyasu Matsushita

Rival Megagun has been showcased at many events all over the world. Below are just a few examples.


I showcased Rival Megagun at BitSummit 2018 in Kyoto, Japan. Unity interviewed me at this event. Check it out here (Japanese).

BitSummit BitSummit 2018


I showcased the game at The MIX 2018 in Seattle, WA. Shacknews interviewed me at this event.

Shacknews Interview


I also showcased Rival Megagun at PAX South 2018 in San Antonio, TX.

PAX South Rival Megagun at PAX South 2018

Online Multiplayer

The first convention I showed Rival Megagun at was the Seattle Indies Expo 2016. At the time I didn’t have many features planned beyond a simple local versus mode. I had no plans for online multiplayer. Lots of people came to play Rival Megagun at the Seattle Indies Expo, and such a huge number of them were asking me if there would be an online mode that eventually I just started saying “yes”. I implemented online multiplayer first thing when I got back from the event.

Shmup networking is known for being particularly challenging. These types of games have very small hitboxes and lots of bullets and enemies on the screen, so every pixel counts. With Rival Megagun we are lucky because it is a split-screen game. To put it simply, there is never an instance where both players need to dodge the same bullet. This give us much more leeway for hiding lag and synchronizing online play.

In Rival Megagun’s online battles, most of what you see on your opponent’s side of the screen is running locally, with the exception of the player’s ship position, which is simulated using a basic movement prediction algorithm. This makes for very smooth online play because you never encounter teleporting enemies or bullets due to lag spikes.

Synchronization of the “Mega Gunship” had to be implemented differently from the normal player ships. During this mode both players share one side of the screen and fire bullets directly at each other. This requires more precise synchronization. Fortunately, there is less need for finesse while controlling your character in the Mega Gunship, so the solution was to implement input delay for the Mega Gunship. This keeps these head-to-head battles smooth and synchronized.

Here’s a video I found of some online battles:

Rival Megagun online battles

Rival Megagun’s online multiplayer was implemented for all platforms using the platforms’ online services (Steam P2P, Sony PSN, Xbox One Multiplayer, Nintendo NEX/Pia).

I wrote about how I implemented online multiplayer without any extra costs here.

Artificial Intelligence (AI)

Rival Megagun has a single player arcade mode where you are pit against the other characters and fight them one by one in the standard split-screen format. For this to work, the CPU player requires bullet hell dodging AI.

The dodging AI is fairly simple when you break it down:

  1. Find the closest “hazard” (bullet, enemy, etc.)
  2. Orbit the subject around the hazard
  3. Change direction if the subject’s directional vector intersects the hazard’s directional vector

There are three noteworthy lines in the image below: the line connecting the subject to the closest hazard (red), the closest hazard’s direction (green), and the subject’s direction (yellow). If the three lines form a triangle, switch the subject’s direction.

Debugging player ship AI Debugging player ship AI

User Interface (UI)

Below are just a few examples of how I implemented the UI in Rival Megagun.

Gameplay

The gameplay UI must be completely independent from the game logic. In other words, if I delete all of the UI, the game must continue to function without it. For this reason, all of the gameplay UI components use an event system to update themselves based on the current state of the game.

For example, here is the Win Counter:

public class UIWinCounter : MonoBehaviour {

    public UIIconCounter totalWins;
    public UIIconCounter currentWins;

    void Start () 
    {
        EventManager.Instance.Subscribe<RoundEndedEventArgs> (RefreshWins);

        totalWins.maxIcons = GameConfigManager.Instance.gameplay.winsNeeded;
        currentWins.maxIcons = GameConfigManager.Instance.gameplay.winsNeeded;

        totalWins.SetCount(GameConfigManager.Instance.gameplay.winsNeeded);
        currentWins.SetCount(0);
    }

    void OnDestroy() 
    {
        EventManager.Instance.Unsubscribe<RoundEndedEventArgs>(RefreshWins);
    }

    void RefreshWins(object sender, RoundEndedEventArgs args)
    {
        currentWins.SetCount (GameplayManager.Instance.GetWinCount(gameObject.GetSide().ToPlayer()));
    }
}

Win Counters Win Counters

Popups

Much of the UI in Rival Megagun is built using my custom “popup” system. A popup can be anything. Character dialogue, the pause menu, and the game over screen are all examples of popups.

Game Over The game over screen is just a full-screen popup with a transparent background.

The popup system is simple and versatile. Here’s the Alert Popup, one of the most basic popups in Rival Megagun:

public class AlertPopup : Popup {

    public TMP_Text label;

    private Action onClose;
    private bool onCloseTriggered;

    public override void Setup(object[] args)
    {
        LanguageManager.Instance.SetParameters(label, args[2] as object[]);
        LanguageManager.Instance.SetTerm(label, args[1] as string);

        onClose = args[0] as Action;
        onCloseTriggered = false;
    }

    public static object[] BuildArgs(Action onClose, string locKey, object[] locParams)
    {
        return new object[]
        {
            onClose,
            locKey,
            locParams,
        };
    }

    void Update()
    {
        if (IsTweening())
        {
            return;
        }

        if (InputManager.Instance.GetInputDown(GameData.InputController.ANY, InputActionID.CONFIRM))
        {
            Close();
        }
    }
        
    public override void Close()
    {
        base.Close();

        if (!onCloseTriggered && onClose != null)
        {
            onCloseTriggered = true;
            onClose.Invoke();
        }
    }
}

The popup is displayed with a simple function call:

PopupManager.Instance.ShowPopup<AlertPopup>(AlertPopup.BuildArgs(locKey, onClose, locParams));

Alert Popup Alert Popup

BuildArgs is implemented for each type of popup to feed arguments into Setup. This structure makes it easy to implement any type of popup.

Many complex popups have been implemented using this structure. Here’s a few:

Popup Prefabs Popup Prefabs

Inline Text Elements

I built a system for displaying UI elements inline with text.

For example, this dialogue data:

"dlg_tutorial_04_a":{  
    "id":"dlg_tutorial_04_a",
    "characters":[  
        "HOST"
    ],
    "next":"",
    "locKey":"Dialogue/Tutorial/04",
    "inlineElements":[  
        {  
            "elementId":"BUTTON_0",
            "type":"BUTTON_ICON",
            "attrs":{  
                "action":"fire",
            },
        }
    ]
}

Maps to this text: Oh yeah baby! Now let's shoot some stuff. Press <style=inline>BUTTON_0</style> to fire.,

And has an inline element named “BUTTON_0”.

In this particular example, the element is a button icon, which is a special type of inline element that detects the player’s controller type and displays the button mapped to the desired action (in this case the “fire” action).

Here’s how it looks in-game:

Rival Megagun inline element example Rival Megagun inline element example

Tools

Here are some of the development tools that I created for Rival Megagun.

Bullet Builder

The Bullet Builder is used to create enemy bullet patterns and export the data to JSON. Bullet patterns are customized and attached to various emitters (or “guns”) on each enemy. With this tool you can play and experiment while designing bullet patterns at runtime.

Attaching bullet patterns to an enemy’s guns Attaching bullet patterns to an enemy’s guns

Configuring bullet pattern Configuring bullet pattern

Wave Creator

The Wave Creator is used to create enemy “waves” and export the data to JSON. A wave is essentially a group of enemies and some rules defining how and when they should spawn.

Each wave is assigned a difficulty range in which it is able to spawn. In any Rival Megagun match, the difficulty increases over time, causing the gameplay to get more hectic as more difficult enemies and bigger or more complex waves spawn on the screen.

Configuring wave’s spawn rules Configuring wave’s spawn rules

Configuring wave’s enemies Configuring wave’s enemies

Rawchars

Rawchars is a collection of raw text files containing characters in different languages. When localizing games, generally you should generate your fonts using your localized text. However, you may also need to display user content (i.e. user names). I created “Rawchars” to help cover all the bases.

Get it on GitHub.

Font Correction Tool

When we were localizing the game we noticed that some of the characters in Chinese, Japanese, and Korean (CJK) fonts had inconsistent baselines. Unfortunately this was because the OpenType Base table is not supported by the font plugin we were using, and our only option at this point was to manually adjust individual characters. I am not versed in CJK, so I couldn’t trust my own eyes with this issue. I created a tool for translators to fix the fonts using in-game text examples.

Font Correction Tool Font Correction Tool

Web Development

Rival Megagun needed a new website before we started marketing the game. I’m cheap, so I didn’t want to pay for hosting. I now use Jekyll and GitHub Pages and don’t have to pay for anything except for the $10/yr domain. This method even allowed me to create a blog that supports comments without a backend. Cool!

Rival Megagun Website

Launch

Rival Megagun was released worldwide on November 29, 2018 on PC, PS4, Xbox One, and Nintendo Switch.