So I figured out the fastest AI sorting way, but is this it?

0 favourites
  • 9 posts
From the Asset Store
A master sorting Puzzle fun and addictive puzzle game! A challenging yet relaxing game to exercise your brain!
  • Are there any faster ways for dealing with a large amount of instances with unique pathfinding AI behavior other than using global_UIDs matching each instance or a number of global for each loops manually built using a few different global_UIDxxxx for instances over 400+?

  • You could assign the instances with an Instance Variable for example (Signature)

    Pick by comparison ->

    Sprite.Signature = "Heroes"

    or

    Compare Variable ->

    Signature = "Heroes"

    or

    Signature = "Enemies"

  • The has the bad habit of choosing all of them when trying to combine it with distance and compare functions sadly. Kind of important to use with pathfinding. But you can get around it by using a complex system of like 10 or more booleans however thats horrifically messy. Only way I know of choosing a single instance each manaul loop is to store its ID or you cant get unique pathing to the object or for the object/from the object.

    Otherwise you're left dealing with boolean flag hell which is horrible. Imagine the same scenario:

    Pick by comparison ->

    Sprite.Signature = "Heroes"

    Sprite.BoolHasSearched != true

    Sprite.BoolHasTarget != true

    Sprite.BoolJustSearched != true

    Everything else has to keep these in check, but this is only BASIC path finding, if I had conditionals:

    Sprite.BoolDamaged != true

    Sprite.BoolJustDamaged != true

    Sprite.BoolHasTargetInSight != true

    Each of these booleans has to get its own unique group of events which can exceed 100+. Now I COULD do it that way, in fact I've done it before and it is painful to keep the events clean when you do it this way, especially just reading the code back to yourself in the event sheet.

    In most other programming languages (typed) I just pass the object to a function as a parameter and it'll loop through the objects unique behavior that way. But we dont get class files/scripts, so choosing is done on one event list editor. Not just allowing the object/sprite to inherate a class/script and use it to do logic. Even if you do this manaully and pass it a GlobalUID you're back to square one. basically, the Sprite object in construct 2 cannot store a class inside of it which causes problems when looping through tons of instances because the instances are simply Sprites that hold variables and behaviors but choosing them is either done through:

    1. A global or Local Variable for UID/other unique identifier each loop

    2. A painfully slow built in For Each Loop

    3. A matching variable to either 1 and 2 through another instance, just as bad

    4. Matching to an existing number inside of an array, not that fast.

    This is discussing instances over 400+ mind you.

  • umm, wellp, someone said to append the items which are pinged (flag/bool/var) to need a search onto a list of items which need to be sorted to use this appended search list to pull the UIDs on the list, which works.

    What i ended up doing in one of my tests is chunkify my lists of objects with limited scope. Which isnt new to programming I forget what this is called. Usually threaded I'm sure. But I just discovered event sheets can have functions which are called from other sheets which can end up being useful. Not sure if functions can get passed UIDs and store them PER(tick) call. Anyone know?

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • I don't really get what you're doing. I understand you have a lot of objects with the pathfinding behavior and I guess you want them to target each other? I get lost with the talk of uid and for each loops and such. I must be tired I guess.

  • Oh, right basically I'm just cutting down on resource usage from the built in for each loops and appending each item to a manual loop iterator (using globals combined with a param in each function (note: only one function))

    but simply put it goes like

    call function loops:

    1-20

    add 1 to a value sort 1_20 (a list of sorts)

    20-40

    add 1 to a value sort 20_40 (you will always want to reset the counter once over 40 to the base 20 and then add 1, never counting 20 of course)

    etc etc each are loops.

    Each loop ends with one group of SpriteObject Variables (well, UIDs) being tested per loop, and with those being chosen, pass their param via one CENTRAL function with CentralFunc(Param0: SpriteObject.UID) its a way ive been creating class built in functions because I cant actual create classes in construct 2 which can inherent scripts within them and choose themselves. Atleast thats what is capable within game maker.

    Now I despise game Maker studio, not only is it buggy but their EULA is restrictive and they themselves say they will enforce it any time of their choosing. (Anyone know of an engine much like game maker with scripts? )

    So, Ive got issues, right now if you do stuff like

    Every "dt * value" seconds--->

    For each object ---->

    pass object to a function(param0: object.UID) and then in the function test to see if it is equal to function.param(0) it works,

    my problem stems from, yes I can do it instead like:

    pick object with a param/variable ---->

    test another condition or even overlap of a sensor object ---->

    pass object to a function(param0: object.UID) and then in the function test to see if it is equal to function.param(0) it works,

    The bad thing baout this, right now I got about 1000+ instances and the CPU usage is manageable, HOWEVER, if I dont create like 3 or 4 of these individual functions that only scope a certain about of objects each time (I.E. a range of objects with a unique variable, or objects onto a list (not sure how this is done in construct 2 tbh)) then I get TERRRIBLE bottle neck issues where some AI dont even get picked for over 50 seconds or more.

    I was wondering like what are some ways to go about managing these bottlenecks with the manageable way besides calling separate scoping loops ruining each tick in tandem with one another?

    GlobalVar1_1to100: 0

    add to GlobalVar1_1to100: 1

    On Loop 1-100>>

    ID > 0 <= 100>>

    pick if ID == GlobalVar1_1to100>>

    call function func(param0: UID)

    then function with matching UID as normal, make 4or 5 of these with blocks of 101-200, 201-300, etc etcetc

    seems to be the fastest way when dealing with instances over 1000+

  • I understand that a bit better. So basically you want to only process a certain number of objects at a time instead of doing it all at once?

    The "pick nth instance system" condition could be useful. You could also use an array to make a list of uids i suppose but picking the nth instance is simpler.

    So basically you're doing this? It only loops over 100 of the sprites per frame. So with 1000 instances it would take 10 frames to loop over them all.

    global number n=0
    
    system: repeat 100 times
    system: pick sprite instance n
    --- function: call "doStuff" (sprite.uid)
    --- system: set n to (n+1)%sprite.count
    
    on function "doStuff"
    sprite: pick by uid function.param(0)
    --- ...[/code:27411qou]
    
    Edit:
    That code assumes there are more than 100 instances. Probably should change the "repeat" to the following to keep instances from being looped on more than once when the sprite count is less than 100.
    system: repeat min(100, sprite.count) times
  • Oh yea, that will loop through 100 times each tick? Will def check it out thanks, basically I'm trying to make the least lagiest for each loops for large amounts of sprite objects who will be given functionality through another function which will do whatever but do it in large volumes. Mostly for stress test purposes. I only use construct 2 to prototype ideas tbh and light game experiments. I was noticing there is a bottleneck everytime I try doing something like this so I had to manually create what you just did in multiple function loops only iterating through scoped object chunks of 1-200, 201-400, etc, etc. Which works great but is made simpler with other functions I discovered (something similar to yours but without nth picking.) I'll give your thing a shot and report back as I require rest now thanks alot

  • In case of someone who is keeping track of this, I combined R0J0hound's method of handling this with my other previously used method of cycling through only a certain number range of instances at a time which keeps the events within afew lines and yet is dynamic enough to be modular. Very nice stuff. (well, appending items needing to do tasks to lists is useful asweell. will experiment further)

    Edit 1:

    Still seems to be some terrible issues with resource management (on instances 1000+, around 400+ it seems OK.) , FPS, and unit count. I'm not sure but it still might require dedicated scoped loops (separate ones) due to the way its either

    1. Being executed

    2. used

    3. built in limitation or issue I cant see.

    oh well I'll keep experimenting with it. Kind of a bummer. Pretty sure itsbecause of the repeat event per tick. I wonder if there is a way to perhaps change the repeat event iteration to every other tick or something? so as not to bog down the processing of tons of units each and every tick?

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)