Updated 2 years ago
UNI-I is a side scrolling beat-em-up game being developed with unity. I'm the only person working on this game so far, i'm hoping to see if i can achieve something worthy of developing further with help from others.

Platforming + Combat Moves

One of the fascinating features of guacameele is the fact that you can use special combat moves to perform platforming in the game. I've implemented a similar system in this game. We have stamina + platforming which leverages the special attack moves.

DoTween + FX

I've started using the awesome Tweening library called DoTween, because i've gotten used to the cocos2d-x way of doing things this makes me feel right at home. I've gotten around to adding some Fx for the attacks. I'm using 2D particle system for the attack Fx and Sprite animation for the Dash Attack.

Combat System

I've played a lot of games where you can keep pressing the attack button and the character would go into a frenzy of attacks. This is pretty amazing to look at and feels very satisfying. The other interesting feature is the way you can trigger special attacks by pressing different keys at the same time.
I've never implemented a complicated combo system before, but based on the games i've played so far i wanted to put in these features.
  • Queue of inputs available for player attacks
  • Certain sequence of keys will trigger special attacks.

Queuing the Attacks

in the update function i add the input key to the queue as soon as it's pressed if there is capacity in the queue. I've created a structure to keep track of this info.
struct InputKeyTracker { public KeyCode key; public float timeStamp; };
void Update () { if (Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.K)) { if( inputKeys.Count < MAX_INPUT_QUEUE-1) { AddInputKey(KeyCode.K); } }else if(Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.LeftArrow)) { if (inputKeys.Count < MAX_INPUT_QUEUE - 1) { AddInputKey(KeyCode.A); } } else if (Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.RightArrow)) { if (inputKeys.Count < MAX_INPUT_QUEUE - 1) { AddInputKey(KeyCode.D); } } }
After the key is added, in the fixedUpdate() function, we check if the key queue (attackKeys) has any values, we peek into the first element and check if we have waited long enough for the user to key-in a combo. If the wait time has elapsed and the player character is idle, we figure out if its' an actual combo or a normal attack. We pick a random attack animation for single attack key press events. In the Animation we add a callback function to be called when the animation finishes. This is used to check if there are further keys queued for attack and calling the next attack animation. So if we have a combo attack animation setup with us, we should be able to play through the sequence as long as there are attacks lined up for animation system to pickup.
void FixedUpdate() { if (inputKeys.Count > 0) { InputKeyTracker k0 = (InputKeyTracker)inputKeys[0]; if(Time.time - k0.timeStamp > COMBO_WAIT_TIME && currentAttack == CharacterState.IDLE) { HandleKeyInputs(); } } }

Combo System

The combo system or special key combination attacks for a cleaner explanation.. are a way to unleash powerful attacks by hitting multiple keys in sequence. This has to be done within a certain time, that's the beauty of it. So i used a variable to track the duration between two key strokes and if the second keystroke was hit before the designated wait time elapsed, we would pick normal attack instead.
private void HandleKeyInputs() { InputKeyTracker k0 = (InputKeyTracker)inputKeys[0]; inputKeys.RemoveAt(0); //we have more than 2 keys pressed, figure out if there is a combo that can be executed. if (inputKeys.Count > 0 && (k0.key == KeyCode.D || k0.key == KeyCode.A)) { //we know that this could be a combo stuff. InputKeyTracker k1 = (InputKeyTracker)inputKeys[0]; if (k1.key == KeyCode.K) { inputKeys.RemoveAt(0); if ((k1.timeStamp - k0.timeStamp) < COMBO_WAIT_TIME) { //TODO: special attack goes here. //remove two key strokes from stream. setCharacterState(CharacterState.SPECIAL_ATTACK1); } else { PerformSequenceAttack(); } } else { setCharacterState(CharacterState.IDLE); } } else if (k0.key == KeyCode.K) { PerformSequenceAttack(); } }
This is a snippet from the fixedUpdate() function, where we are checking if the character is IDLE and taking an action if the key combo is valid. This obviously needs to become more flexible, for example the time should be associated with the key press rather than just the previous key like it is right now, I'll work on this to ensure its' a lot more flexible.

Art Pipeline

The art pipeline that i have setup for myself is pretty simple. I draw sketches on the notebooks, digitize them using Inkscape and then color them in Inkscape itself. Once the character is setup, all that remains is to animate the character using the engine specific tools for 2D animation.
I've worked with other 2D Animation packages available from 3rd Parties, Dragon Bones, Spine, Godot and even CocosBuilder all of those tools have one common feature that you could re-use an image for multiple parts of the character without actually replicating the image in the sprite sheet.
For example the skeleton character i made re-uses a single bone image 8 times(red), hand(green), feet (blue) and eye(black) images are used 2 times each. This optimizes the size of the image needed for the character a lot, but in unity i was surprised that i had to put them in the image even if i know i was going to re-use the same piece.

The other interesting thing is the fact that your bone setup is done in sprite-editor and you are supposed to correct the positioning of bones in the unity editor. It isn't a huge pain, but its' a bit weird when you move from other tools.

Once you wrap your head around these two quirks, the workflow is pretty smooth.
With the limited time i spent on the demo, i've been able to implement a simple combo attack system in place. It was pretty easy to find tutorials for most of the things i wanted to do which is awesome. I hope to keep working on this and make something interesting.
vamsi krishna veligatla
thank you :)
Saurabh Saxena
2 years ago
Founder of Delhi Technology Club
Good work 😊