Shooter Game Tutorial
Saturday, 30 May 2015
Saturday, 23 May 2015
Refactoring
I started this project when Unreal Engine 4 was released. It was months ago and during this time engine has changed a lot. There is lot of things that can be done better and faster now using latest UE4 version.
Another thing is that couple of functionalities that I wrote here won't work in current UE4 version. I was thinking how to resolve that and I came to decision.
I decided to do full refactor of functionalities that I have wrote here and I will try to use assets only from Unreal Marketplace because I can see that people are having problems with porting assets from Unity or using 3d studio max.
Another thing is that I have learned UE4 a lot during this time so hopefully my new posts will be much more easier to understand and easier to implement to your own projects.
Basically earlier I was planning to do refactor after completed demo. Doing full refactor is something typical in game development after working prototype/demo. The main goal of prototype/demo is to show core gameplay and how fun it is - not optimisations, systems and backend - those doesn't matter because you don't know if the game that you are doing will be fun. Implementing systems or backend takes time (money and energy) and they should be implemented after you are sure that core gameplay is fun.
Most of the game development companies have "prototype new ideas" teams that are doing new gameplay prototypes (or whole new games ideas) and they aren't focusing on optimisations or systems (because it takes time and budget) Their goal is to achieve fun as soon as possible. If the fun is there and the team is sure about it project will be kicked off from beginning.
You can ask why to start from beginning if lot of work was done during creation of prototype. Why to put all of the work to trash?
Well... I see a lot of games in production that are lacking with optimisations / good and effective pipelines because they are moving forward to fast like when they were in prototype stage. There are two big advantages of doing full refactor after prototype:
- Programmers can analyse the prototype and plan how to implement core from start to be prepared for fast iterations,
- Whole team can improve pipelines effectivity,
Basically thanks to that your production will be moving faster forward and your team will be more happy because it will be easier to iterate.
To sum up I will start from scratch and use Unreal Marketplace content. The idea for the game hasn't change but during the prototyping I've lot of ideas to make the game better. Stay tuned for first refactoring post!
Another thing is that couple of functionalities that I wrote here won't work in current UE4 version. I was thinking how to resolve that and I came to decision.
I decided to do full refactor of functionalities that I have wrote here and I will try to use assets only from Unreal Marketplace because I can see that people are having problems with porting assets from Unity or using 3d studio max.
Another thing is that I have learned UE4 a lot during this time so hopefully my new posts will be much more easier to understand and easier to implement to your own projects.
Basically earlier I was planning to do refactor after completed demo. Doing full refactor is something typical in game development after working prototype/demo. The main goal of prototype/demo is to show core gameplay and how fun it is - not optimisations, systems and backend - those doesn't matter because you don't know if the game that you are doing will be fun. Implementing systems or backend takes time (money and energy) and they should be implemented after you are sure that core gameplay is fun.
Most of the game development companies have "prototype new ideas" teams that are doing new gameplay prototypes (or whole new games ideas) and they aren't focusing on optimisations or systems (because it takes time and budget) Their goal is to achieve fun as soon as possible. If the fun is there and the team is sure about it project will be kicked off from beginning.
You can ask why to start from beginning if lot of work was done during creation of prototype. Why to put all of the work to trash?
Well... I see a lot of games in production that are lacking with optimisations / good and effective pipelines because they are moving forward to fast like when they were in prototype stage. There are two big advantages of doing full refactor after prototype:
- Programmers can analyse the prototype and plan how to implement core from start to be prepared for fast iterations,
- Whole team can improve pipelines effectivity,
Basically thanks to that your production will be moving faster forward and your team will be more happy because it will be easier to iterate.
To sum up I will start from scratch and use Unreal Marketplace content. The idea for the game hasn't change but during the prototyping I've lot of ideas to make the game better. Stay tuned for first refactoring post!
Tuesday, 6 January 2015
Prototype - Sci-Fi Enemy Brute
Next enemy will be different than others. I will use Sci-Fi Orc from Dexsoft.
Enemy spec:
- Can crounch,
- Will shoot from random position,
- Will reload his weapon,
- Can do Melee damage,
- If you hit in the head - ragdoll will appear,
- Mouth simple animation,
Animation States
First of all you really should watch Epic tutorial about blend spaces and states and read about them here.
Create new blueprint extending from MainAI_Pawn, name it Orc_Pawn. Change walk speed to 200 (in defaults) and add isCrounching bool variable. Make it exposed on spawn.
I assume that you imported all of your animations at this point. If you have a problem with them post in comments.
We will need two blend spaces (1D ofc)
- CrouchWithWeapon_Idle to CrouchWithWeapon_Walk,
- WithWeapon_Idle to WithWeapon_Walk,
The max speed should be set to 200 (as in Orc_Pawn defaults)
Now create AnimationBlueprint and add variables:
- Speed - float,
- IsCrounching - bool,
- CurrentVelocity - float,
In your Event Graph update those variables like here:
I'm using interpolation because Velocity is changing really fast and I don't know why. Here's a topic about that on AH.
Now in Anim Graph we will be using Montage animations so it will be blended as earlier character. Locomotion will be described in couple of seconds ;)
And here's locomotion. Basically I'm checking if isCrouched is set or not and use different blend spaces.
Now in your spawn manager change spawning to Orc_Pawn and create Random Bool as isCrouching variable.
At this point you will see that your Orc is moving and stopping with proper animations!
Animation - Reload
First let's prepare our reload animation. I will use state machine here and I don't know if it's the best solution. You could use animation montages for this but I'll try to improve current state machine.
Open your Animation Blueprint and add new bool variable: isReloading.
Now go to your Locomotion state machine and add two new states coming from crouching and walking - CrouchReload and WalkReload like here:
We are going to Crouch_Reload when isReloading == true. We go back if it's false. The same for Walk_Reload.
As for the states - I'm blending reload animation with our blend space using Bip01_Spine bone. Here's crouch_reload example - the same should be added to Walk_Reload but with walk blend space and walkreload animation.
At this point when you change isReloading you should see reloading animation. We aren't driving isReload variable at this point. Open Orc_Pawn and create new bool variable: isReloading. Create new function SetReloading and add one bool to input, and set isReloading using this function like here:
I'm using function to change this bool because weren't able to change it from notify.
Now create new Blueprint extending from AnimNofity and name it Orc_ReloadEnd. If you don't know anything about notifies just read earlier posts. Using this notify will set IsReloading to false so the animation will play only once.
Now add this notify into your reload animations (in the end of the animation) if you don't know how - as always: read older posts! :)
In your animation blueprint event graph you need to set isReloading from Orc_Pawn - don't forget about it!
At this point Orc will play reload animation when isReloading is set.
Mouth Simple Animation
This will be simple. Open Animation Blueprint and add some variables:
- isShouting - bool,
- isOpeningMouth - bool,
- ShoutTranslation - vector,
- ShoutRotation - rotator, (0,5, -25)
- ShoutAlpha (float),
Now in your anim graph after your locomotion we will modify Jaw bone like here:
In event graph we will increase ShoutAlpha and decrease it so it will look like the Brute is yelling.
Do Once block is playing shout sound. You would need to properly setup delays for animation to fit your sound.
Animation - Recoil
We were doing recoil earlier in our fpp arm mesh. This time I will try to do it better and only using animation blueprint. It will be harder than mouth animation because we will need to modify couple of bones.
First let's create the functionality. In your Animation Blueprint add new variables:
- RecoilRotation (rotator: 0, -2, 0)
- RecoilAlpha (float,
- RecoilTranslation (vector: 0,-6,0)
- RecoilStart (bool)
- isShooting?(bool - you will use that for test while simulating)
Now in EventGraph let's fill RecoilAlpha as we did with mouth. If you would like to have better results you should add more random to the variables here.
And in AnimGraph let's modify some bones with the RecoilAlpha.
Modify should be in ComponentSpace and it should be Additive.
You can test it out if isShooting is set to true. Just simulate and polish the effect. You can add more bones, create more variables for different bones.
Shooting - Projectiles
So we have recoil but what about shooting real bullets? Go to your OrcPawn and add custom event - BruteShoot. Compile and go back to AnimationBlueprint. In the event graph let the OrcPawn know that we have started recoil.
New block highlighted. |
Go back to OrcPawn and try to spawn some projectiles! We need to create new projectile for this enemy. Basically you should have some base for projectile - I have created mistake when started working on this project and I've different projectiles blueprints for all weapons...it should be one with different properties.
But let's move forward. Open Orc mesh and add new socket from Bip01_L_Finger11 - name it Weapon. Create an copy of Rifle_Projectile blueprint, and open it.
Add OrcReference variable - extending from Orc_Pawn. Remember to assing your Orc_Pawn when spawning this projectile.
And here's the blueprint. At this point you should be able to change this blueprint by yourself without my help. If you can't read earlier posts!
So this is our projectile - you can create a copy of the beam and make some modifications to it as you want.
Earlier we have created muzzle flash for Rifle - copy it and add some modifications. Emitters should have lifetime - now they are spawning forever. Emitter Loop should be 1 and you should use Burst List. If you don't know what I'm saying - read earlier posts! Or watch cascade tutorials on the web - there's a lot of them. Latest from Epic can be found here.
Now if we have projectile and muzzle flash. Lets open Orc_Pawn and spawn them in custom event - BruteShoot.
Now Brute will move and shoot all the time if you have isShooting enabled in Animation Blueprint.
Shooting - Ammo and Reload functionality
Open Orc_Pawn and add some variables:
- CurrentAmmo - int: 5
- MaxAmmo - int: 5
- isShooting? - bool,
First lets make the Brute shoot. Create Begin Play event and set isShooting to true after 1-2 float delay. Remember to set isShooting in AnimationBlueprint from this Orc_Pawn bool. If you don't know how to do that - read older posts! ;)
Still in Orc_Pawn create new function : FillAmmo and in this function set isShooting to True and CurrentAmmo to Max Ammo.
Now go to Orc_Reload_Nofity we have created earlier and call FillAmmo function from the owner.
Go back to Orc_Pawn and in BruteShoot function decrease CurrentAmmo and how much ammo do we have.
Now Brute is reloading his gun. Yay.
Ragdoll
If you don't know how to create them just read older posts :) I assume that you have successfully prepared physical asset in PHAT. When we want to enable ragdoll:
- When Brute is dead,
- When critical was taken (then impulse is needed),
So we need to deal with health - read post about Golem and try to remember how we are managing health. We will do the same here.
isDead should be set to TRUE - my bad! |
And now we have nice ragdoll created in 15 minutes.
Destroy Body Parts
We will do only base functionality for this. If we want to break all of the bodies we should prepare animation blueprint and animations different. I will try to create full body destroy like fantasy skeletons later, but not now.
Which bodies we can break:
- Head,
- Arms and upper arms,
- Legs? - let's test this out,
Issue with the skin: Basically we can't break bodies in this mesh because it wasn't rigged correctly. Bones have to much influences and when I'm breaking them I can see a lot of polygons attached to them... :(
If you have prepared mesh correctly you can add impulse to the BoneName which will be bigger than "Breakeable" values in PHAT.
What you can do is to attach Heart Component to the Head. To do that you need to create new socket from Head bone. Then in Begin Play: Heart -> attach to -> mesh. So now we will get critical strikes when we hit head. Remember that there are some variables that can help: HowFarFromHeart and CritMultiply.
Blood
Blod Particle.We will use early created particle: P_body_bullet_impact. Just create a copy. Create a copy of material which particle use.
The material should be Unlit and you should connect color to Emissive Color. In your particle change color over life to green. You can change size as well.
Melee Damage
This will be simple. First let's randomly set if Brute will go near player. To do that just change MinProcentageOfRoute and Max. In Begin Play
Now create Custom Event. It should be triggered in Begin Play.
Still in Orc_Pawn create new function which will take bool as input. Function should set isShooting variable from input.
Create new Blueprint extending from Notify State. Name it Orc_Attack. Open it. Implement Begin and End functions. Begin function will set isShooting to false and End function true.
Here's example:
Add this notify to two animations: scifi_brute_gun_grenade and scifi_brute_gun_crouch_throw.
Now create new montage which will have these two animations. Create two sections: Hit_1 and Hit_2 so we can randomly play one of the animation.
And that's all.
Sounds
You should search here. Remember to convert mp3 to wave.
I won't be posting about adding sound this time - at this point you should be able to do it by yourself.
Final Effect
Due to refactoring I'm moving to new blog which can be found here: www.shootertutorial.com
See you there!
Friday, 11 July 2014
Another my game on AppStore
It won't be added to content of course, but I would like to show you a game that was shipped lately. Hellraid: The Escape was made using UE3, it's logical-puzzle-adventure game that I've worked on for couple of months. Really recommended for everyone that like puzzles and don't like F2P games. It was created almost completely using Kismet/Scripts.
You can also check Hellraid for PC which use Chrome Engine.
You can buy the game on AppStore here.
Wednesday, 2 July 2014
Prototype - Golem melee enemy
Next enemy will be slowly melee Golem from DLNK.
Specs:
- If you shoot at the center of him you will heal him,
- You need to shoot in head to make real damage,
- It will be slow,
- He will use melee damage,
Fix Pick Location Task
Open MainAI_Pawn and create new float variable: ProcentageOfRoute. Default should be 0.7.
Open PickLocation task and change random Min to ProcentageOfRoute. Thanks to that we will have option to change this functionality in other enemies.
Animations.
Import Golem from Unity - if you don't know how to do that read post about importing Sci-fi pack.
Create new Animation Blueprint from SkelMesh. Add one bool variable: IsNearPlayer. Create new blueprint - Golem_Pawn extending from MainAI_Pawn and add the same variable to it.
Now in Animation Blueprint read out this variable from Golem_Pawn
At this point reading variables from your characters should be easy. If it's not - read earlier posts! Don't be lazy!
Now we need to:
- Start moving Golem to Target,
- When we hit him - play hit animation,
- When he is near player - he need to play attack anims,
You should read this documentation about Animation Montages. So in our Anim Graph create something like this. We are blending from ArmoredGolemSpine1 bone.
Thanks to this we will be able to play our animations from anim montages.
If you right click on your animation you will be able to create Animation Montage from it. Create Animation Montages from Hit1, Hit2 and Hit3. Remember to name your slot like here (it's used in Animation Blueprint)
Create another animation montage from Attack1. Open it. Create two montage sections: Attack1 and Attack2. If you right click on Montages you can create new ones.
Drag your Attack1 animation to Attack1 montage section and do the same with Attack2 animation.
For me the dragging isn't always working so you need to keep trying. You should have something like this when everything will be ready:
So basically this montage is playing 3 animations. What I weren't able to find is to play them with random. It can be done using blueprints but I will leave it now.
Now open your Golem_Pawn and add one bool variable: isDead. Assing your mesh and your animation blueprint to the Pawn, and setup Walking Speed in CharacterMovement component. You should change SpawnManager to spawn Golem_Pawn to be able to change everything.
Create new Begin Play funcion in Golem_Pawn. We need to check where is player to change the isPlayerNear bool and run the attack animation.
And add Point Damage event to run the hit montages.
At this point Golem should walk to Target, play hit animation and attack animation when he is near.
Shooting at Golem and healing/killing him.
Open Golem skel mesh and one socket: Heal (from ArmoredGolemSpine3) and Head (from ArmoredGolemHead).
Now open MainAI_Pawn and we would need to change Crit Damage hardcoded values to be editable. So create new float variables: HowNearHeart (10), CritMultiply (2) and connect them.
Still in MainAI_Pawn point damage. Create custom Event: WasCrit and connect it where you know that there will be critical damage.
Thanks to that we can now implement some custom functionality when crit.
Open Golem_Pawn and attach Hearth to Head socket in begin play event.
So the head will move now with the socket.
Go to the Event Graph and add new WasCrit event - connect your hit animations to it like here:
Now let's move to healing him. Make sure your Heal socket is in center of his "reactor".
Go to Golem_Pawn and add new vector variable HitLocation which you will set in Take Point Damage. If we hit near the socket we won't be dealing any damage, we will heal the Golem for 10%.
Let's move to killing the Golem. Later in your Point Damage we will randomly run animation or ragdoll.
Make sure you have your ragdoll setup properly. I needed to use SetWalkSpeed because weren't able to StopMovement while it's moving from AI Tree. It's a hack, and what you should do is to prepare your AI Tree so it will be able to stop when you want.
Melee Damage
Basically in games that use melee attack you should do the traces from your weapon and check if collide with something. In our example it would be much more simpler.
We will use Custom Anim Notify to let the blueprint know that there was player hit. We have created custom anim notify earlier so you should read older posts.
Create new blueprint extending from AnimNofity. Name it EnemyAttack. Open MainAI_Pawn and create custom event, name it Attack.
Now in AnimNofity Enemy attack let's call Attack in MainAI_Pawn.
Now you just need to add EnemyAttack notify in your animations. I've added to AttackAnimMontage.
We will use this Nofity later after we add player health. For now it's done.
Adding sounds
Footsteps: here you can find some sounds I've mixed them with metal sounds. Just try to do the sound cue by yourself, and create SoundNotify in your walk animation to trigger the sound.
Attack: https://www.freesound.org/people/Matvej/sounds/157890/
Dying:
Here you can find some sounds that can fit:
https://www.freesound.org/people/Corsica_S/sounds/106576/
https://www.freesound.org/people/artfwo/sounds/63838/
https://www.freesound.org/search/?q=transformers&f=&s=score+desc&advanced=0&g=1
https://www.freesound.org/people/suonho/sounds/23695/
https://www.freesound.org/people/JarredGibb/sounds/218270/
https://www.freesound.org/people/RADIY/sounds/213147/
Hit sound: this should be helpful:
https://www.freesound.org/people/copyc4t/sounds/235740/
https://www.freesound.org/people/tigersound/sounds/9092/
https://www.freesound.org/people/SpeedY/sounds/62905/
https://www.freesound.org/people/gowers/sounds/131592/
Now in your Golem_Pawn blueprint go to WasCrit function and play your soundcue.
At this point you should be able to find the sounds you like, create sound cues and play them in animation or blueprint.
Final effect
In next post I will add another enemy.
Due to refactoring I'm moving to new blog which can be found here: www.shootertutorial.com
See you there!
Sunday, 29 June 2014
10 000 views, thanks!
I just wanted to thank you all for reading the blog! It's motivating me to to post more often. Blog has been online for couple of weeks now and Today you have break 10 000 views. I'm happy to help you guys! Don't forget liking my Facebook Page;)
Friday, 27 June 2014
Prototype - Flying, Exploding Drone
Enemy spec's:
- He flying to player,
- When he collide with player he will explode,
- He will have different SpawnPoints, (above the ground),
- He will be quick,
- He will have really low health,
- After dead he will explode and make radius damage that can hurt other enemies as well,
It sounds it will be hard but it's super easy. I will be using MainAI_Pawn as a base for this enemy, so keep that in mind and read earlier posts.
Asset
Again will use PA SciFi Enemies and Vehicles and use Drone. I've combined all of the meshes and added two bones to the engine. You can download FBX here.
After import create PhysicalAsset for the mesh. Delete all of the bodies and create own by yourself. I've used Single Convex collisions and enabled bone break. If you don't know how to do that please read earlier post.
Animation BP
Right click on your Mesh and create Animation Blueprint. Name it Drone_AnimBP. Add new float variable: Current Rotation, and in Event Graph add some value to it.
This value will be used for gear rotation. Move into Anim Graph and add couple of Modify Bones blocks. You should know how to do that if you read earlier posts ;)
That's all here.
Drone Pawn
Now create new Blueprint extending from MainAI_Pawn and name it Drone_Pawn. Assing mesh to it and set animation blueprint.
Let's do the same as earlier with Speed and Scale, you should be able to do it by yourself now. Just try it! The goal here is to have random scale and random speed. Before you start you can change Walking to Flying mode. To do that just add Begin Play event and set movement mode like here:
Thanks to this your Drone will fly now. If you want to test it out just change spawning actor in Spawn Manager to Drone_Pawn. That's all. Last thing is health this actor should have low health something like 10.
Adding Radial Damage
Go to MainAI_Pawn and create RadialDamage event. I'm copying almost everything from PointDamage.
Now in Drone_Pawn add AnyDamage event and manage health.
Now when you kill Drone it will create radial damage and make damage to all other's enemies in radius. Unreal is making the magic where if enemy is near the explosion it will get more damage.
Flying Movement.
Well I've see that MoveTo isn't working correctly with Flying Characters yet so everything connected to Flying can be thrown to trash :) We will do our own movement then.
This one is easy but blueprint is some kind of complex. I will use MoveComponentTo which needs Time to move from point X to point Y. First I need to process my Speed to move over time from point X to Y.
So every time MoveComponentTo will fire - it will move the same speed even when route length will be different. That was the hardest part, let's move.
Create new blueprint "DroneController" extending from AIController. Open your Drone_Pawn and change AIcontroller (in Defaults) from AIController to DroneController. Thanks to that our Behavior Tree won't fire on this Pawn. So it won't pick location and move to target.
Go back to content browser and create new Enum - DroneState which should have: MoveToPlayer, MovingUp and Dead.
Open drone Mesh and add two Sockets from RootBone: EndTraceSocket, TraceSocket. Don't change rotation!
We will use them for tracing.
Open Drone_Pawn add some variables:
- DroneState - which should be DroneState enum, (set it to MoveToPlayer in BeginPlay,
- Speed - float,
- OverTime - float,
You need to set Speed and Over time in Begin Play event. Just copy above's blueprint. (two images up :) )
We will create CustomTick that will fire every 0.1 seconds. In UE3 there was timers I wasn't able to find them in UE4 but we can do something like that using blueprints.
I tried to comment everything, here is the blueprint. Basically we are moving Drone to TargetPoint. If Drone is near someone he will move up and try to avoid it. If avoided - move again to TargetPoint. It's simple. The best way to learn is to try to create it by yourself - don't copy my blueprints! And - I'm not a programmer so don't trust me! :)
How it will avoid:
It's far from perfect but it's doing his job. I will polish it later: movement speed, re-tick delays, rotating mesh and engines.
Different Spawn Points
Just place couple of spawn points where you want to spawn Drones. I've created bunch of them, one higher one lower. I've renamed them so I know which one is for Drones. You need to have couple of Target Points near player as well. They should be near player so Drones will collide with him.
Now in your SpawnManager create another array for SpawnPoints and name it DroneSpawnPoints and add your spawn points to it. If you don't know how just read earlier posts.
In SpawnManager Graph just change foreach from SpawnPoints to DroneSpawnPoints. Remember to assign CurrentSpawnPoint when spawning Drone_Pawn. Here's BP for everyone that haven't read earlier posts.
Adding Explosion Effect
I will use P_Explosion_Bomb as a template I'm not sure where I found it - you will need to download some Marketplace content and search for it.
Create an copy and name it Drone_Explosion. Disable Fire and Smoke emitters. I've deleted GPU Sprites as well because they won't work on Mobile. I've changed emitters scale to be smaller.
Create another Socket base on RootBone - name it ExplodeSocket. It will be used as impulse location for small explosion.
Now go to Drone_Pawn and where are you enabling simulation add Radial Impulse.
And spawn your particles when exploding. After explosion change DroneState and before it check if it isn't Dead because you will spawn a lot of particles there!
Adding Sounds
Explosion: I've found a lot of good sounds:
http://www.freesound.org/people/Nbs%20Dark/sounds/94187/
http://www.freesound.org/people/funhouse/sounds/2514/
http://www.freesound.org/people/tcpp/sounds/132098/
http://www.freesound.org/people/animationIsaac/sounds/207322/
http://www.freesound.org/people/funhouse/sounds/2513/
http://www.freesound.org/people/lorenzosu/sounds/72069/
http://www.freesound.org/people/Sancho82/sounds/78457/
http://www.freesound.org/people/Andromadax24/sounds/169775/
Import them into UE4 and create new Sound Cue. Iv'e created something like this:
Parts on hit: I will use some of those: http://www.freesound.org/browse/tags/MetalHit/
Create another sound cue and try to experiment to get the best results.
Open your drone Physical Asset and select all bones and enable Simulation Generate Hit Events thanks to that our mesh will fire Hit event on RigidBody collision.
Now go to Drone_Pawn right click on Mesh and create Hit Event.
I'm using vector length to fire up the sound because this event will popup almost like a tick.
Engine sound: http://freesound.org/people/zippi1/sounds/17951/
Create new sound cue using this sound:
Now in your Dron_Pawn create Audio Component with this sound. It should have Auto Activate turned on. Before killing Drone you should deactivate this sound.
Attack Player
Open Drone_Pawn and create new variable which will be HitResult type. In your custom tick lets check where the player is. It would be better to use some collision events for this but this will work as well.
What you can do by yourself is to implement Drone state: AttackPlayer - when Drone is near (something around 250) he can start moving faster and rotate to player as well.
Final Effect
In next post I will add another character - this time something more humanoid;)
Subscribe to:
Posts (Atom)