[Solved] Multiple instances' states are changed when only one should change

Here is a screencast of the problem I’m having. Once all the grey blocks are removed, the raycast should pick the bottom green Squibble and set its state to ‘falling’. But all of the Squibbles’ states are set to ‘falling’, and I can’t work out why…

Peek 2022-08-31 10-36

Here’s the relevant part of my event sheet:

Any ideas what I’m missing/doing wrong?

Not to mention, all but one fall through the grass (they shouldn’t do that):

How are you checking each individual object’s state? Is the ‘For Each’ loop else where?

You mean to move them down when they’re in the ‘falling’ state? I’m just using a single condition, no foreach. See the ‘Falling state’ screenshot above.

Could it be that your raycast is constantly checking (and therefore making them ALL set to “falling”)? Maybe a simple trigger once could fix it? :thinking:

Also you have a repeat condition here (image below), might wanna get rid of it! :wink:

I thought that too, but realised the state of squibble can change in the previous 2 events (before the last event). So the check is a valid one, and not a repeat.


That inverted logic of a raycast makes no sense - a raycast returns objects, not boolean. You need to check against the number of objects selected in the previous raycast.

With respect, I’m not sure that’s correct… Here’s a test I did:

Results in:

image

Whereas:

Results in:

image

I believe this is because a raycast return FALSE when it doesn’t find the given object. Hence the second condition (checking the number of picked objects) is never run.

So my negated raycast does what I need it to (return TRUE when it doesn’t find anything).

Ok, that’s something I need to wrap my head around - the logical opposite of nothing is true.

But back to your issue. I get the feeling the issue may not be in the events you screen snipped. Is there any way the falling of a Squibble during play could be working here? Is there anywhere else where the Squibble’s Y position is updated?

If you pause the game while the Squibbles are falling at the end, you can use the debugger to check the variable state of all the Squibbles in the scene. I use something like the following to pause the game :

image

1 Like

One way of looking at it is that raycasts simply pick 0 or 1 objects. If they pick 0 objects, that equates to FALSE (0 == FALSE in most programming languages). And so NOT 0 == TRUE.

Thanks for that tip. I’d been wondering how to check the debugger while the game was running…

I’ve done that, and indeed all Squibbles had the ‘falling’ state. So that explains why they’re moving down the screen. I then changed the state from ‘falling’ to ‘debug’ in my raycast event to try and work out if it was that event or elsewhere that’s setting their state to ‘falling’. And when I tested that, only one Squibble had the ‘debug’ state (the rest were all still ‘idle’ (which is how they start)). So the issue seems not to be in the raycast section, but elsewhere. I’ll have to try and work out how that’s happening…

1 Like

Yeah, I’ve been aware of that for my 40 years of coding :smiley:


Although it’s not a solution, it is progress. Good luck with the bug hunting. I’ve seen some doozies in the past that took a good few days to figure out. But it’s satisfying when you finally nail that sucker :slight_smile:

Just some clarification on Raycast logic:

  1. Non-inverted/ Raycast checks for an object instance within a certain distance. If one is found, it is validated as true, and that (first/nearest) object instance is picked for all event actions/subevents. If no object is found within the distance, it is treated as false
  2. Inverted Raycast does the exact same thing, except it checks for the furthest instance of an object within a certain distance. That furthest object instance is picked for all event actions/subevents. If no object is found within the distance, it is treated as false.
  3. Raycast within the advanced Not condition does the exact same checks as the above, but only proceeds if no objects are found within the distance at all. This also means no object instances are going to be selected from this condition. If you have actions that use an object in this event, it’s going to either apply to all instances of the object, or a random one, since there is no picked object list.
1 Like

So here’s what I’ve done/discovered so far:

  1. I added an action to tint the Squibble red that is chosen by the raycast (i.e. the only one that should be falling). All the Squibbles fall, and all are tinted red. That tells me the action that’s incorrectly setting everything to ‘falling’ is the one in the raycast event. Therefore the rest of my game should be fine.

  2. When I set the state of the raycast’s chosen Squibble to something else (e.g. ‘debug’, instead of ‘falling’), only one Squibble is changed (as it should be). I can’t explain why the ‘falling’ state makes a difference…
    image

  3. If I swap out the raycast condition with one that just selects the bottom Squibble based on its Y position, it’s then the only Squibble that falls. This tells me the raycast condition is doing something weird.

This looks like you have something going on with your source position variable or elsewhere in actions, because while you probably should be raycasting with Trigger Once as a condition, I’ve run a test and it only changes the tint on one object:

https://game-previews.gdevelop-app.com/1662038661066-385626/index.html
Events:


Preview:

I found it!

I added that wait to cause a slight delay between removing the blocks and setting the Squibbles falling. But I’m guessing it’s causing a bunch of asynchronous routines to spin up and run through the rest of the code, making all Squibbles fall instead of just one.

So I’ll need to find a new place for the wait, or just use a regular timer instead. But removing the wait from there seems to fix the issue!

Or use a trigger once on the condition.

Nice catch, btw. The wait action is a fairly recent addition to GDevelop, and I guess we’re still figuring out how it works.

This makes some sense, wait is asynchronous ,(doesn’t care about other events at all or even frames)which means it can behave weirdly.