Results 1 to 17 of 17
  1. #1

    Delay in While Loop

    Hello,

    I would like to know if there is a way to add a delay while a while loop is running. I tried adding a delay sensor and inside of the while loop and i wrote: if cont.sensors['delay'].positive: and the I continued the script. Whenever I do this Blender just crashes. Please help me.



  2. #2
    Member BluePrintRandom's Avatar
    Join Date
    Jul 2008
    Location
    NoCal Usa
    Posts
    17,800
    Don't use a while loop
    Code:
    for i in range(numOfPartsToProccessThisFrame) :
         Data = list[own['index']] 
         DoStuff(data) 
         own['index'] +=1
         if len(list) < own['index'] :
             own['index'] =0
    Break it and remake it - Wrectified
    If you cut off a head, the hydra grows back two.
    "headless upbge"



  3. #3
    Im sorry but I do not understand what to do with that. This is the code that doesn't work:

    Code:
    while number < 21:
        if cont.sensors['delay'].positive:
             This is where stuff happens
             number = number + 1

    So if the number is less than 21 i want it to continuously execute the code 20 times with a delay in between the executions using a delay sensor. Im sorry if i just do not get your code because Im kind of a noob at python but can you just explain it to me a little better
    Last edited by orosmatthew; 20-Mar-17 at 20:14.



  4. #4
    Member BluePrintRandom's Avatar
    Join Date
    Jul 2008
    Location
    NoCal Usa
    Posts
    17,800
    While does not mean over time, while is all in 1 frame:


    Delay duration 28-----python (do stuff 1 time)

    Sounds more like what you need
    Break it and remake it - Wrectified
    If you cut off a head, the hydra grows back two.
    "headless upbge"



  5. #5
    well, since i dont know what the application for the code is, try this, its simpler:

    Code:
    ## Requires Game Object to have a property "Timer" as type "Integer" and a property "Count" as type "Integer" ##
    
    import bge
    
    ctrl = bge.logic.getCurrentController()
    owner = ctrl.owner
    
    COUNT = 20 # in frames
    DELAY = 5 # in frames
    
    if owner["Count"] <= COUNT: # the sign can be just "<" if you want to exclude the 20th
        owner["Timer"] += 1
    
        if owner["Timer"] >= DELAY:
            ## DO STUFF ##
            owner["Count"] += 1
            owner["Timer"] = 0
    connect the script to an "Always" sensor set to True pulse (first little button with dots). now you can set the properties to debug(little "I" next to property) and see the numbers change. make sure debug and framerate/profiler are on in the render settings.

    loops dont work in the bge since each frame need to finish the code. a while loop that doesnt exit will get caught running that frame forever, appearing as a crash. for loops are better, but its best to avoid these where possible, since it might take a little time, causing stutters in framerate.
    System "IVAN" (rev 1.3b) - Win7 64bit - Blender 2.74:
    CPU- Intel i3-3220 3.30 Ghz | GPU- EVGA GTX 970 | RAM- GSkill Ares 16GB 1600 Mhz | MB- ASUS P8Z77-V LK



  6. #6
    Moderator Monster's Avatar
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    13,524
    I strongly suggest to read this two guides:

    BGE Guide to the GameLoop
    BGE Guide to Python Coding

    It should help you to get an understanding how the BGE works and what consequences the above design has (in terms of timing).



  7. #7
    There are some times when it's useful to use while. But usually it's best to steer clear of it.
    If you do use "while" it's best to have an escape clause.

    I usually incluse an "error" property which is +1 every loop. The while statement can then say:

    error=0

    while condition and error <1000:

    That way if the main condition isn't met, for example there's a bug in your code, the while statement won't get stuck in an infinite loop, forcing you to ctr-alt-delete your way out.



  8. #8
    Member sdfgeoff's Avatar
    Join Date
    May 2010
    Location
    Where the best chocolate comes from
    Posts
    4,815
    That way if the main condition isn't met, for example there's a bug in your code, the while statement won't get stuck in an infinite loop, forcing you to ctr-alt-delete your way out.
    Some other ways to escape that may be interesting:
    - In Linux, you can just go to Blender's terminal (assuming you're running it from one) and hit ctrl+C, this will raise an exception and kill the while loop. If you're unlucky, it will just plunge back into the while loop on the next frame, but if alternate between hitting the escape button and killing the python script you can often avoid having to kill blender. (This is useful when you have unsaved work).
    - Or if you tweak the python exception hook you can get it to automatically quit the game engine on a python exception (eg ctrl+C). I do this for most of my projects..
    - Or you could bind the sigint to exit bge, so most errors behave the normal way (BGE keeps running), but a ctrl+C exits.

    The end two options assume you don't put big try-except statements through your code. If you are, you should probably reconsider why your code is generating exceptions. <rant>For some reasons, throwing and catching exceptions is considered 'pythonic', but in my mind, exceptions should be reserved for when there is unexpected behaviour. Pretty much: if you can check first, do, and don't be afraid to throw exceptions yourself.</rant>
    Where in the world am I?

    Website: www.sdfgeoff.space



  9. #9
    Moderator Monster's Avatar
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    13,524
    Originally Posted by sdfgeoff View Post
    <rant>For some reasons, throwing and catching exceptions is considered 'pythonic', but in my mind, exceptions should be reserved for when there is unexpected behaviour. Pretty much: if you can check first, do, and don't be afraid to throw exceptions yourself.</rant>
    It is the opposite, you catch expected errors.

    Unexpected errors are errors you do not catch = your code is not ready to deal with them.

    In other words: When you catch an error it means the error is expected behavior of the surrounded code. The surrounding code knows how to deal with it.

    Finally it comes to the same point: do not be afraid to throw exceptions when your code does not follow the "good case". It is sort of a return value too.



  10. #10
    Member Lucrecious's Avatar
    Join Date
    Jul 2008
    Location
    Canada
    Posts
    2,608
    Throwing exceptions is sin!!

    As many have mentioned, all your python scripts run in 1 frame, so all while loops run in 1 frame. To "loop", you should use either a delay sensor (execute script every X ticks) or a timer (execute script every X seconds).

    For the latter use, an always sensor that executes the python script every tick, but if X time has not passed then return from the script immediately.
    Last edited by Lucrecious; 21-Mar-17 at 11:58.
    Current Project: Apparatus
    Website: lucrecious.com



  11. #11
    i find it rather amusing that everyone is throwing around complex concepts in a thread where the poster is clearly not looking for technical things.
    System "IVAN" (rev 1.3b) - Win7 64bit - Blender 2.74:
    CPU- Intel i3-3220 3.30 Ghz | GPU- EVGA GTX 970 | RAM- GSkill Ares 16GB 1600 Mhz | MB- ASUS P8Z77-V LK



  12. #12
    Member Nicholas_A's Avatar
    Join Date
    Oct 2014
    Location
    own.worldPosition
    Posts
    793
    Yeah honestly. It is not hard to explain a while loop. When using a while loop, you are not looping in real time, over the course of many frames. You are looping all within only one frame. that is why the game freezes, because BGE is waiting for the loop to finish before going on to the next frame. If you use a tighter while loop, only restricting it to a few loops, or use a for loop, you will be better off.
    My YouTube channel | My Blendswap profile | Current Project: Infinite Ammo

    I sell custom logos for $5 (among other things). Check them out!



  13. #13
    Wow, thanks everyone for the responses. I ended up finding a way just by avoiding the while loop because I realize that it is not the right use of it. I ended up using an if statement with some more variables and I got it working.



  14. #14
    Originally Posted by Daedalus_MDW View Post
    i find it rather amusing that everyone is throwing around complex concepts in a thread where the poster is clearly not looking for technical things.
    I think people are trying to explain when you actually would use a while loop, and problems to look out for if you do.
    When I first started out with python in blender the tutorial I read said "Don't use while loop".
    That's not very helpful.



  15. #15
    Member BluePrintRandom's Avatar
    Join Date
    Jul 2008
    Location
    NoCal Usa
    Posts
    17,800
    yeah I avoid while at all costs. (hangup is no fun)
    Break it and remake it - Wrectified
    If you cut off a head, the hydra grows back two.
    "headless upbge"



  16. #16
    Moderator Monster's Avatar
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    13,524
    Originally Posted by BluePrintRandom View Post
    yeah I avoid while at all costs. (hangup is no fun)
    I would say:

    "avoid while [without end] at all costs"

    I do not use while that often because of the potential endless looping. This is more a style thing rather than really needed.


    The recommendation is: avoid long running python code.

    A loop is just something that can easily stack up processing costs, but it is a really good construct to deal with repeating operations.



  17. #17
    While can be very useful in some cases. You shouldn't avoid it just because it can cause an infinite loop, but you should avoid it when it's not the correct thing to use.

    When working with a stack while is important. You want to keep going until you've processed the entire stack (which might grow while the loop is working). A good example of this is a flood fill:

    Code:
    def fill(canvas, mouse_position):
        current = mouse_position
        stack = [current]
    
        while stack:                 
            x, y = stack.pop()
            current_tile = current_dict.get((x, y))
            if current_tile.empty:
                 current_tile.empty = False
                 search_array = [(-1, 0), (0, -1), (1, 0), (0, 1)]   
                 for n in search_array:
                     nx, ny = n
                     stack.append((x + nx, y + ny))
    
    mouse_position = (5, 12)
    fill(canvas, mouse_position)
    In all cases you should make sure that either there is a natural limit to the stack size (in a flood fill it would be the edge of the canvas) or add an counter to stop the loop if it goes on too long.
    Recursion in python is a kind of stack and while loop:

    Code:
    def add_to_list(number_list, current):
             current += 1
         if current < 1000:
             if current%2==0: # if the number is even, keep it
                 number_list.append(current)
             add_to_list(number_list, current)
    
    number_list = []
    add_to_list(number_list, 0)
    There are other uses for the while loop, such as solving a problem (packing rectangles in to a grid, maze navigation, etc...) through brute force.
    Most often it is used where you can't use a for loop because the contents of the list can change during the operation.

    If the list remains the same then the best practice is to use a for loop. If you want the operation to carry on over several ticks then you should use an index counter or pop items from the start of the list.



Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •