- Home /
How to repeat a coroutine with an event?
Firstly, I am unsure whether "repeat" is the right terminology (feel free to correct me on that). Secondly, I am making a waypoint-based navigation for NavMesh agent to follow. The problem is that I am using a timer (i.e WaitForSeconds) to assign the waypoint to the agent (if I don't do this the loop will run just 1 frame and the agent just moves to the last waypoint).
Here is the pseudocode of what I was want to do:
if (agent reaches a waypoint)
{
agent.setDestination(nextWaypoint);
}
But I do not know how to do this.
Here is what I have so far:
IEnumerator wayPointPicker()
{
for (int i = 0; i < waypoint.wayPointPositionList.Length; i++)
{
opponentAgent.SetDestination(waypoint.wayPointPositionList[i]);
yield return new WaitForSeconds(timer);
}
}
If you need more information to go on for I will try my best to supply. I will be very grateful if you can type a code snippet along with your explanation - preferably in C# but I can make do with JavaScript.
Also if you have another method on tackling waypoints - feel free to share! I find techniques on solving the same problems fascinating!
Thanks for taking the time to read this far!
IEnumerator wayPointPicker()
{
for (int i = 0; i < waypoint.wayPointPositionList.Length; i++)
{
opponentAgent.SetDestination(waypoint.wayPointPositionList[i]);
// wait until waypoint is reached
while(agent not at waypoint){
// if not at waypoint then wait till next frame
yield return null;
// can also use WaitForSeconds ins$$anonymous$$d of a frame
}
}
}
It does not seem to work. The agent only moves to the first destination and stops there. It happens to both "yield return null" or "yield return new WaitForSeconds".
Here's how I interpreted your suggestion into my code:
IEnumerator wayPointPicker()
{
for (int i = 0; i < waypoint.wayPointPositionList.Length; i++)
{
opponentAgent.SetDestination(waypoint.wayPointPositionList[i]);
while (transform.position != waypoint.wayPointPositionList[i])
{
// yield return new WaitForSeconds(timer);
yield return null;
}
}
Answer by Ibzy · Jul 13, 2015 at 12:35 PM
I'm not entirely sure if the destination gets cleared when an agent reaches its destination, but if it does, a check of opponentAgent.HasDestination() could be used to check if they've made it to the waypoint.
According to Unity scripting API, there is no ".HasDestination()" but a ".hasPath()" (if that is what you have meant?)... and where would I add this check in the coroutine?
Answer by meat5000 · Jul 14, 2015 at 10:02 PM
Im not sure if this is what you are after, but I use the child's/monkey's approach, it seems (For a predefined path).
Here's some snippets.
The first is the OnDrag routine which records my swipe across a RenderTexture from an overhead camera.
The Second is the simple timed stepping through the elements of the created List containing the points, and a Lerp to project my spaceship through the path.
Its pretty crude but you should be able to see how it works.
function OnDrag(data : PointerEventData)
{
if(enlarged)
{
didDrag = true;
var hitR : RaycastHit;
var maskL : LayerMask = 1 << 14;
var rayTouch : Ray = myCam.ScreenPointToRay(data.position);
if(Physics.Raycast(rayTouch, hitR, Mathf.Infinity, maskL))
{
this.playerPath.Add(Vector3(hitR.point.x, 10, hitR.point.z));
}
}
}
function FixedUpdate ()
{
nextPos = lastPos + 1;
if(getPath)
{
GetPath(); //Returns playerPath List
getPath = false;
followPath = true;
}
if(followPath && nextPos < myPath.Count)
{
timer += Time.deltaTime;
if(timer > timerMax)
{
lastPos += 1;
timer = 0.0;
if(!firstPosHit) firstPosHit = true;
}
var t : float = timer / timerMax;
var temp1 : Vector3 = Vector3(myPath[lastPos].x, 10, myPath[lastPos].z);
var temp2 : Vector3 = Vector3(myPath[nextPos].x, 10, myPath[nextPos].z);
if(!firstPosHit)
{
transform.position = Vector3.Lerp(transform.position, temp1, t);
}
else transform.position = Vector3.Lerp(temp1, temp2, t);
}
else followPath = false;
//Debug.Log(temp1+" "+temp2);
}
Your answer
