Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Broadcasts are not completed before rerun thus DeleteClone does not finish in time. #4143

Open
cvoinf opened this issue Dec 11, 2023 · 3 comments

Comments

@cvoinf
Copy link

cvoinf commented Dec 11, 2023

Expected Behavior

A broadcast should be completed before it gets induced again.

Actual Behavior

It seems that not all broadcasts are properly completed since not all clones are deleted by the end of my program
Scratch Project.sb3.zip

Steps to Reproduce

grafik

System Details

Linux Chromium, web-editor

@cvoinf cvoinf closed this as completed Dec 11, 2023
@cvoinf cvoinf reopened this Dec 11, 2023
@cvoinf
Copy link
Author

cvoinf commented Dec 11, 2023

I ran into this problem when I tried to simulate radioactivity:
https://scratch.mit.edu/projects/937805607
Perhaps there is another way to avoid the problem?

@cvoinf cvoinf changed the title Clones are not properly deleted Broadcasts are not completed before rerun. Dec 11, 2023
@cvoinf
Copy link
Author

cvoinf commented Dec 11, 2023

I've found a workaround:
Instead of deleting the clone, I just hide it and set a local variable "hidden" to true or 1.

Obviously, the "delete clone"-block does last too long.

grafik

@cvoinf cvoinf changed the title Broadcasts are not completed before rerun. Broadcasts are not completed before rerun thus DeleteClone does not finish in time. Dec 11, 2023
@towerofnix
Copy link
Contributor

towerofnix commented Dec 24, 2023

There are a couple misconceptions that are probably throwing your investigation off here.

First, "when I receive" is received by the original sprite too, not just its clones. So every time you broadcast "startDecay", the original sprite in addition to each of the clones runs the "when I receive" script. It performs the same random check, and when that check happens to be true, it runs "change NumberOfClones by -1" and "delete this clone". Now, "delete this clone" doesn't mean anything for the original sprite, so that block is just skipped. But "change NumberOfClones by -1" does work regardless who is running it. This means you sometimes count that variable down when you aren't actually deleting a clone, and so the "repeat until" loop exits earlier than you expect it to - some of the clones are still alive, but only because you stopped running the loop too early, not because of anything intrinsically different about the "delete this clone" block.

(It might be kind of confusing that the sprite or clone who is performing a broadcast receives and responds to its own broadcast! It's not terribly intuitive, necessarily, but this is just how Scratch has always treated broadcasts. In projects where you aren't using clones, you don't usually run into it, because your broadcasts are just for communicating from one sprite to another. But yeah, broadcasts start scripts in the same sprite/clone, too, not just others.)

Second, broadcasts are not supposed to complete before they run again. Your project actually isn't exhibiting this behavior at all ("delete this clone" really is instantaneous), but it is existing behavior in Scratch. The ability to cancel a "when I receive" script by broadcasting its message again is an intentional feature. See this project and this project for some examples. If you want to ensure a broadcast really has run all the way through before you broadcast it again, use "broadcast and wait" instead of "broadcast".

I don't know for sure but I have a guess that the reason your workaround works is simply that you've set the "hidden" variable to 1 for the original sprite (because it's, well, hidden). That means it never performs the random check, because it is already at the desired "hidden = 1" state - your "if hidden = 0, do random check..." means the random check will never be run for a sprite or clone whose hidden value is 1. That means, if your original sprite starts with hidden = 1, it never inadvertently counts down. (If it starts at 0, well, it will count down like a clone would, but only the one time, because then its own hidden variable will become 1. You should be left with exactly one clone leftover, instead of possibly several, like the original project.)

A common workaround is to give each clone a "clone ID" variable, with the original sprite always being ID = 0, and "when I receive" scripts that should only run for clones will have an "if clone ID > 0" at the top. Or you can just use a "am I a clone?" variable, which is false for the original sprite and true for clones, and check that in "when I receive" scripts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants