1,105,585 Community Members

How to correctly exit if statement in this case?

Member Avatar
DaveTran
Junior Poster
154 posts since Mar 2010
Reputation Points: 3 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
1
 

I am moving an object around from one node to another. I need to tell the object to stop moving when it has reached its destination node.

I am currently using this algorithm for movement and node checking

if (!isFinished)
            {
                // If the level has arrived at the current destination node and not at the final node
                // Destination node is based on the interpolated points on the spline
                if (AtNode(catmullRomSpline.InterpolatedPoints[nodeIndex], node))
                {
                    // If we have not reached the final node/interpolated point on spline
                    if (nodeIndex + 1 < catmullRomSpline.InterpolatedPoints.Count)
                    {
                        // Increase the node index
                        nodeIndex++;
                    }
                    else
                    {
                        isFinished = true;
                    }
                }

                // Now move object unless finished is true

The problem I have is that I don't want to do any of the above if the isFinished boolean is true but if it is flagged as true in the method then the object will still be moved for that frame. This is because the isFinished is only checked at the start of the method.

How can I change the method to avoid this or exit correctly once isFinished is flagged as true?

Member Avatar
ali_zdn
Newbie Poster
7 posts since Jul 2010
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

break ;

Member Avatar
Lusiphur
Practically a Posting Shark
852 posts since Jun 2010
Reputation Points: 185 [?]
Q&As Helped to Solve: 134 [?]
Skill Endorsements: 4 [?]
Team Colleague
Featured
 
0
 

If I understand this correctly you're intending this process to check for isFinished == true and proceed only if it's true.

Your concern is, if the condition changes WHILE it's processing the steps within your if block, correct?

First, I'm not sure you should be using IF for the initial part of your code block but perhaps WHILE. IF will start the block and run through it once from start to finish as long as the condition existed to begin with. WHILE on the other hand will start the block and conrinue to run the block until the condition that started it changes.

Just judging by what you have within the block it looked more like you wanted a WHILE loop instead of an IF check was all... but if I'm wrong, no harm no foul, someone else will likely get your answer for you :)

Member Avatar
DaveTran
Junior Poster
154 posts since Mar 2010
Reputation Points: 3 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

break ;

break won't work in this situation, if isn't a loop.

If I understand this correctly you're intending this process to check for isFinished == true and proceed only if it's true.

Each time the method is called isFinished is check and the object moves if the boolean evaluation is false.

First, I'm not sure you should be using IF for the initial part of your code block but perhaps WHILE.

If I used while then the movement update would be stuck until the object had reached its goal. In my case I would like the object to update its position once per frame but only if isFinished is false. The problem is that the object could be finished in the current frame yet the object will still move.

Member Avatar
Lusiphur
Practically a Posting Shark
852 posts since Jun 2010
Reputation Points: 185 [?]
Q&As Helped to Solve: 134 [?]
Skill Endorsements: 4 [?]
Team Colleague
Featured
 
0
 

I wonder if a combination of the while loop and break might come in handy :)

Basically a loop that is deliberately broken after the desired effect...

The concept being that it maintains it's "while" check and self terminates if the value evaluates false but also force-terminates when it completes it's initial required step.

Not sure if that makes any sense or not :-/

Member Avatar
DaveTran
Junior Poster
154 posts since Mar 2010
Reputation Points: 3 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

I wonder if a combination of the while loop and break might come in handy

This would mean that the loop would be broken each frame and then not executed once the boolean value is true. The loop would only ever need one iteration every time before it is broken.

Is there no other way?

Member Avatar
Lusiphur
Practically a Posting Shark
852 posts since Jun 2010
Reputation Points: 185 [?]
Q&As Helped to Solve: 134 [?]
Skill Endorsements: 4 [?]
Team Colleague
Featured
 
0
 

This would mean that the loop would be broken each frame and then not executed once the boolean value is true. The loop would only ever need one iteration every time before it is broken.

Is there no other way?

Heck, I was just tossing theories at that point, I'm not super knowledgeable on node navigation :twisted:

Member Avatar
arunkumars
Posting Whiz in Training
204 posts since Jul 2009
Reputation Points: 16 [?]
Q&As Helped to Solve: 22 [?]
Skill Endorsements: 0 [?]
 
0
 
if (!isFinished)

{

    // If the level has arrived at the current destination node and not at the final node

    // Destination node is based on the interpolated points on the spline

    if (AtNode(catmullRomSpline.InterpolatedPoints[nodeIndex], node))

    {

        // If we have not reached the final node/interpolated point on spline

        if (nodeIndex + 1 < catmullRomSpline.InterpolatedPoints.Count)

        {

            // Increase the node index

            nodeIndex++;
            if (nodeIndex + 1 == catmullRomSpline.InterpolatedPoints.Count)
            {
                isFinished = true;
            }

        }

        //else

        //{

            //isFinished = true;

        //}

    }

 }

I hope this should work, in order to make the isFinished bool variable as true and once nodeIndex + 1 is equal to catmullRomSpline.InterpolatedPoints.Count, the current destination is achieved.

