I’ve been working on top-down angled action idea. For this indie project, I wanted to find safe cover locations for enemies to hide (crouch) behind and shoot from.
On my first attempt at a solution, I tried using the unreal EQS system, then my own implementation (picking points, raycasting to see if they hit an object at a crouching level, and raycast to see the point was clear at gunfire level.
This produced ‘okay’ results. But it presented a few problems. I’d have to implement additional checks for enemy sizes. Implement additional traces to checks if a spot was reserved/occupied. It also would miss spots (as shown by the red spheres) depending on how the checkpoints lined up. I’m also testing a lot of locations.
This solution just had too many issues, so I decided to take a different approach.
My second solution, add a simple box collider to valid cover spots, on a cover only trace channel. To accomplish this, I extended the UBoxComponent class creating UAreaCoverMarker and implementing a GetCoverLocations function. This function takes two parameters, the player’s location, requesting enemies width and returns a TArray of structs that contain each cover points FNavLocation and their ForwardVector (vector pointing towards the cover object.)
To discover the best hiding side, I calculate the colliders top for vertices, and sorted them by distance from the player.
A = Furthest vert from player
B = 2nd Furthest from player
C = 3rd Furthest from player
D = Closest to player
AB will always be the furthest side from the player. The direction of A-C will point away from the BoxCollider and towards the area, we want to test for cover space.
Step 1: Taking the enemies width I divided the length of AB, to calculate how many hiding slots could potentially exist on this line.
Step 2: Using the direction A-C I located the starting and ending test points.
StartPoint = Move A in the direction of A-C by 1/2 the enemies requested width.
EndPoint = Move B in the direction of A-C by 1/2 the enemies requested width.
Step 3: Move the StartPoint 1/2 the distance of enemy width towards B. (this is the center of our first test.
Step 4: Check if this spot has a collider on the ReservedArea channel below it towards the ground. If not proceed.
Step 5: Check if we can cast this point onto navmesh (setup a query tolerance.) if we can the point is valid!
Step 6: advance this test point by the enemies width towards the EndPoint, repeat for the number of hiding slots calculated at Step 1.
As you can see below, this doesn’t exactly work great for large rectangles or cubes. Depending on the player’s location, sometimes enemies should hide behind AC too!
To fix this, let’s turn to the late great Heron and find the side AC. If the Triangle PlayerAC has a greater area than PlayerAB, include AC in the solution.
Step 7: Repeat Step 2 – 6 for the line AC, if the area of triangle PAC > area PAB
PAC area < PAB area