Day 69 — Implementing a Coin Distraction Ability Part 2
Hey and welcome!
Now that we have our coin appearing where we want it to in the game when the player right clicks it’s now time to add in the functionality to get our guards to move towards the coin and the idle around it.
Let’s get start by adding in this new method to our Player script:
void SendAIToCoin(Vector3 coinPos)
{
GameObject[] guards = GameObject.FindGameObjectsWithTag("Guard1");
foreach(var guard in guards)
{
NavMeshAgent currentAgent = guard.GetComponent<NavMeshAgent>();
GuardAI currentGuard = guard.GetComponent<GuardAI>();
Animator guardAnim = guard.GetComponent<Animator>();
currentGuard.coinThrown = true;
currentAgent.SetDestination(coinPos);
guardAnim.SetBool("Walking", true);
currentGuard.coinPos = coinPos;
}
}
This isn’t something that’s going to get called every frame as it’s only going to get called once when the coin is Instantiated so we have no global variables this time and we’re just sticking to having local ones in the SendAIToCoin method.
Speaking of, in order for the guard to know where the coin is we’ve created a coinPos parameter for our method so that we can pass in the value of hitInfo.point right after it gets instantiated. This means that you’ll need to add in SendAIToCoin(hitInfo.point) inside your raycast when you right click in order to get this code to run.
In the code itself we’re creating an array to store all the possible instances of our guards in the game by finding their tag of Guard1, so make sure your guards share the same tag, it can be anything you prefer. Since we’re dealing with an array here we make use of a foreach loop in order to iterate through each instance in the array.
With that done we create 3 local variables that grab a component from the guards which are the Nav Mesh Agent, GuardAI script and the Animator components. You should be able to grasp from the rest of the code what we’re using those for, the one that might not be so clear is the last one where we’re assigning coinPos as the value for the coinPos in the guard script.
Here’s the code that needs to be added into the GuardAI script that should explain things:
public bool coinThrown;
public Vector3 coinPos;if (wayPoints.Count > 0 && wayPoints[_currentTarget] != null && coinThrown == false)
{}else
{
float distance = Vector3.Distance(transform.position, coinPos);
if (distance < 4f)
{
_anim.SetBool("Walking", false);
}
}
I’ve shown in bold what you need to add to the main if statement. So long as coinThrown is false then it’s going to run the code for the modular waypoint system we created as normal.
When we set it to true from our player script then the else statement here runs. This is where we make use of the coinPos value as we’re using that to work out the distance between the guard and the coin. Then when the guard is close enough we get them to change into their idle state so that they’re not just walking in place around the coin.
With all that done you should have something like this:
You can adjust the value that distance should be less than to whichever works best for your game, as you can see here my guards move into their idle pose earlier than they should which means I need to shorten the distance.
If the guard’s behaviour is still a bit off for you then you can adjust their Steering settings in the Nav Mesh Agent component until you get something that looks right.
In my case I turned off the Auto Breaking and set the Stopping Distance to 1.
Last thing to do before I wrap up here is to make use of that throw animation we added to the Animator back when we were setting that up for Darren. Go ahead and adjust it so that it looks like this:
Now create a trigger parameter this time called Throw and add it to the condition for the transition highlighted in blue. That Any State box there just means that our throw animation can play regardless of what animation is currently happening in the Animator.
With that done go ahead and add _anim.SetTrigger(“Throw”) to your Raycast when you right click and you’re all set!