Top Down Stealth Toolkit Tutorial: How to control the AI Perception model for AI agents

The following information is based on the v2.0 edition of Top Down Stealth Toolkit & hence may not remain entirely relevant in later versions. For more information about the toolkit, check out the official support thread in the Unreal Engine forums:

The Top Down Stealth Toolkit uses a custom Perception system to evaluate potential threats for the AI agents. It's user defined properties can all be edited through the component details panel from the owning blueprint, thus facilitating creation of different threat perception models for different types of AI agents. This tutorial will go over the basic parameters that control the working of this system.

Visual Perception Data:

1. IsVisualPerceptionEnabled?: Determines if the agent can use Visual Perception to perceive stimuli.
2. Vision Range: Determines the direct line of sight range.
3. HalfVisionAngle: Determines the half angle for the agent's cone of vision.

Aural Perception Data:

1. IsAuralPerceptionEnabled?: Determines if the agent can use Aural Perception to perceive stimuli.
2. HearingRange: Controls the maximum distance at which a sound of default loudness 1.0 (controlled through the 'PerceptionRangeModifier' parameter of interest stimuli: Breakdown of Stimulus Parameters) can be perceived by the agent.

Intuitive Perception Data:

1. IsIntuitivePerceptionEnabled?: Determines if the agent can use Intuitive Perception to perceive stimuli.

Motion Perception Data:

1. IsMotionPerceptionEnabled?: Determines if the agent can use Motion Perception to perceive a stimuli.
2. DetectionRange: Determines the maximum range at which stimuli can be sensed.
3. DetectionCounter: A counter that decides if the agent should respond to the stimulus [Used because this is an indirect form of perception]
4. CounterIncrementPerCycle: Controls the rate at which the Detection Counter increases if the stimulus is in range.
5. CounterDecrementPerCycle: Controls the rate at which the Detection Counter decreases once the stimulus goes out of range.
6. CriticalDetectionValue: Determines the threshold point for Detection Counter, at which the agent responds to the stimulus.
7. DisplayAlertnessLevel?: Determines if changes in the Detection Counter value need to be displayed in the game space.

Can Perceive Interests?: Determines if the Agent can perceive Interest Stimuli. If set to false, only Target stimuli will be perceivable.

Note: The Perception system has no awareness about it's owning actor & uses a custom interface to receive & send messages. So if you're using a custom AI agent, make sure that the owner class implements the BPI_SensorySystem interface & it's functions. For reference, check out the implementation of the interface functions in BP_PatrolGuard_Parent.

Top Down Stealth Toolkit Tutorial: How to create a new custom Interest Stimulus

The following information is based on the v2.0 edition of Top Down Stealth Toolkit & hence may not remain entirely relevant in later versions. For more information about the toolkit, check out the official support thread in the Unreal Engine forums:]

The v2.0 update for Top Down Stealth Toolkit introduced a dedicated stimulus driven AI perception system. This tutorial will go over the process of using the aforementioned system to create a new Interest stimulus from scratch.

The base attributes for Interest stimuli are controlled through the 'InterestStimulusDataArray' in BP_AISensoryManager class. Each element of the struct array contains details about a specific type of Interest & hence provide an avenue for easily customizing it's properties. Before going into the actual process of creating a new Interest, I'll provide a brief description of the various parameters that control that control these stimuli.

1. InterestType: Determines the type of Interest associated with the array element.

2. PerceptionType: Determines the AI perception model that can detect this Interest.

3. ThreatClass: Determines the priority level of an Interest when it comes to override requests. For example, an Interest of lower threat class will not override one of higher threat class, thus making sure that the AI retains focus on the stimuli based on their relative importance. By default, all Interests have a threat class level of 1.

4. PerceivedThreatValue: Maintains a normalized [0.0 to 1.0] value of the threat rating of an Interest as perceived by AI agents. Higher values of this parameter will make AI bots go directly into a high alert level state. Within a single cycle of sensory evaluation, Interests with higher value of this parameter within a threat class, are evaluated first to ensure that the AI responds to the most immediate threat.

5. PerceptionRangeModifier: Controls the range at which an Interest can be perceived by adding a distance modifier to the agent's perception checks. For example, Alarm & Gunshot noises have a value of 2.0, thus ensuring that an AI agent possessing a hearing range of 500 m can perceive these stimuli up to double the said distance.

6. PerformRangeTestToInterestCreator: Determines if AI perception tests should conduct distance checks against the actual Interest location, or the entity that created it. For example, perception checks for alarm noises are conducted against the actual source of the noise itself, even though the Interest location would be set as the location of the entity that triggered the alarm.

