PRE-ALPHA II

For Pre-Alpha II, my focus was to first refine the patrol behavior scripts from Pre-Alpha I, then begin developing the driver script for our game’s ranged enemy. The PatrolBehavior.cs and GroundDirectionChooser.cs scripts from Pre-Alpha one had a major flaw – they manipulated the enemy’s velocity directly (which should generally be avoided) instead of utilizing NavMeshAgents. I began my refinement of these scripts with the goal of making this change as well as adding the state transition that I missed during the last sprint. As I started looking through the patrol documentation, however, I realized some misunderstandings I had about how the behavior was supposed to work. I reached out to my pod’s lead who confirmed my suspicions, and I took this opportunity to make the necessary alterations to these scripts as well.

Making the NavMeshAgent change was generally straight-forward, although it took me a while to sort out the best way to approach it. I began by using the NavMeshAgent’s SetDestination function when a new patrol path was chosen, then checked if hasPath was false to determine when a new path needed to be chosen. This was followed by checking if PathStatus == PathStatus.Complete to solve the same issue. Neither of these approaches worked as expected and the enemy would stop moving after it’s first patrol destination. After doing some research on NavMeshAgents, I then altered this to simply setting agent.destination to the new location and checking if agent.remainingDistance <= agent.stoppingDistance for the “finished patrol” check. This worked perfectly.

PatrolBehavior code using NavMeshAgent

PatrolBehavior.cs utilizing NavMeshAgent

I believe that my prior attempts did not function as expected due to a misunderstanding of how NavMeshAgents handle pathfinding – reducing the scale of the enemy allowed some of my earlier implementations to work correctly, leading me to believe that the shape of an agent causes it to rarely reach the exact destination you specify. I also made the decision to change from calculating the distance between the enemy and the player with Vector3.Distance() to Vector3.sqrMagnitude. Removing the square root calculation that Vector3.Distance() divides by and instead comparing Vector3.sqrMagnitude to the square of values in my condition checks has the same results, but is much more efficient.

GroundDirectionChooser.cs required more of an overhaul because of last sprint’s misunderstandings, but most of the changes turned out to simplify the script. I thought it was odd that the charger enemy’s PURSUING state did not beeline towards the player, and after clarification, it turns out this was indeed the intended behavior. The SEARCHING state was also intended to work this way. Where previously the GetNewDirection function took in an isHostile Boolean, I determined that a function was no longer needed to determine direction in these states, as PatrolBehavior.cs could just direct the enemy toward the player. This removed GroundDirectionChooser.cs’s dependency on PatrolBehavior.cs. I also allowed me to remove the code that previously determined a path for an enemy in a hostile state. The other change I made to this script was adding a slight bias toward the player when choosing a direction to move. Before, when a direction was deemed invalid, the function repeated its process until a valid one was found. Now, the invalid direction rotates either left or right until a move can be made – the direction of rotation is determined by which angle between the invalid direction and the player is smaller. This slight tweak made the enemy’s behavior more deliberate and engaging than in the previous iteration.

Enemy patrolling with slight bias toward the player

Patrol behavior with slight bias towards the player

After completing the patrol alterations, it was time to create the ranged enemy’s driver script. I began as I did with PatrolBehavior.cs, creating an enumerated list of states, and checking for the specified conditions in the documentation for when states should be changed. I then walked through my list of transitions, combining like conditions or removing some entirely that would never be satisfied. This was where I had intended to stop, as my pod had not yet decided the best way to handle activity within each state. However, knowing that my pod was already behind schedule, I wanted to make an effort to get us back on track. I combed through the ranged enemy’s documentation and wrote pseudo-code within each state for that state’s intended behavior. Whether my team decides to create functions for each state or develop separate scripts, I believed this would help to give us direction as to how each programmer’s scripts will interact. During our pod meeting the night before, there was a rather large change to how this enemy’s movement will be determined, so translating the documentation given those changes was a lengthy process. I believe that my pseudo-code has the same functionality, but extensive testing will need to be done to ensure this once it is implemented. If all goes as expected, we now have a solid basis for how to approach the rest of this enemy’s development.

ShooterBehavior update loop code

ShooterBehavior.cs base update loop

State transition check code

State transition checks and pseudo-code for each state

Time breakdown:

Weekly studio meetings – 2 hours
Additional enemy pod meetings – 2.5 hours
PatrolBehavior.cs and GroundDirectionChooser.cs refinement – 3.5 hours
ShooterBehavior.cs – 2 hours
Total time spent: 10 hours

Previous
Previous

PRE-ALPHA III / PRE-BETA I

Next
Next

PRE-ALPHA I