Turns out that thing aren’t always simple as they seem at first glance. I spent more time than planned on overhauling the weapon pickup and replacement system i wrote about in the previous dev log. Apparently, despite the system being laid out well, there were some hurdles that appeared.
First of all, the weapon switching system that was meant to be extremely basic and function by simply activating and deactivating children objects (weapon objects with firing FSMs) on the gunpoint of the ship proved too common for the concept of weapon equipping, upgrading and dropping during the game. I upgraded the system and while it’s very complicated and probably can be laid out a lot simpler, it works as intended.
Upon starting the game, Player is spawned, its child Gunpoint, and Gunpoint children, Basic Weapon Object (Level 1 out of 5 weapon) and Empty Weapon Object. You’re probably wondering why would i put something like Empty Weapon when it’s not even used, but we’ll get to it. Every Weapon Object has two FSMs, Main FSM, used for the upgrade system, and Firing FSM, used for firing the weapon. Gunpoint object stores the Weapon Switch FSM. Bear in mind that Weapon Object can also be Weapon On Ship, or a Weapon Pickup, depending on the state in which it is and the fact that Player can have two weapons equipped, but only one active at the same time.
Weapon Upgrade System – how it works?
Main FSM controller on the Basic Weapon Object enters the first state. It searches for the Gunpoint object (place on the ship where it will be spawned. Search is done by tag, since it is quicker than searching for it by name). When it finds it, it stores it in the variable. By checking if the Weapon Object is childed to a Gunpoint or not, the Main FSM is branching in two directions, which determines if it’s really a weapon equipped by Player, or a Pickup waiting to be collected.
Shorter branch is executed is if the Weapon Object is a child of the Gunpoint object. It is then stored in the Weapons On Ship array, and the Main FSM finishes it’s job for now. That means that it is a weapon equipped by Player and it can be fired.
If it is not childed, it means it’s a Pickup (drifting in space, waiting to be collected), its Firing FSM is disabled, a child which is an animated circle indicator for easier visibility is activated and the state machine starts its next event.
Weapon Object starts measuring distance from the Player. When the distance drops below defined value, Weapon Object can receive the key command from the Player, otherwise, it’s non-responsive to key press. In game terms, when the Player hovers over the weapon, by pressing key following states can occur:
Simplest case occurs ff the same weapon type of maximum upgrade level exists on the ship (checked by iterating through the Weapons On Ship array). “Weapon is at maximum upgrade level” message appears, the pickup eventually leaves the screen and it is despawned.
If the same weapon type of lower upgrade levels exist on the ship, it is upgraded. If the pickup is of the same or lower level than the weapon on the ship, the weapon on the ship is upgraded by one level. But if the pickup is one or more levels higher than the weapon on ship, the weapon on the ship is upgraded to that level. So, you get a pickup and it upgrades your weapon by one or more levels and it disappears. In game terms, it sounds simple, but actually there’s a lot of mechanics behind it.
For example, Player is equiped with Level 1 Weapon, and there’s a Level 1 Weapon Pickup which we collect. Level 1 Weapon Pickup iterates through the Weapons On Ship array, and it finds the Level 1 Weapon of the same type. It gets the position of the Gunpoint object, spawns Level 2 Weapon and adds it to the Weapons On Ship array. It also checks if the Level 1 Weapon in the array has its Main FSM enabled or not. If it is enabled, that means it’s an active weapon (we’ll also get to it when we get to the Weapon Switching mechanism), which means that the Level 2 Weapon that is spawned should also be active which is done by activating Firing FSM on Level 2 Weapon nad adding it to the Active Weapon array (needed for the Weapon Switching mechanism). Firing FSM on Level 1 Weapon is disabled, it is removed from the Active Weapon array, removed from the Weapons On Ship array, Level 1 Weapon equipped on ship itself is despawned and Level 1 Pickup is finally despawned at the end of the last state. If the Level 1 Weapon on ship is inactive (its Firing FSM is deactivated), the Level 2 Weapon also spawns with its Firing FSM deactivated, but is not added to the Active Weapon array.
What happens if the Player is equipped with one or two weapons that are different from the pickup?
Things get a bit complicated there. If Weapon On Ship array does not contain any of the levels of the Weapon Object that is the same as the Weapon Object pickup, a Replace Active/Replace Empty state is entered. Remember the Empty Weapon object from the setup? It is used as a placeholder when picking up a weapon that is different from the basic equipped weapon. By iterating the Weapon On Ship array and finding no weapons of the same type but finding an Empty Weapon object, it is simply despawned, removed from Weapons On Ship array and replaced by the picked up Weapon Object. Since it is not active, spawned weapon Firing FSM is also not active, thus not added to the Active Weapon array.
A different Active Weapon acts similar to an Empty Weapon object if all slots are taken. It is removed from the Weapons On Ship array, removed from the Active Weapon array, deparented from the Gunpoint, its children activated (circle indicator that makes it visible more better on screen), and the pickup is spawned on the Gunpoint. As i said in the beginning, whenever a Weapon Object spawns, it immediately checks if it is a parent of the Gunpoint or not, and then added to the Weapons On Ship array or not.
Finally, switching the weapons. First we need to make sure that the Player can’t cycle between the equipped weapon and the Empty Weapon object. As long as the Empty Weapon is in the Weapons On Ship array, cycling is not enabled. When it is no longer contained in the array, Player can freely switch between weapons. Every switch gets the first and second index numbers of the Weapons On Ship array, stores them as Weapon 1 and Weapon 2 variables, enables and disables Firing FSM on them, adds the Weapon Object with enabled Firing FSM to the Active Weapon array, and removes the Weapon Object with disabled Firing FSM from the Active Weapon array. We need the information about the Active Weapon so it can be replaced with the pickup that is different from it. That enables the Player to upgrade the weapon of the same type as the pickup on ship whether it is active or not, or select which weapon will be replaced (if both are different from the pickup) by simply switching weapons to active or not.
It’s been almost two weeks and i’ve been very busy with my day job so i didn’t manage to spare too much time for game, but i finally finished (for me) a very complicated thing – upgrade and weapon switching system.
Player starts out with one weapon. During the game he can pickup a variety of weapons from destroyed cargo ships. The first time he picks up a weapon, it is added as a second weapon, and player can switch between them according to situation (bullet, energy and missile weapons don’t deal the same amount to normal, armored and shielded enemies). When another weapon appears as a pickup, two scenarios are possible: if the weapon is already equipped, it gets upgraded and the pickup despawns. If the weapon is already at maximum upgrade level, player is notified via on-screen message and the pickup stays where it is. If the weapon is not equipped, currently selected weapon is replaced (dropped as a pickup, while pickup spawns on player). While dropping the weapon is not very important in single player game and complicates the situation a lot, it is handy in 2 player game, where one player can drop a weapon for the other player to upgrade his weapon. The handy thing is that when a player drops, for example, Hyperblaster Level 4 and the other player picks it up, he’ll get the Level 4 Hyperblaster too, not level 1. Since there are (for now) 23 weapons in game and the only way to upgrade them (besides universal weapon upgrade pickups) is to pickup the same weapon, that will be very cool in terms of player cooperation.
Here’s a shot of an FSM:
Basically, when the weapon spawns, it checks itself if it is a weapon or a pickup (by checking if it is parented or not). If it is a weapon, that means that it is player equipped and it is added to the array and the variable is stored if it is in slot one or slot two (required for weapon switching during the game). If it is a pickup, distance check state is activated. Player can only pick it up if he is closer than a defined distance from it (by pressing space, so no accidental pickups are possible). When he picks it up, it iterates through the array to see if it will replace the existing weapon (if no weapon of same type is found) or upgrade it (if weapon of same type is found). If it replaces it, the existing weapon is dropped (which means it is despawned, removed from array, spawned on location of a pickup with its firing scripts disabled and pickup indicator enabled, while next level weapon is spawned on gunpoint with its firing scripts enabled and pickup indicator disabled).
Weapon switching is, compare to the upgrade and pickup system, a walk in the park. Stored weapons are simply activated/deactivated by pressing the switch key.
Scripting this thing alone would probably take a lot more time than it did, so using Playmaker did the job pretty quick since i can try something out in a matter of seconds, not waiting to write a couple of lines with risk of making syntax errors.
But, here comes the downside. Instead of making the script that can just be copied/pasted on all weapons (have in mind that there are 23 weapon with 3-5 levels each, so that comes to about a hundred prefabs, with more to come), i have to copy/paste an FSM to every weapon and tweak the variables in each one of them. I don’t have to tell you that if any larger scale fixes in logic are necessary when all the weapons are already prepared it will be a lot of work to change everything. Not to mention the possibility of making errors when managing such a tedious task.
One more thing i did is implementing the sprite atlas which reduced draw calls a lot, and boosted frame rate from 15-30 FPS to ~150. Now everything goes very smoothly. There are some hiccups, but those are due to extensive logging which is quite necessary in this phase. Swarm missiles got an overhaul too, now they’re flying nicely in a semi-random homing pattern, they way i imagined them to be.
Also, the artist guy did some weapons art for me, some will maybe change, but i thing they’re pretty good looking and quite different.