Creating Gameplay Balance System – Part 2 – Patterns and Manager

In last Gameplay Balance System post I was writing about fun. Now it’s time to actually implement patterns and manager. In this tutorial you will learn how to:

  • Update enemies to communicate with patterns,
  • Fast create patterns using UE4 components,
  • Manage enemies – without destroying / spawning actors,
  • Select which pattern should be shown to player,

This will be the first tutorial where I have done Live Streaming for you guys. Let’s move forward!

This Tutorial has been created using Unreal Engine 4.10</strong>
Make sure you are working on the same version of the engine.

Live Stream

You can watch live stream where I was developing those features here:

Hierarchy Explanation

First some explanation. I will do two classes:

Pattern

This class will be responsible for storing data about enemies in the pattern. It will activate / deactivate all enemies inside the pattern. The goal here is to not Spawn / Destroy enemies during gameplay.

USEFUL TIP: Spawning actors which have animations / complicated materials cost a lot of resources and can cause glitches. It’s always better to spawn them on level start (while in loading) and manage them without need to destroy / spawn again the same enemies.

Pattern Manager

It will be responsible for choosing which pattern should be presented to player. Manager will choose the best pattern at given time and move it from pool to player viewport.

This is really simple approach which will add a lot of freedom to designing patterns.

Updating Project

It’s not the first time when I need to update earlier created functionalities. In games you will be always getting back to things you have created earlier.

Currently my enemies are Destroyed on Die. I need to have a way to communicate to enemy and tell him to activate / deactivate. In this Tutorial I will update Drone Enemy as it have physics.

IEnemies Interface

Create new Interface named IEnemies. Open it and add those two functions:

  • ActivateEnemy,
  • ResetEnemy,

It will be used to communicate with Enemy from Pattern class.

Update BP_BaseEnemy

Now open BP_BaseEnemy and Implement IEnemies Interface. Add one variable as well:

  • isActive (bool),

And one new Dispatcher:

  • OnEnemyDead,

Open Event Graph and add ActivateEnemy and ResetEnemy Interface events:

BP_BaseEnemyInterface

It should be self explanatory.

Create new custom event named EnemyCanReset:

EnemyCanReset

Now update Die function to call EnemyCanReset at the end:

DieUpdate

Update BP_Enemy_FlyingDrone

I need to update the Drone to be able to reset. This won’t be so simple as it uses physics. Open BP_Enemy_FlyingDrone and add those variables:

Var Name Var Type Default Value  Description
Loc_PA_Drone Transform
Loc_PA_BladeLeft Transform
Loc_PA_BladeRight Transform
Loc_PA_WingLeft Transform
Loc_PA_WingRight Transform

Those variables will store translation of each drone part before running physics. So we can use them later to restart the location and rotation of the parts.

Open Event Graph and add new Function named GetPartsLocationBeforePhysics:

Drone_GetPartsLocationBeforePhysics

Add another function named SetPartsLocationBeforePhysics. 

Drone_SetPartsLocationBeforePhysics

Remember to first Attach the Component and then change relative transform. This way Drone will be able to move again and will be attached to default components created earlier:

Drone_Components

Open your Event Graph again and add IEnemies Interface events (they should be visible as BaseEnemy implements it)

Drone_IEnemiesInterface

And that’s all here. I won’t be updating rest enemies yet. Just the drone.

Pattern Class

Create new Blueprint extending from Actor named Pattern. Open it and add those variables:

Var Name Var Type Default Value  Description
bWasSpawnedEarlier bool  false  Hold the information if this pattern was spawned earlier.
CustomDelayBeforeStart float 1.0 Delay for activating Pattern.
Difficulty float 0  What’s the difficulty of this pattern ( from o to 1)
PlayerDeathCount int 0 We will store how many times player dies on this Pattern. Will be used later.
AllEnemies Actor Array  Stores all enemies connected to this Pattern.
DeadEnemiesCount int 0 How many enemies were killed. Used to determine if all enemies are dead and we can activate next pattern.
AllEnemiesLocation Vector Array Stores start location of each enemy as Pattern Manager will move Patterns to and out viewport.

Add those Dispatchers:

  • OnPatternEnded,
  • OnPatternStarted,

Add new function named StartPattern:

Pattern_StartPattern

Another one named EndPattern:

Pattern_EndPattern

