Objects spawned in function don't exist after call?

Get help using Construct 2

Post » Tue Sep 23, 2014 12:50 pm

from the manual: The action then triggers the corresponding On function event (e.g. On function "CreateEnemy"), running the event's actions and any sub-events, before returning to the original Call function action and continuing from where it was.

so maybe it is a scope issue?? okay, now I'm confused to why Wait fixes it. Unless wait causes the proceeding events to happen after the tick? Wait 0 works and I assumed proceeding events were pushed to the end of the sheet, yet still in the same tick.

@blackhornet do you know why "wait" fixes it?
B
88
S
29
G
14
Posts: 1,158
Reputation: 15,011

Post » Tue Sep 23, 2014 2:03 pm

I'm not the person to ask "why" C2 does what it does ;)
ImageImageImage
B
71
S
21
G
221
Posts: 3,651
Reputation: 124,231

Post » Tue Sep 23, 2014 3:49 pm

A function is run as if it was instead placed where the function call was. Minus any picking. So it doesn't count as a toplevel event.

"Wait 0" is a fix since it waits to run the following actions and sub events till the end of the event sheet where created objects are pickable as normal.

As for what is happening consider

start of layout
---- create sprite

Before the event you can think of the state of the engine like this:
sprites=[0,1,2] // A list of all the sprite instances
picked=[] // A list of picked sprites
new=[] // A list of new sprites

Inside the event "picked" gets a list of all the sprite instances
sprites=[0,1,2]
picked=[0,1,2]
new=[]

The "create" action adds the the new object to "new" and picks only that.
sprites=[0,1,2]
picked=[3]
new=[3]

Then upon leaving the event the "new" list is moved to the "sprites" list:
sprites=[0,1,2,3]
picked=[]
new=[]

So the main point is the "new" list is only merged with the "sprites" list between toplevel events.
B
91
S
31
G
103
Posts: 5,241
Reputation: 67,768

Post » Tue Sep 23, 2014 6:04 pm

Wow @R0j0hound , that is a great explanation. I finally understand how this thing exactly work! Thanks! A post that deserve a bookmark!
B
28
S
8
G
4
Posts: 553
Reputation: 4,914

Post » Wed Sep 24, 2014 6:13 am

sorry @blackhornet you seemed to know since you said this has come up before.

thanks @R0J0hound - a nice visual explanation! So does Wait 0 sort of make the Function act like a top level event?
B
88
S
29
G
14
Posts: 1,158
Reputation: 15,011

Post » Wed Sep 24, 2014 9:44 am

I fought with the same problem as you and came up with a solution for not having to use waits, whether it will work in your case I don't know. But this is from that post (Its a bit long :)):

"-- First post --"
Think I might have found a solution to do it without using waits. However it does requires an extra check every tick. But if it works I think its worth it :D

The Idea is to use an object handler, that can handle all newly created objects.

You can make it with a list or array whatever you prefer. However you still need to organize the way you create objects according to the normal rules.

In my case it uses a list, the idea is that these objects that rely on other objects that might not be created yet during the cycle, are added to this list. And then you apply whatever extensions to them that you want. And its actually quite simple to make.

In my game the handler looks like this:
Image

Which in this case is the Quest_master_object that give me the problem. As its the one that rely on a Quest_step, which is a sub quest that are part of the master quest. To this Quest_step there is a dungeon attached. Which again is used to generate a random Quest description.

To use the object handler all you have to do, is tell it what action you want it to do, in form of a Boolean, and then add the UID to the list. And then hook it up to a function, or whatever you prefer.
Image

And you can just add as many conditions and objects to the object handler as needed. I think the benefit comes when you have to do something several times during one tick. For instant in my case I actually have to repeat it 5 times, but having to wait each time is first of all not something I like, but also seems to create problems, as sometimes the descriptions got mixed, some steps weren't made etc.

Anyway haven't tested it fully, but the initial tests seems to work very well, and now at least this problem is solved :D"

"-- Second post --"
Nice work. Looks pretty slick.

I was reading up on the thread that explains why picking works this way now, and I'm actually confused.
viewtopic.php?t=73647&start=0

In the thread, it is explained that the object doesn't exist to same-level events until the next top level event. Then how come pick by UID works on our tests?

Agree that it gets confusing, because its logic that you have created the object, so surely it must be there, but it actually ain't as explained by Ashley in that post.

A solution also from that post is:
The workaround is to try to do everything in the same event - nest the other events beneath the creating event if possible, so everything is moved up in to the green area.

Which are the reason that you can create an object and right afterwards set its variables.

Create object
Set Object name = "Whatever"

That also means that you can pick UID of the object if its in a sub level of the create function.

But if you do it like this:

level 1: Create object
--------------Do something
Level 1: Pick Object with UID of the newly created object shouldn't work.