7. TrackAlertedAgents?: Determines if the Interest object should keep track of agents that have been alerted to it's presence.

8. UseInterestCreatorLocation?: Controls whether the AI agents that detected this stimulus move towards the Interest location or the actor that created it.

9. AutoDeactivate?: Controls the active lifespan of the Interest. For example, noise stimuli have this parameter turned on, thus making them relevant only for a single evaluation cycle.

10. IsInteractive?: Determines if the AI agents can interact with the Interest. If turned off, the AI bots will only investigate the source location.

11. InteractionModel: Controls the manner in which an agent interacts with an interactive Interest. For example, patrol guards will use the 'Reactivate' interaction model to wake up any incapacitated allies they may come across.

12. SortedPriorityOrder: This parameter is set automatically at the start of a game based on the threat class & perceived threat value of the Interest. Ensures that AI Sensory Manager evaluates the Interests with higher priority order before moving on to the rest.

Now in order to create a new Interest, first add a new entry to the enum 'EInterestStimulusType'. All that's left is to add an element to the InterestTypeDataArray for this new type, & assign the parameters mentioned above as per the requirements.

Top Down Stealth Toolkit Basics: AI Perception

The v2.0 update for Top Down Stealth Toolkit introduced a custom component driven AI Perception system tailored specifically for implementation in Stealth games. This system uses a combination of four different perception models to evaluate threats based on the new Stimulus model introduced in the update.

Perception Models:

1. Visual Perception: Using a combination of distance, angular, & line trace checks, the Visual Perception enables an AI agent to detect stimuli within it's direct line of sight range. It is capable for sensing Target stimuli as well as certain types of Interest stimuli like Incapacitated & Defunct allies.

2. Aural Perception: The Aural Perception enables an AI agent to perceive & track noises created in the vicinity. It factors in the Loudness of a noise while performing the distance check operation, in order to gauge the relevance of the stimulus. This ensures that louder noises can potentially be heard by an agent, even if it was created outside the default hearing threshold.

3. Intuitive Perception: The Intuitive Perception model is used by AI agents to evaluate stimuli based on their memory, thus negating the need to do any form of range checks. For example, a target that has evaded a Patrol Guard's line of sight can trigger the creation of a Missing Suspect stimulus using it's memory about the target's last seen location, which can then be perceived through this system with very minimal search costs.

4. Motion Perception: Unlike the other perception models, the Motion Perception is used to evaluate stimuli that have not been directly perceived by the agent. An example of this would be a stimulus created by an entity located in close proximity to an agent, but not necessarily within it's direct field of vision. As a result, this system uses a dedicated alert meter to make sure that the agent responds to a perceived stimulus only if it stays within range for certain period of time.

All or any of these systems can be modified or turned off from the owning class, thus facilitating creation of different types of perception behavior among two types of agents like say, a Patrol Guard & a Surveillance Camera.

Top Down Stealth Toolkit Basics: Stimulus Types

The v2.0 update for Top Down Stealth Toolkit introduces a new Stimulus generation system that will enable the users to easily customize & add new types of perceivable events for the AI agents. Inspired by the AI Threat Detection system used in the 2D Stealth game - Mark of the Ninja, the stimuli are primarily divided into two categories: Targets & Interests.

The Target Stimuli represent the highest level of threats that can be perceived by the enemy AI. Once an agent has acquired a target, it will focus all it's attention on the said stimulus, with complete disregard for anything else until the target actor manages to evade it's line of sight. The Player Character is an example of an entity that registers itself as a target stimulus.

The Interest Stimuli on the other hand, represent cases that require some level of preemptive investigation before an agent can make further decisions. These are more varied due to the multitude of attributes that define them (more on this to be added in a later post), & hence split into the following categories:

  1. Incapacitated Ally: AI agents that get incapacitated at any point of time will register itself as an Incapacitated Ally. These interests will continue to exist for as long as the agent remains in the said state. However, since they support interaction by other agents, the stimulus creator can be brought back to an operational level, at which point the interest will be set to a deactivated state.
  2. Defunct Ally: Created when an agent gets terminated & will remain an active stimulus till the end of the level. These interests keep track of agents that have been alerted to it's presence & hence ensures that a single agent will respond to it only once.
  3. Alarm Noise: Created whenever an alarm has been raised by any entity. Has a very short lifespan, but can put agents on a high alert state.
  4. Gunshot Noise: Created when a non-silenced weapon is fired. Works similar to the Alarm Noise interests at a functional level.
  5. Missing Suspect: Created by AI bots based on the their memory about the last seen location of a target. Can only be perceived by the agent that registered the stimulus, but requires no form of range checks.
  6. Footstep Noise: Noises created by the player character's footsteps can be perceived by AI agents through these type of interests. Has a very short lifespan, & generally perceived as a medium level threat.
  7. Whistle Noise: Functions similar to the Footstep Noise interests, but created when an entity uses the Whistle.
  8. Peripheral Motion: Represents all entities that can be perceived by AI agents based on the proximity level. Unlike other interests, this stimulus will remain active throughout the lifespan of the actor responsible for creating it. However, owing to the indirect nature of perception used to detect this form of stimulus, the AI bots will react only if the stimulus creator remains in close proximity for a certain period of time.