Thanks,
if its working fine, do not forget to mark it as solved.

Member Avatar
DaveTran
Junior Poster
154 posts since Mar 2010
Reputation Points: 3 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 
if (!isPathFinished)
                {
                    if (AtNode(catmullRomSpline.InterpolatedPoints[nodeIndex], node))
                    {

                        // If we have not reached the final node/interpolated point on spline

                        if (nodeIndex + 1 < catmullRomSpline.InterpolatedPoints.Count)
                        {
                            // Increase the node index
                            nodeIndex++;

                            if (nodeIndex + 1 >= catmullRomSpline.InterpolatedPoints.Count)
                            {
                                isPathFinished = true;          // <=============== (!isPathFinsished)
                            }
                        }
                    }
                }

Doesn't work as it is afflicted with the same problem as the original method, unless I'm mistaken. It doesn't work for me.

Member Avatar
Ketsuekiame
Posting Virtuoso
1,676 posts since May 2010
Reputation Points: 793 [?]
Q&As Helped to Solve: 231 [?]
Skill Endorsements: 27 [?]
 
1
 

It might be a bit extreme, but where you set isFinished, could you just return; and exit the method?

Otherwise, you will need a second boolean check.

if (!isFinished)
            {
                // If the level has arrived at the current destination node and not at the final node
                // Destination node is based on the interpolated points on the spline
                if (AtNode(catmullRomSpline.InterpolatedPoints[nodeIndex], node))
                {
                    // If we have not reached the final node/interpolated point on spline
                    if (nodeIndex + 1 < catmullRomSpline.InterpolatedPoints.Count)
                    {
                        // Increase the node index
                        nodeIndex++;
                    }
                    else
                    {
                        return;
                    }
                }

                // Now move object unless finished is true

or;

if (!isFinished)
            {
                // If the level has arrived at the current destination node and not at the final node
                // Destination node is based on the interpolated points on the spline
                if (AtNode(catmullRomSpline.InterpolatedPoints[nodeIndex], node))
                {
                    // If we have not reached the final node/interpolated point on spline
                    if (nodeIndex + 1 < catmullRomSpline.InterpolatedPoints.Count)
                    {
                        // Increase the node index
                        nodeIndex++;
                    }
                    else
                    {
                        isFinished = true;
                    }
                }

                // Now move object unless finished is true
                if(!isFinished)
                {
                   // Do Stuff
                }
            }

You have a check for "isFinished" up at the top also, is this necessary? I don't know how you're handling things outside this local block so I can't say for certain, but if you thought it may exit immediately once isFinished becomes true inside the block, that is incorrect.

Member Avatar
arunkumars
Posting Whiz in Training
204 posts since Jul 2009
Reputation Points: 16 [?]
Q&As Helped to Solve: 22 [?]
Skill Endorsements: 0 [?]
 
0
 

I suppose you are using a for loop before checking !isfinished, provide that loop as well. may be we can sort it out..

Member Avatar
DaveTran
Junior Poster
154 posts since Mar 2010
Reputation Points: 3 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

I suppose you are using a for loop before checking !isfinished, provide that loop as well. may be we can sort it out..

There is no for loop. I've currently got my method looking like this.

public void UpdatePathfinding(float dt)
        {
            Vector3 destinationNode = Vector3.Zero;
            bool isPathFinished = false;

            if (AtNode(destinationNode, catmullRomSpline.InterpolatedPoints[nodeIndex]))
            {
                if (nodeIndex < catmullRomSpline.InterpolatedPoints.Count - 1)
                {
                    nodeIndex++;
                    isPathFinished = false;
                }
                else
                {
                    isPathFinished = true;
                }
            }

            if (!isPathFinished)
            {

As it stands now, the object checks every frame to see if it has arrived at its destination node. The object still checks when it has reached the final node. In a way I think this is good because the check is inexpensive and the node can be updated and the object will move normally.

The node check is just

private bool AtNode(Vector3 nodePosition, Vector3 objectPosition)
        {         
            Vector3 v = nodePosition - objectPosition;
            return Math.Abs(v.LengthSquared()) < 0.04f;
        }

Does this look better?

Ideally I would like the object to stop checking once it has arrived at the final node, and start checking once a new destination node is given. I can't figure out how that would work though.

Member Avatar
arunkumars
Posting Whiz in Training
204 posts since Jul 2009
Reputation Points: 16 [?]
Q&As Helped to Solve: 22 [?]
Skill Endorsements: 0 [?]
 
0
 

I have a doubt now, How do u define the destination node..?
My view : Once you u know u have reached the destination node, make the isFinished boolean variable as true.
so, the next time it wouldn't come into the loop...
I hope you understood what I am trying to mean here.

Member Avatar
DaveTran
Junior Poster
154 posts since Mar 2010
Reputation Points: 3 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

The destination node is defined as a point

catmullRomSpline.InterpolatedPoints[nodeIndex]

where the nodeIndex is index of the points.

The final node is where: nodeIndex = InterpolatedPoints.Count - 1.

The object is at the node if it is within a certain radius of the point. This is to counter floating point errors.

Member Avatar
arunkumars
Posting Whiz in Training
204 posts since Jul 2009
Reputation Points: 16 [?]
Q&As Helped to Solve: 22 [?]
Skill Endorsements: 0 [?]
 
0
 
bool isFinished = false;
      // If the level has arrived at the current destination node and not at the final node

      // Destination node is based on the interpolated points on the spline

      if (AtNode(catmullRomSpline.InterpolatedPoints[nodeIndex], node))
      {

      // If we have not reached the final node/interpolated point on spline

      if (nodeIndex == (catmullRomSpline.InterpolatedPoints.Count - 1))
      {
	if (!isFinished)
      	{

	      // Increase the node index

	      nodeIndex++;
         }

         else

         {
   	   isFinished = true;
         }
      }
       
      // Now move object unless finished is true

try this,
let me know.

Member Avatar
DaveTran
Junior Poster
154 posts since Mar 2010
Reputation Points: 3 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 
bool isFinished = false;
      // If the level has arrived at the current destination node and not at the final node

      // Destination node is based on the interpolated points on the spline

      if (AtNode(catmullRomSpline.InterpolatedPoints[nodeIndex], node))
      {

      // If we have not reached the final node/interpolated point on spline

      if (nodeIndex == (catmullRomSpline.InterpolatedPoints.Count - 1))
      {
	if (!isFinished)
      	{

	      // Increase the node index

	      nodeIndex++;
         }

         else

         {
   	   isFinished = true;
         }
      }
       
      // Now move object unless finished is true

This still checks the node even when the object is finished. It doesn't do anything different from my code as far as I can tell.

Member Avatar
Ketsuekiame
Posting Virtuoso
1,676 posts since May 2010
Reputation Points: 793 [?]
Q&As Helped to Solve: 231 [?]
Skill Endorsements: 27 [?]
 
0
 

Dave, can you please describe the entire method and how it's called.

You're implying there is a loop, yet, the code you posted and what you say, means there isn't one. So it's a bit confusing.

Thanks.

Member Avatar
DaveTran
Junior Poster
154 posts since Mar 2010
Reputation Points: 3 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

Absolutely, sorry for the confusion.

The path finding code is called from the Update() method.

public void Update(float dt)
        {
            HandleInput(dt);
            UpdatePathfinding(dt);
        }

This is a method that is called 60 times per second.

The UpdatePathfinding method itself is not a loop.

Vector3 destinationNode = Vector3.Zero;
            bool isPathFinished = false;

            if (AtNode(destinationNode, catmullRomSpline.InterpolatedPoints[nodeIndex]))
            {
                if (nodeIndex < catmullRomSpline.InterpolatedPoints.Count - 1)
                {
                    nodeIndex++;
                    isPathFinished = false;
                }
                else
                {
                    isPathFinished = true;
                }
            }

            if (!isPathFinished)
            {

I do not wish to execute this method if isPathFinished is true. Setting isPathfinished during the method to true still executes the remainder of the method though and that is where my problem lies.

Member Avatar
Ketsuekiame
Posting Virtuoso
1,676 posts since May 2010
Reputation Points: 793 [?]
Q&As Helped to Solve: 231 [?]
Skill Endorsements: 27 [?]
 
0
 

Then I suggest you take my other approach that I mentioned on the first page. At the point where you set isPathFinished to true, rather than doing that, simply put a return statement.

This will exit the method at that point.

You will always need to find a way of checking whether you are at the end of your path. I think if you want to do this any differently you will have to redesign what this method does.

Unfortunately that would probably require knowledge of code outside of the specific block you want help with.

Also, if if (AtNode(destinationNode, catmullRomSpline.InterpolatedPoints[nodeIndex])) fails, you can use the "else" statement to abort the method.

if (AtNode(destinationNode, catmullRomSpline.InterpolatedPoints[nodeIndex]))
            {
                if (nodeIndex < catmullRomSpline.InterpolatedPoints.Count - 1)
                {
                    nodeIndex++;
                    isPathFinished = false;
                }
                else
                {
                    isPathFinished = true;
                }
            }
            else
            {
                return;
            }

Even though your method is a returning "void" you can still use the return statement to break execution. You won't find it very often because many people take it as bad design (which in most cases is true) But I think you can get away with it in this case.

Member Avatar
Ryshad
Nearly a Posting Virtuoso
1,263 posts since Aug 2009
Reputation Points: 480 [?]
Q&As Helped to Solve: 247 [?]
Skill Endorsements: 14 [?]
 
0
 

I second what ketsuekiame said. If there is no code to run after the if(!isFinished) block then use return to exit the method.
If there is code that has to run after the if block regardless of isFinished then add a second condition check. That way you will only move the object if isFinished is false at the start AND remains false after the first section of code.

You
This article has been dead for over three months: Start a new discussion instead
Post:
Start New Discussion
Tags Related to this Article