You have to reach a top level. (Now this post is from version r102, so its pretty old, but don't think a lot if any have changed.)

However the common way of dealing with this problem as you most likely know is to throw in a Wait of 0, 0.1 or 0.01 or whatever as it will then go through to the next tick and force it to reach a top level or what to say and then it works. Im not really sure how solid this actually is, it seems to work well with simple stuff, but if it gets a bit complex it seems to not really work well.

For instant if you have an event:

Repeat 10 times
------- Call function("Spawn enemy")

Function Spawn enemy
Create enemy()
Call function ("initialize enemy")

Function Initialize enemy
Call function ("Create enemy weapon")

Function Create enemy weapon
Create Enemy_weapon

Then suddenly things starts to go wrong as I see it.

Because now there are actually two objects that doesn't exist yet, The Enemy and the Weapon that you want it to use. So if you throw in a Wait different places to solve it, It might work. However at the very start we are actually repeating this 10 times, to create 10 enemies which will then create 10 different weapons, so suddenly you might have 20 objects that actually doesn't exist, and then it seems to go wrong. Whether that's completely true im not 100% sure about, but it seems that a function doesn't count as a top level, which I find to be logic if its the case, but I haven't seen anything saying that it ain't which is why im not certain.

As I mentioned in my last post, I had to repeat it 5 times, but I did something similar with 50 objects using a wait, and it looked like it was working fine, however as I went through the objects in the debugger I could see that suddenly some of the objects would have "NaN" in some of the variables. Which didn't make sense as 95-98% of them had no problems and all different possibilities for this variable was used, but for some reason some of them just failed, and my guess it that since I repeated it several times, it might have screwed up with the wait somehow. So the only thing I did, was to move the function call to the Object handler, didn't change any code and none of them had any problems after that, same goes for several other mistakes that was happening. So I moved those as well and now all of them gets initialized correctly, without having to use wait, which I think in itself is a huge benefit.

"--- end ---"

Also if this doesn't work, maybe you can use the "Wait for signal" which weren't available when the above was discussed, but you might be able to make it so it will not do anything to these objects you create before all of them are made, in that case you "Signal" it to continue.

jobel wrote:@R0J0hound - a nice visual explanation! So does Wait 0 sort of make the Function act like a top level event?

No, wait doesn't make anything a top level, it just forces C2 to go "around" so to speak, it will look like it might make a function a top level. But in fact it could be anything else and most likely Is something else. And also as mentioned it the last part of my "Second post" you will most likely end up with things that seems to work but at some point it will probably give you weird problems, that are not easy to fix, as you "loose" control when using wait 0, 0.1 etc., At least that's my experience and why I never use them.
B
44
S
11
G
2
Posts: 1,182
Reputation: 6,828

Post » Thu Sep 25, 2014 7:03 pm

@nimos100

yeah I don't know about this, seems heavy handed when you can probably just rearrange how you do things; initialize all the relative objects within the same event umbrella. Because we aren't really talking about anything other than initialization or rather, things that happen only once. Otherwise a reoccurring event will catch up with no noticeable problem.

Not saying your object handler won't work, it's just maybe not very practical? I don't really know, I'd have to see a situation where you couldn't keep created object references together.

In those examples of Create Enemy, Initialize Enemy, GiveEnemyWeapon. You could still have those functions perform actions and have the function return a result you could apply to the newly create object within the same event nest.
B
88
S
29
G
14
Posts: 1,158
Reputation: 15,011

Post » Thu Sep 25, 2014 7:26 pm

Since there's actually one condition that doesn't have any issue in picking newly created objects, I suggest that we all abuse the hell of it. You'll find attached a simple "hack", that use an array to remember newly created objects of a specific type. I suppose it could be modified to handle multiple object types, but I only wanted to show the simplicity of this method. I personnaly prefer that to using "Wait 0" since the order of the events is then easier to follow.
You do not have the required permissions to view the files attached to this post.
B
67
S
28
G
24
Posts: 970
Reputation: 18,675

Post » Thu Sep 25, 2014 7:43 pm

jobel wrote:@nimos100

yeah I don't know about this, seems heavy handed when you can probably just rearrange how you do things; initialize all the relative objects within the same event umbrella. Because we aren't really talking about anything other than initialization or rather, things that happen only once. Otherwise a reoccurring event will catch up with no noticeable problem.

Not saying your object handler won't work, it's just maybe not very practical? I don't really know, I'd have to see a situation where you couldn't keep created object references together.


I agree its not practical in any way, its merely a solution to the wait problem :D And it will work in any situation where you would normally solve the problem with a wait. But maybe I misunderstood your situation.
B
44
S
11
G
2
Posts: 1,182
Reputation: 6,828

Previous

Return to How do I....?

Who is online

Users browsing this forum: bluesun66, Centra, Yahoo [Bot] and 3 guests