Amerigo Moscaroli - Game Programmer
  • Home
  • University Projects
    • Eye-Snipe
    • Airport Mayhem
    • Star-Buck
    • HLSL Demos
  • Professional Work
    • Race Yourself - Glass (Beta)
    • Race Yourself - Mobile (Beta)
    • Race Yourself - Gear
    • Crazy Slots Adventure
    • Cops 'n' Robbers: World Tour
  • Tutorials
    • OpenGL ES Video Tutorials
    • Creating Cross Platform Games with Xamarin
    • Creating a 2D Platformer
    • Create and Monetize your C# Games on iOS and Android
  • Personal Projects
    • A Crack in Time - Dev Blog
    • Time Runner

Player Attacks Part 3

3/23/2019

0 Comments

 
This will be the last part for the attack system for now - I will create the weapon & register the hitbox!
I downloaded the weapon pack from Quaternius' Patreon account for use with my player character (his Patreon can be found here). 
I used the Dagger asset from this pack, and started by creating a new C++ class which inherits from Actor. For now this class is pretty simple, with a method to get the hitbox of the weapon and a constructor. In the constructor I created a StaticMeshComponent and set it as the root component of the Actor, and then I create a BoxComponent to be used for the collision of the attack. 
Picture
With this class set up, I create a blueprint class which inherited from this one - this way I can set the mesh through blueprint & easily edit properties of the hit box. For the hitbox, I added a new Object Channel for collision filtering for an Attackable object:
Picture
I also created two new presets for the attacking - once for the PlayerAttack which overlaps the Attackable objects, and one for the Attackable which blocks all incoming objects.
​For the Dagger blueprint, I created a hitbox that was slightly bigger than the dagger to make the weapon collisions a bit more player-friendly. The end result of the blueprint was this:

Picture
The next step is to have the dagger spawn in the Player's hand. I opened up my Character class and in the header I added a couple of new fields - a TSubclassOf<Dagger> and the Dagger instance itself. I used this method so that in the blueprint I am able to easily change the Dagger class if I ever need to - in the future I'll make a subclass called Weapon so that I can switch the type of weapon the player has. I also added a getter for the weapon.
In the BeginPlay of my character I spawned my Dagger and attached it to the sword socket on the player:
Picture
Next I need to edit my character's skeleton to actually add the socket for the weapon. In the skeleton, I added the socket to the MiddleHand_R bone and set the transforms so that the dagger fits correctly into the hand:
Picture
The last class I need to edit is the Player's Attack state so that I can activate the weapon. 
First, I updated the SetCharacter method in the state to cast the character to a PlayerCharacter object - this way I can retrieve the weapon when required:
Picture
Next, I updated the OnEnter method so that I can retrieve the player's weapon & the hitbox, and then register my callback for when the collision box overlaps an object:
Picture
For the next step I had to add the method for the callback. For this method I had to add a couple of new fields to my state:
  • hitActors_ - This is a TArray of all the Actors that have been hit in the current attack. This will be compared against during the overlap so that an Actor isn't accidentally hit twice if they're moving.
  • damage_ - This is the amount of damage that the attack will perform.
In the callback method, I first iterate through the list of actors and check that the current actor hasn't already been hit. If it hasn't I add the actor to the list and apply point damage to it:
Picture
Next I had to update the OnMessageReceived method to perform extra functionality during certain messages:
  • In OnAttackStart, I allow the hitbox to generate overlap events
  • In OnAttackEnd, I disable the hitbox's ability to generate overlap events again
  • In OnAttackComplete, I empty the list of actors so that the next attack starts fresh, allowing all objects to be hit again. 
