This document discusses path finding experiments for units and squads in a tactical RPG game. It covers setting up a grid-based movement system using Apex Path, handling formation movement for squads, and overcoming challenges like units getting stuck or moving to blocked areas. Custom scripts were created to select units and squads, control their movement and formation, and position them correctly on different terrain like slopes.
Historica Fantasia, Development Blog 07, PathFindingExperiment
1. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 1
By Matumit Sombunjaroen V1.0 2017/05/03
Historica Fantasia Dev Blog
Chapter7:
Path Finding Experiment
2. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 2
Tools Used
To stick with the
More Mechanical and Less Façade Principle,
+ It was proven in previous Test that this can be done,
While being command as a Squad,
Each Unit will have their own position coordinate
Apex Path is used,
because it has Apex Steer as add on –
Which can be use to solve the
complex calculation of Formative Movement
3. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 3
Unit and Squad Dimension
By Default, Unity’s Physical scale is 1unit = 1meter
Assuming that a Tall Character would be 2m tall,
To arrange Formative Defense,
Minimal Distance to each other should be 1.5m
The Squad will have 5x5 Position Slots
inside a 10mx10m Squad
1.5M
2M
4*1.5 interval + 2*1.5 Proximity
= 9.5m
~ 5Radius ~ 10Diameter
5. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 5
Overall Structure
A
B
C
A Stage will contain Several Areas
that overlap each other at a certain point
As long as there is no Visibility Obstruction,
it is possible to do Range Attack across the Area
Assume that this is a chasm,
Squads on both Side can Shoot each other
6. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 6
Area Size
20m 60m
By average,
a squad should be able to move up to 20m/command
or 30m for Fast Squad
To Provide substantial area for Strategic Decisions,
It should take 3 Commands to
be able to move across the Area
As such, an average Area
should be at least 80m in either Width or Length
7. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 7
Path Width
Several Location will contain Narrow Paths,
Such as a Cliff Path
Forcing the Squad to march in Column formation
This will provide Strategic Advantages/Disadvantages
for various circumstances
Such as ambushing exposed weak Unit
The Needed Script is provided in Apex Steer
4m
>12m
8m
8. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 8
Height Elevation
Each Area can have 2 or more Floors,
with 10m cut per major elevation
It is possible to move under another floor,
such as a Castle Gate & Wall or an Aqueduct
10m
2nd FL Grid
Move Beneath Arch Going up the Floor
9. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 9
Dynamic Obstacles
Obstacles: Rocks, Walls, etc
Block Line of Sight, Movement Obstacle,
Can be destroy with Siege Attacks
Burnable Obstacle: Buildings, Trees, etc
Block Line of Sight, Movement Obstacle,
Can be destroy with Siege Attacks
Can be burned with Fire Attacks
10. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 10
PathFinder Unit
Squad with PathFinder can enter other Areas via
Secret Paths that are usually inaccessible
Need to research a Script to limit Path
based on Unit in a Squad
12. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 12
Default Component
By Adding [Navigating Unit with Selection] to the Unit
The needed minimum Components will be automatically added.
By Default, it uses Rectangle Selection on Unit, common in many RTS Game.
We want to change this control Scheme to
All Units in the same Squad will got pick when one is clicked.
Inside GameWorld, Delete the Following,
[SelectionRect(Clone)] Transform
[InputReceiverBasic] Component
Then Add a New Customize Unit Selection Component,
Name this HF_UnitSelection
13. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 13
Unit Selection
Apex has an InputController provided,
and they should not be messed with,
So I created an inherited class to work on.
This Script will Select a Unit when you Click on it,
And will Deselect only when you Clicked another Unit.
The Key is to get an IUnitFacade from Selection,
it can be access via GetUnitFacade(); on the Transform
then put it in GameServices.gameStateManager.unitSelection
Then, call the Function from HF_UnitSelection
FIX Renamed to
PathFindingController
FIX Relocated to
SquadManager
14. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 14
Group Selection Script
Once all Unit got Selected,
use unitSelection.AssignGroup(index);
to Assign Units to a Group
To Select,
use UnitSelection.SelectGroup(index);
15. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 15
Squad Selection Structure
Apex has this really confusing Control Schematics,
So, instead of trying to figure out how to Utilize them,
I decided to create something that I’m more comfortable with.
Basically, SquadManager will Control Squads,
then Squads will Control Units
All Player Inputs are issued via InputManager
And Due to how Apex’s Main Control Work,
Only SquadManager will have access to
PathFindingController to avoid future confusion.
After Clicking on the Unit,
it will go to SquadManager to tell which Squad it’s from
and pass all Units in the Squad to PathFindingController
Squad
Manager
Squads
Units
Input
Controller
//
Renamed to
PathFinding
Controller
Input
Manager
17. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 17
Basic Movement Script
Access PathFindingController, and call SetDestination() Function
To designate Target Location
Note: This control only work for Player,
A Custom function is needed for Enemy AI
If addWayPoint is true, another Waypoint will be added instead
-------------------------------------
Once issued, the Unit will Start Moving by default
On SelectedUnits, call Resume() and Wait() to Start or Stop Moving
If Stop() is used, Path Data will be terminated
18. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 18
Movement Speed
Originally, the speed will be controlled by HumanoidSpeedComponent
Replace HumanoidSpeedComponent with
a Custom Component derived from SpeedComponent
Because The Game will only contain 3Type of Squads,
Slow, Normal, Fast,
it is more convenient to do a Global Editing instead
As such, the needed variables
were moved to HS_SquadManager
To change Speed of an Individual Unit,
access HF_SpeedComponent and call SetSpeed_[Speed]();
19. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 19
Numerical Notes
Make these really high
~ more than Speeds to do instant Stop
Should they be lower than Speed,
they will do a Curvy Steer,
Which is not what we wanted
Row Speed will make the Frontline Units move Faster
This is use in the case of 180degree Formation Turn,
where they need to overrun Backline Units
20. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 20
Moving Up Slopes
To Create 2nd Floor, add a GridComponent to an Object
Then place, a GridPortalComponent to link between the 2 Grids
Inside NavigationSettingsComponent,
Set MaxSlopeAngle to a desirable number
To setup Individual Units instead,
Deselect UseGlobalHeightNavigation
and edit UnitComponent
Y Position of the Floor
need to be just above Upper Boundary
21. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 21
Rotate toward Target
Add SteerToLookAt to the Unit
Inside an extended class of OrientationComponent,
Override GetOrientation()
And issue input.unit.lookAt = targetPosition
The Value will be used by SteerToLookAt
//Don’t forget to input.unit.lookAt = null
when out of proximity
22. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 22
Distance Limit
To get First Unit from Selected Group
Access
GameServices.gameStateManager.
unitSelection.selected[index].modelUnit;
On Unit or Group, call CreatePathRequest,
and in Path Result,
Access CalculateLength() to get Distance
The Length returned is the total Traveling Distance on Route
///Not that the value is not updated, and is equal to
the Length by the time of Request
23. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 23
Difficult Terrain Path
Define enum for Attributes,
Inside UnitComponent, define the Unit’s Attributes
Add DynamicObstacle to an Object with a Collider
When Unit has
matching Attribute with Dynamic Objects,
it will treat it as a passable Area
24. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 24
Display Path
After CreatePathRequest and registered it to
GameServices.pathService.QueueRequest(req);
Inside Path data,
use path.Peek().position to get the first waypoint,
Then iterate the rest of the position via
foreach( IPositioned nextPosition in path ){}
LineRenderer need to set the exact count of waypoints
in order for SetPositions to Work
26. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 26
To issue Formation
After Units got Selected,
Create DefaultSteeringTransientUnitGroup,
then add all units to it
Use group.SetFormation( Formation ); to create Formation,
Then issue MoveTo(target) to order the Squad to move
27. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 27
Formation class
Make a new Class and Inherit IFormation
GetFormationPosition( int, int, IUnitFacade )
Will return the Desirable position within the Squad
…..HOWEVER…..
Instead of Maintaining Unit position
within allocated Lot in the Squad,
Apex Steer use this allocated Unit to the
nearest relative Position algorithm
If all of the Units has the same Job Class,
then this would not be an issue
But, because we need to maintain Individual Unit to a Position Slot,
we will not use Apex Steer Formation,
And will create a Custom Logic to do Formation instead.
29. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 29
Formation positioning
SquadGuidance is a Transform that will tell Unit where to Position
Each Unit has Position Variables
that told where it should be in SquadGuidance
In order to iterate all Units,
Foreach( IUnitFacade tempUnit in groups.All() )
{
//Do something with Unit
}
30. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 30
Overshoot Problem
PathOptionsComponent => NavigateToNearestIfBlocked
When this is On, If the Target is unreachable,
Unit will go to the nearest position it can go to.
Unfortunately, they could go to the other side of the wall
And when NavigateToNearestIfBlocked is off,
They will simply not move at all
31. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 31
Fix Overshoot
Use GridManager.instance.GetGrid().GetCell()
to find the Cell Property
Use Cell.Walkable() to check if the Unit can reach there
If not, iterate the opening Position
until the reachable position is found.
With Priority being the Rear
******IN ORDER FOR THIS TO WORK*****
Pathways and Walls need to be at least 5m Wide
20 = 2,-2 21 = 2,-1 22 = 2,0 23 = 2,1 24 = 2,2
15 = 1,-2 16 = 1,-1 17 = 1,0 18 = 1,1 19 = 1,2
10 = 0,-2 11 = 0,-1 12 = 0,0 13 = 0,1 14 = 0,2
5 = -1,-2 6 = -1,-1 7 = -1,0 8 = -1,1 9 = -1,2
0 = -2,-2 1 = -2,-1 2 = -2,0 3 = -2,1 4 = -2,-2
32. @OtakuEatMama : @HistoricaFantasiaDevBlog : Zenneth@zodiac-alliance.com 32
Slope Positioning
Assume that the Maximum Slope is 30Degree
And Squad Radius is 8.5m
Tan(30) = height/8.5
Height = Tan(30)*8.5 = 4.91 ~ 5
Place Raycast Origin 5 above,
and RayCast Down 10 to get Final Position
30degree
8.5
10
5