Tower Defense Starter Kit Tutorial: How to add custom Tower Abilities

[The following information is based on the v1.6.3 edition of Tower Defense Starter Kit & hence may not remain entirely relevant in later versions. For more information about the toolkit, check out the official support thread in the Unreal Engine forums:]

The Tower Defense Starter Kit features two Tower Abilities (Overdrive & Repair) than can be added to the towers in order to provide the player with an additional element of control over the gameplay. This tutorial will go over the steps involved in the creation of a new Tower Ability & it's integration with the existing system.

Before delving into the matter of actual implementation, I think it would be best to understand that there are generally two types of dynamically driven abilities: sustained abilities that modify the functioning of the targeted actor over a brief span of time, & momentary abilities that cause a certain change within the system for just an instant of time. Overdrive & Repair are sustained abilities & hence I would like to show the creation of a momentary Shockwave ability with this tutorial. 

1. Create a duplicate blueprint based off of the 'BPC_OverdriveAbility' class. This will provide you with a base template for the new ability without having to start from scratch. At this step of the tutorial, there is a slight difference based on which direction you want to take.

If you plan to create an ability with sustained effects, there is no need to make any changes to the default parameters right now.

On the other hand, if you want to have a momentary ability, then delete the following variables: RemainingTime, AbilityDurationDisplayUpdateTimer, AbilityDurationDisplayUpdateTimerInterval, AbilityStatusBarFillColor, & AbilityDuration. Also make sure to delete all instances of the ability duration timer within the component.

2. The next step is to modify the following text variables to suit the description of your new ability: AbilityName, AbilityNameAbrreviation, AbilityDescription, HUDStatName_CoreFunction, & HUDStatsName_LimitingFactor. These variables determine the information displayed about the ability in the HUD.

3. Now create the variables that would be required for the functioning of your Tower Ability. For example, I'm going to add a couple of float variables named 'ShockwaveDamage' & 'ShockwaveRadius' [see sample screenshot below]. For a very basic shockwave ability that does damage to all enemy units in it's range, that should be enough. For now, that's all there is do within the ability component class. We'll come back later to write down the actual implementation once the remaining factors are taken care of.

4. Open up the enum 'ETowerFunctions' & add a new entry with the name of your new Tower Ability.

5. Now that we have the new enum entry & component set up, you can add a new ability to the list maintained in the 'BP_GameInstance' blueprint. To do this, add a new element to the Tower Functions Array & make the following changes to the default values: set the 'FunctionType' as the new enum value, & the 'AbilityComponent' as the custom component; the 'AbilityCost' can be set to any arbitrary non-negative value; under the 'CompatibleTowers' list, add all towers that should be able to use the new ability; & set the 'Unlocked?' parameter to true.

Here is a sample screenshot for my Shockwave ability entry:

6. The next step is to integrate the new Tower Ability into the system through the 'BPI_TowerAbilities' interface. You will have to add new functions to handle the following cases: to add the new ability component to the tower actor, to activate the ability, & to deactivate the ability. The last two functions are only necessary of it's a sustained ability. If you check out the interface functions list, you will notice that both overdrive & repair abilities have these two functions to handle it's activation/deactivation. Since I'm creating a single fire ability, only the first function is required as shown below:

7. Now head over to the 'BP_Tower_Parent' blueprint & implement the newly created interface functions. In order to add an ability component, just copy the same code from the equivalent interface function for the overdrive ability & replace the Add Component node (check screenshot below) with the node to add the new Tower Ability component. With this function set up, you should be able to request a call to activate the ability from other classes that interact directly with the player. In case of sustained abilities, make sure to implement the Activate/Deactivate functions as well. Basically these functions are used to modify/reset any changes made to the Tower's attributes by the component. You can check out the implementation for Overdrive/Repair abilities as a reference, if there are any doubts.