Picture
Finally, in the OnExit method if the hitbox exists I de-register my callback from the hitbox.
Picture
Now all I needed to do was test the attack! For testing purposes I created a new Blueprint class for a crate, and attach a box mesh to the object. In the event graph, I added a node for the PointDamage event and used this to damage the crate. The health is decremented, and if it is less than zero the crate is destroyed. I also set the default of the health to 5 so that it can be destroyed in one hit.
Picture
Now, when I run the game you can see the attack!
Picture
With the attack system now in place, the next area of the game I'm going to be looking at is the Stop Time ability! This system will also be split into multiple posts, so stay tuned!
0 Comments

Player Attacks Part 2

3/11/2019

0 Comments

 
Now that the animation is all set-up, the next thing I needed to implement was the attack state for the player. For my game, I'm currently going to have a combo system where the player can press the attack button multiple times to chain a melee attack. In the future, I might look at having different melee attacks such as strong attacks and special attacks, but for now I'll focus on the standard melee attacks.

First, I needed to add a new state class that the player can enter for attacking. I added multiple variables to this class:
  • The animation instance - used to trigger the attack animation montage
  • An int32 for the current combo count - this is to keep track of how many attacks the player has completed
  • An int32 for the maximum combo count - used to prevent too many attacks
  • A bool for whether or not a combo has been chained - this prevents spamming of the attack button
  • A bool for whether or not the player is in the "combo area" - this way, the player can only chain attacks between certain frames of the animation
I started overriding the OnEnter method from the IState interface - in this method I have reset the variables and told the animation to start the attack montage.
Next, I overrode the OnMessageReceived method, which is where the bulk of the logic will be as the state will handle messages from the animation - this method looks like the following:
Picture
In the OnAttackStart and OnAttackEnd, I will eventually activate the weapon however for now I have activated & deactivated the combo area. The OnAttackComplete message resets the playNextAttack boolean so that the player can trigger another combo attack. Finally, the OnAnimationComplete message will change the state to the Idle state.
Next I have overridden the the OnActionInputReceived method, where I check if the input is the Attack input, and if it is the player can attempt to combo an attack. The method looks like the following:
Picture
Finally, I overrode the OnExit method to stop the attack on the animation instance.

I had to create a subclass of the animation instance so I could add my own custom methods for performing the attacks. I added a variable for the animation montage of the attack, and 3 methods - StartAttack, ChangeAttack and StopAttack:
Picture
In the ChangeAttack method, I form the section names for the montage & tell the montage to set the next section. The StartAttack method simply starts the montage, and the StopAttack method stops the montage. Once this class was complete I re-parented the animation blueprint of the player to my new class.
The last step was to add the state to the PlayerController. Now, the player can attack:
Picture
In the next post I will discuss how I implemented the hitbox & the particle effect for the attack.
0 Comments

Player Attacks - Part 1

3/11/2019

0 Comments

 
I've decided to split the player attack explanation into multiple parts, as there's quite a lot to go through. This part will mainly explain how the animations are played for the player's attacks & the notifications into the PlayerController.

I decided to use an Animation Montage to put together the sword attack combos. For this temporary asset, I only had the 1 attack animation so to create the combo I added the animation multiple times into the montage, reversing the next animation for the follow-up attack. I then trimmed each animation so it flows directly into each other and split each part into sections, and by the end the sections looked like this:
Picture
By default, each section will play an animation and if it is not told to play another section it will play the wind-down animation and end the attack.
For the next part of this montage I needed to add the notify events so that the state can be messaged when the attack end, when the animation is complete and when the attack should be activated.
For the AttackComplete and AnimationComplete events I used a basic Notify, whereas for the Attack active state I used a NotifyState - this way I can make the attack active with the NotifyBegin and NotifyEnd methods.
I created a subclass for the NotifyState which is used to notify the PlayerController about the attack becoming active using a message. Currently, the NotifyState only works with the PlayerController but in the future I might need to refactor this to be more generic. In the end, this class looks like this: 
Picture
I added multiple null checks into the GetPlayerController method to ensure that the PlayerController is valid, and I send the attack start & end message through to the player controller if it is. 
​I then added the notifications into the animation montage at key points during each animation, so the final result looked like this:
Picture
Now with the montage setup I needed to add the montage to the animation blueprint. First, I updated the AnimGraph to play the montage between the default pose like so:
Picture
I assigned the slot to be the AttackSlot that I defined, and hooked up the animation to the final animation pose.
I then updated the EventGraph for the new animation to allow for sending messages to the player controller after the montage events:
Picture
I added three variables to the blueprint - an FName for the Attack completing, an FName for the Animation completing and a PlayerController instance. I added the PlayerController so that I wouldn't have to continuously cast the controller for the notifies.
I then implemented the BeginPlay method to obtain the player controller & set it.
Finally I added the events for both AnimNotify events which will simply send a message to the player controller.