Next one GetAllEnemies:

Pattern_GetAllEnemies

CheckIfPatternIsFinished: (Pure)

Pattern_CheckIfPatternIsFinished

Now in your Event Graph create new Custom Event named GetEnemiesInPattern:

Pattern_EventGraph

In the Components I have added Billboard (Hidden In Game: False) and Arrow to see the Patterns.

Pattern Manager Class

Create new Float Curve named TestDifficulty:

TestDifficutyCurve

This will be our balance curve for the Patterns.

Create new Blueprint extending from Actor named PatternManager. Open it and add those variables:

Var Name Var Type Default Value  Description
AllPatterns Pattern Reference Array Stores all Patterns in Level.
CurrentPattern Pattern Reference Stores current active Pattern.
PatternsLocations Vector Array  Stores location of pattern before moving into viewport.
PatternStartLocation Vector Location in front of your player. This is location where active pattern should move.
CurrentTime float Holds current level time.
MaximumLevelTime float 60 Stores maximum level time. After this time level will end.
Difficulty Curve Float Reference TestDifficulty Stores Difficulty curve for this Manager.
NextBestPatterns Pattern Reference Array Stores chosen patterns for next activation.
CurrentTolerance float 0.1 Tolerance value to find best difficulty pattern on curve.
ManagerEnabled bool true Is manager enabled?

And one Dispatcher:

  • OnLevelEndedWithTime,

Now create new function named GetAllPatterns:

Manager_GetAllPatterns

Next one GetLevelProgress: (pure)

Manager_GetLevelProgress

It will return value from 0 to 1.

Next function GetDifficultyFromCurve: (pure)

Manager_GetDifficultyFromCurve

Next one is TryToGetBestPatterns:

  • Float Input named Tolerance,
  • Bool output named Success?
  • One Local Bool Variable named FoundSomething?

Manager_TryToGetBestPatterns

This is basically searching for patterns that wasn’t enabled earlier and theirs difficulty is nearly equal than on curve.

Now in Event Graph add Tick function:

Manager_Tick

It will make sure we stop when level time ended.

Create new Custom Event named FindPattern:

Manager_FindPattern

Here’s the place where magic happens. Binded event dispatchers comes to CurrentPatternEnded:

Manager_CurrentPatternEnded

Which will make sure current pattern will move outside the screen and start another pattern after delay.

Now add last event – Begin Play to start everything:

Manager_EventGraph

Creating Patterns

Now create new Blueprint extending from Pattern named P_Drone_00.

Add Child Actor Components:

Pattern_Components

Create more Patterns with Drone Child Actors and with different Difficulty (from 0 to 1)

Then place those patterns into your level somewhere behind player:

PlacingPatterns

Now place the Pattern Manager to the level and set your Pattern Start Location – should be location in front of the player.

Here’s the video presenting my patterns:

Last thing you would like to to is to inform GameState that Manager finished. Open GameplayGameState add one variable:

  • ManagerReference (Patter Manager Reference),

Add new custom event named OnPatternManagerAdded:

OnPatternManagerAdded

And new function named SetPatternManager:

SetPatternManager

This way your Game State will know when Pattern Manager will finish.

In PatternManager class create new function named RegisterPatternManager:

Manager_RegisterPatternManager

And just call it in Begin Play. That’s all! Hope you have learn how to create pattern managers!

Creating ShooterTutorial takes a lot of my free time.
donateIf you want you can help me out! I will use your donation to buy better assets packs and you will be added to Credits /Backers page as well. Implementing game is taking time but writing about it is taking much more effort!

 

2 Replies to “Creating Gameplay Balance System – Part 2 – Patterns and Manager”

  1. I encountered an issue where all my patterns were starting simultaneously; the drones out of view were getting activated and consequently the patterns were all ending and I was getting the “CAN’T FIND A MATCHING PATTERN MESSAGE” a bunch. Well, I was also getting drones stuck in the walls, so that was indicative of a problem as well. Going into ghost helped to see what was happening. The solution was to go into the Event Tick inside BP_BaseEnemy_FlyingDrone, where all the flying gets done, and add a Branch that checks if “IsActive” is true in between the branch checking “IsDead” and the call to Parent:Tick. I plugged True into Parent Tick and left False blank, and this seems to have solved the issue and given me what was demo’d in the video.

Leave a Reply