8. Open the 'Widget_TowerFunctionsButton' class & call the previously added interface function for adding the custom ability component & connect it to the switch case output for the associated entry as shown below:

Also make the following changes within the 'UpdateTowerFunctionWidgetState' function:

With these connections set up, the player interactions with the tower function button for the new ability will be able to connect with the tower in order to pass on the request.

9. Before going into the implementation of the ability, there's one more thing to be taken care of & that is to add the code to display information about it through the stats UI element when the mouse hovers over the tower function button. This is handled through the 'GetTowerAbilityClassInformation' function in the 'Widget_TargetInformation' class. Just copy the nodes connected to the overdrive switch case, & paste it elsewhere. Now swap out the cast with a cast to your custom ability component & connect it to the corresponding switch case output as shown below:

10. The final step is to head back to the tower ability component & write down the actual implementation for your ability. In my case, I'm going to add an apply radial damage node & connect it to the begin play event to do damage to all enemy units around the tower.

With that, we've come to the end of the tutorial & you should have your own version of tower ability ready to go. If anyone has any doubts regarding the workflow, feel free to post in the comments section.

Unreal Engine Diaries #12

1. Blueprint function libraries cannot be accessed from an Object class.

2. If you spawn an 'Actor' using Spawn Actor from Class function, it's transform (or the individual sub components like location, rotation, & scale) cannot be modified.

3. The 'Get Game User Settings' node can be used to get the local machine settings like screen resolution, texture quality, etc, but this function returns the settings data from the memory & not from a permanent storage location like the hard disk. This means that if the player had used 'Save Settings' prior to this function call during the same instance of the game, it would not return the saved information.

4. The 'Load Settings' & 'Save Settings' function [accessed through the Get Game User Settings node] loads/saves settings data from/to the disk. While saving new data, it does not apply these settings parameters to the game. So it's generally used in scenarios where the player has to restart the game to see the desired effect.

5. The 'Apply Settings' function [again accessed through the Get Game User Settings node] on the other hand, takes the active game user settings from the memory, applies these to the game, & saves the information in a permanent storage location.

Top Down Stealth Toolkit Tutorial: How to modify the size of noise pulse emitters

[The following information is based on the v1.4.1 edition of Top Down Stealth Toolkit & hence may not remain entirely relevant in later versions. For more information about the toolkit, check out the official support thread in the Unreal Engine forums:]

The noise pulse emitter's radius is indirectly dependent on two user defined factors: one being the AI bot's hearing sense radius, & the other factoring in the loudness of the noise itself. By default, the patrol bots have a hearing sense radius 'r' of 500 units. This basically means that a noise event with a loudness value of 'l' (default = 1.0) can be heard by the AI bot up to a maximum distance of 'r*l' units. For example, the footstep noise with a loudness value of 1.0 can be heard up to 500 units, while a different custom noise event with a loudness of 2.0 could be heard from a distance of 1000 units. This maximum distance corresponds to the maximum size of the pulse particle effect.

In order to demonstrate how to edit this value, I'm going to increase the AI hearing sense radius to 800 units & have the same loudness of 1.0 units for the noise event. So first we have to edit the hearing sense radius from the AI Perception component of the Patrol Bot parent class as shown below:

Since the footstep noise loudness is 1.0, I'm not going to edit it. So now we open up the 'P_FootStepPulse' particle system asset & make the following changes:

1. Within the 'Initial Size' module, set the Start Size value to be (1.0, 1.0, 1.0) [the already existing value works as well, but this is easier to understand]

2. Now within the 'Size by Life' module, set the Life Multiplier out value for point 1 to (1600.0, 1600.0, 1.0). This value is basically a multiplier for the initial size value. Point 0 corresponds to the starting value & hence we multiply it's size with the default (1.0, 1.0, 1.0) & while point 1 (which corresponds to final moment of the particle lifespan) multiplies the x & y values by 1600 units thus forming a circular ring of radius 800 units.

With that, you should be able to control the radius of the noise pulse.

FPS Tower Defense Toolkit Basics: Holographic Tower Constructor

[The following information is based on the v2.1 edition of FPS Tower Defense Toolkit & hence may not remain entirely relevant in later versions. For more information about the toolkit, check out the official support thread in the Unreal Engine forums:]