The animation blueprint & the animation are now both ready for the attacks! The next post will discuss the implementation of the Attack state.
0 Comments

Character State

3/4/2019

0 Comments

 
So before I jumped into creating the attack logic I decided to do a minor refactor to allow for the PlayerController to control the current state. The idea behind this is that the state will dictate what exactly to do with any input or other messages that it receives from the controller. Initially I'm going to have the following states for the character:
  • Idle/Movement - the state where the player can navigate the map & jump etc.
  • Attack - The state where the player can attack enemies with his sword.
  • Interact - Where the player can interact with the environment/NPCs
  • Power/Abilities - Certain abilities may use different controls or messages. I'll flesh this out as I develop the abilities.
As the game progresses I imagine there'll be more states required to separate character logic, however for now these states should work well.

I decided to use an interface for the character state called IState, however I encountered a number of issues while creating the interface. This was mainly due to documentation online being seemingly catered to the Blueprint implementation of the interface. 

Documentation online showed that interfaces should be implemented via the UFUNCTION macro with the  BlueprintNativeEvent or BlueprintImplementableEvent tag. Using this method, in the class that inherits from the interface the method needs to override Method_Implementation() instead of just Method(). Then, to call the method, you can use the static method in the interface and pass in the object you want to call the method on. For example, with an interface callled IState and a method called OnEnter, call IState::Execute_OnEnter(myActor).

 However, for a pure C++ implementation, you can use standard pure virtual methods to define the interface methods & override them as usual.

I first created a new class in Unreal making it a subclass of UInterface. With the interface, all methods are defined in the class prefixed with I, so my state looks like this:
Picture
So when a state begins, the OnEnter is called and when its complete OnExit is called. When the states are created the PlayerController sets the OnComplete callback and the Character that the state will alter. When the PlayerController receives any input or messages, they are forwarded on to the state. For the OnComplete callback and the Character, I decided to keep those methods pure as interfaces should not contain any logic.
For the OnComplete callback, I used Unreal's Dynamic Delegate with 1 parameter so that the state can tell the controller which state to enter next. The delegate looks like this:
Picture
I then added a new state for the player called USPlayerIdle, which inherits from UObject and IState. For this state, I moved the movement logic in from the PlayerController which looks like this:
Picture
In the OnActionInputReceived method, I've added a check for the Attack input binding which will execute the OnComplete callback to start the Attack state. The rest of the state is empty for now. 

The last change I had to perform was to the PlayerController to take into account the player's state. I've added a new PopulateStateList method which will fill a TMap with implementations of the IState interface, with the key being an FName. I added an InitialiseStates method which then passes through the OnComplete delegate and the character to each state - this method looks like the following:
Picture
In BeginPlay, I call the two new methods & set the current state to be my new Idle/Movement state. Finally, I altered the input methods to pass the input to the current state as so:
Picture
So now its back to where it was before, but cleaner!

Next post will be the Attack implementation, which might be split into 2 depending on the length.
0 Comments

    Author

    Software developer working on a game in Unreal Engine 4, this blog chronicles the development of the game.

    Archives

    March 2019
    February 2019

    Categories

    All

    RSS Feed