The FishGibble AI gets spawned using a Spawner blueprint.
The level itself is a test level, and contains some production assets, but the characters (fish) are simply place holders while the actual fish characters are being created.
When an enemy AI sees you, or starts hunting you, the screen will flash yellow.
Video detailing some of the process here:
The AI will guard a location, and swim around randomly at various speeds, near their guard location/post and every so often use any of their non destructive abilities ( if they have any ).
Once they detect they are about to collide with something they will try and swim to another location, within their guard sphere.
Enemy AI constantly search for any player characters, and once they found one, they will broadcast it’s prey to all nearby enemies, which in turn will do the same ( broadcast the location of their prey to nearby enemies ), and start hunting you. When within strike range, you will start taking damage.
Once line of sight is broken, through rocks, foliage, walls, moving objects etc.. they will search for you near the last location they saw you for a short time, and then return to their posts.
Some AI are friendly, and do not attack you, and players are able to interact with them.
Some more images of the AI, and interaction with them.
AI Enenmy Spawner Blueprint
The enemy AI are spawned by the SpawnEnemyAIBP Blueprint which derives from a custom C++ class called FGSpawnActor.
Spawners are responsible for spawning a certain amount of actors, within a certain time, within a certain location, as long as the player is within a certain range of the spawner, and the spawner itself is active. Spawners may be activated through receiving/completing quest objectives, or simply by manually setting their in game visibility.
Spawners maintain their list of actors, so if an actor is no longer active, or pending kill, it will be removed from the spawned actor list.
Spawners have instanced based settings that allow them to spawn after receiving/completing a specific Quest/Objective.
Spawners may spawn and instantiate from multiple actor classes. And is not limited to a single actor class to spawn.
From the Spawner tick function, the spawner decides when to spawn, and when it is deemed to spawn something, it will invoke the CheckSpawn function.
The CheckSpawn function will then clean up any pendingkill actors from it’s list of spawned actors, and then decide on a random actor class to spawn by calling the Blueprint event SpawnActorOfClass.
It will also only spawn actors, if the player is within a certain distance from the spawner for performance.
The SpawnActorOfClass Blueprint event will then decide to spawn the request actor, based on a few factors, like ‘spawner active’ or Quest/Objective given ( by passing a lower number objective index, the objective completed is checked vs objective given, objective index 0 signifies ‘quest given’ ) making it very flexible.
After spawning the actor, the blueprint will invoke the ‘ActorHasSpawned’ C++ function, to give the game a change to do any housekeeping, like storing a reference to the spawned actor.
So the Blueprint and C++ communicate through BP events an C++ functions, including passing parameters.
ThirpersonCharacter / AI Character
The AI actor class the spawner instantiates is called the ThirdPersonCharacter blueprint class.
Looking at the project settings, the game mode set for this game is pointing to the custom class ‘FishGibbleUE4GameMode’
This game mode specifies the ThirdPersonCharacter, as the main player character. This means that the same class is being used for the main player, and for AI. this is because players can unlock a possession skill from the skill tree during the course of the game, and allow them to completely possess an enemy AI for a duration, including using all the skills that the enemy AI has, and temporarily inherit their skill level too.
The ThirdPersonCharacter blueprint class, derives from the FishGibbleUE4Character C++ class, and has various settings pertaining to AI.
The character asset itself, is a place holder and will be replaced with a proper skinned mesh as the art assets are completed.
When a spawner places an instance of the character in the game, there are rules in place that will ensure the game knows if your are trying to place an AI, or player character in the game.
This is done by setting up the ‘Pawn’ section of the blueprint to the following:
Auto Possess Player: Disabled
Auto Possess AI: Placed in World or Spawned
AI Controller Class: AIController
In this game, I do not use the AIController class explicitly, but a value must be specified here for the above settings to work, so that when a character is spawned, it will become an AI character, and the player will not auto possess it.
The ThirdPersonCharacter derives from the FishGibbleUE4Character c++ class.
From the constructor, various property defaults are done *a lot of these are overridden in the derived Blueprint itself.
Including character and AI defaults.
The beginplay function decides if this is the main character or not, after the actor has been spawned and placed in game.
The tick function is responsible for calling various AI functions.
AIChecks: Performs AI/character swopping and performance code.
AIBehaviour: Uses a state machine to manage the various AI states.
AI States currently include:
- Guarding – guard an area
- Hunting – hunt for prey
- Hovering – hover around an area
This function is responsible for determining if the character is a player, or AI, as players can possess AI, these checks are not done every single frame, as that would be computationally expensive, and slow the game down, it is done, like most checks, in a cycle over time.
It is also responsible for performance optimizations like visibility of the mesh, and culling, which will stop rendering, and expensive computations like physics checks, movement etc.. if the character is too far away.
The character will still move around but not be visible within a certain range, and then outside of that range, will be completely disabled, allowing for hundreds of AI characters to be present in a particular level.
The AIChecks function is also responsible for determining if the it is going to hit something, if it were to travel along it’s current path, by doing a SweepSingleByChannel collision check, and using a sphere as a shape, thus it will perform a swept sphere check, by creating a capsule of a certain size, for a certain amount in front of the AI, to check what would be hit, if it were to continue on it’s path.
The sphere radius of 70 is derived from the ThirdPersonCharacter blueprint, by including the Capsule half height, and Capsule Radius ( 45 ) settings. The sphere check radius is 70.
The next function the tick event calls every frame is AIBehaviour, this function is responsible for deciding which state the AI should be in, using the rules of the game.
The AIBehaviour will invoke the RandomAIBehaviour function at random times.
It will also invoke the GuardBehaviour and HuntBehaviour function every tick.
RandomAIBehaviour will simply force the character to look for a new guard position, if it was guarding.
GuardBehaviour is a relatively simple function that moves the AI toward a goal, at a certain speed, and will find a new spot to move to, once it’s reached it’s destination, or enough time has passed and it decided to go to a new spot. It also invokes AIVision if the AI, is set to hunt for prey.
The movement itself is done by calling the AIMoveToFocalPoint function.
AIMoveToFocalPoint simply calls the engine’s AddMovementInput function, to move the character in a particular direction, at a specific speed. This function is called every frame, and uses the DeltaSeconds to move small increments at a time.
AIVision is invoked every frame while guarding, and hunting for prey. This creates a ‘cone of vision’ and determines if any players are inside of it. If they are, it will pick the closest one with an unobstructed view, and move toward it, by setting the character up as the ‘FocalCharacter‘.
The enemy vision may be debugged by setting the ‘Show AI Vision‘ in the ThirdPersonCharaterBlueprint.
Here is an example of the AI vision in debug mode. The faint yellow lines indicate the cone of vision.
From the AIVision function, if an enemy is detected, the AI will invoke the AIBroadcastPrey function, this will find any close by enemy AI, and tell them about the prey, they will in turn, tell others around them, within a specific distance, about the prey, meaning once you get spotted, they start swarming toward you if they are close together.
This function is invoked from the GuardBehaviour function, and is responsible for hunting/chasing the ‘FocalCharcater‘ while the enemy has line of sight, this is done by calling the LineOfSight function.
It is also responsible for striking the FocalCharacter, if it is within range, causing damage. If the prey is lost, the GuardBehvaiour will resume, but from the last known location of the prey, after a while, the AI will return to it’s original guard post.
This function is called while hunting/chasing the prey. This simply casts a swept sphere from the AI, to the prey, for a small capsule radius of 35 units, and checking the hits collected during the sweep, anything that is not the character class or any ammo type is considered, meaning the environment, rocks or any blocking physics volumes will break the line of sight.
This is for interactive AI, and allows them to hover in place.