The Holographic Tower Constructor represents the part of the Holographic Tower Display system that displays Holographic models of the tower designated by the player for construction. The Holograms are created & updated at run time through the 'BPC_HolographicTowerDisplay' component (attached to the player character) using information specified in the 'Holo Constructor Data' array, located within the Tower Manager. Listed below is a brief explanation of the different parameters that drive the Tower Constructor:

- The 'TowerType' enum identifies the data associated with the tower model selected by the player for construction.

- The 'Tower' parameter determines the base mesh (same as the mesh model for the actual tower) used to create the tower hologram.

- The 'LocationOffset_GridCellToTower' controls the translational offset of the tower hologram relative to the location of the focused grid cell.

- The 'UsesGridCellOrientation?' flag decides if the hologram will be partially or fully aligned with the grid generator. For example, the Trap holograms have this value set to true, since their spatial orientation completely match that of the underlying grid generators. The remaining towers (including the Tower Base) on the other hand, have this value set to false, since they only partially align (along the XY plane) with the grid generator.

- The 'HasTurretAttachment?' flag determines if the tower has a turret attached to it.

- The 'TurretAttachment' determines the mesh (same as the turret mesh model for the actual tower) for holographic display of the Turret (if any).

- The 'LocationOffset_TowerToTurretAttachment' controls the translational offset of the turret mesh hologram relative to the tower mesh hologram.

- The 'RotationOffset_TowerToTurretAttachment' controls the rotational offset of the turret mesh hologram relative to the tower mesh hologram.

- The 'DisplayTowerRange?' flag determines if the constructor needs to display the effective range of the tower.

- The 'LocationOffset_TowerToTowerCenter' stores the offset between the tower location & the central point of the tower mesh (specified based on the said offset in the actual tower class).

- The 'AffectsNavMesh?' determines if the placement of the tower affects the navigation mesh. This flag is set to true for the Tower Bases since the AI bots will have to path around them. As a result, the holograms for Tower Bases keep updating their color to convey the availability of valid navigational paths based on the tower placement location.

The Hologram itself will be displayed as long as the selected tower model can be created at the focused location. However, based on the construction pre-requisites like availability of tower resources & valid navigational paths, the hologram may change it's color to reflect the feasibility of constructing a tower of the selected variety under the given conditions.

Tower Defense Starter Kit Tutorial: How to create custom Towers

The following information is based on the v1.6 edition of Tower Defense Starter Kit & hence may not remain entirely relevant in later versions. For more information about the toolkit, check out the official support thread in the Unreal Engine forums:]

The Tower Defense Starter Kit comes equipped with seven types of Tower classes that all derive from the parent blueprint 'BP_Tower_Parent'. As the name suggests, this tutorial goes over the process of adding your own new customized Towers into the mix.

1. First we're going to have to create a new Tower class. To keep things simple, I'm just going to duplicate one of the existing Tower classes named 'BP_ShockwaveTower' & name it 'BP_CustomShockwaveTower'.

If you want to create a tower from scratch, you can do so by creating a child class derived from the 'BP_Tower_Parent' class. The only extra step involved is the setting of static mesh/materials for the 'Tower' static mesh component as shown below:

2. Now we need to make an entry for the same in the 'ETowerType' enumeration. I'm just going to name it Custom Shockwave.

3. The next step in the process is to provide the default stats for our new Tower. Since the toolkit uses a data driven approach to Tower creation, all default user defined attributes for the Towers are specified within the Tower Data Array (in BP_GameInstance class). Again I'm going to duplicate the array element for Shockwave Tower, & change it's 'SpawnClass' & 'TowerType' attributes to 'BP_CustomShockwaveTower' & 'Custom Shockwave' respectively.

The remaining attributes can all be changed based on the specific requirements for the tower & tooltips have been provided to specify the modifications that each attribute brings to the table. Here is a sample screenshot for the custom Shockwave Tower:

4. Now that the default attributes are set up, we need to register the new Tower for Tower Functions which includes Upgrades, Abilities, etc. The 'Tower Functions Array' in the'BP_GameInstance' class determines the functions that are available to the different towers.

To avail all the functions for our new Tower, we just add the associated enum value to the 'Compatible Towers' list for each function as shown below:

5. All that's left now is to make the necessary node connections that rely on the ETowerType enum. I've marked all of them in the screenshots below. Just connect the output nodes from the Custom Shockwave switch case to the designated input nodes as shown in the screenshots & the new tower should be good to go.




With that, we have covered the basic steps involved in creating a basic Tower class. If you have any queries about the procedure, feel free to contact me through the comments section or the aforementioned forum support thread for the Tower Defense Starter Kit.