0 Favourites

Picking Objects does not work inside functions

  • Problem Description

    You can`t compare instance variables of objects that has been set inside functions with the oficial Function plugin. Let`s say you create a function called SET that sets an instance variable value of a sprite to 1 (And logs it`s value)

    Then you create a function called GET that only logs the value of the instance variable. If you run SET and then GET after (Inside an On Start of Layout event) the SET will set the value and correctly log the value. The GET function that runs after will fail to log the value (Will log the old value stored in that variable)

    That being said... you can`t pick objects based on their instance variables unless you wait for the next frame. Waiting for the next frame is a terrible workaround. I`m uploading a capx with 3 tests. Only the test without any functions works as expected.

    Attach a Capx

    Description of Capx

    The capx has 3 tests where a "Card" object and a "CardImage" object are created on start of layout. CardImage stores inside itself the UID of the Card created. After that, the scale of both Card and CardImage are changed to 0.1. Test1 has two functions (SpawnCard and SetScale), Test2 has one function (SetScale) and the card is spawned "hard-coded" inside an On Start of Layout event. The Test3 is made without any function (So it does not support parameters without ugly go horse workarounds) but it works by successfully picking the right CardImage and resizing it. I`m not using containers for this because what I need is more complex and containers are too limited to this (Because they can only allow one instance of each object per Container Group)

    Steps to Reproduce Bug

    • Run the tests inside the capx

    Observed Result

    What happens?

    When using functions, events do not recognize the value of instance variables and fail to pick objects to change their scale. The SetScale functions just works correctly one frame after the objects Card and CardImage were created

    Expected Result

    What do you expect to happen?

    To work just like the Test3 without functions

    Affected Browsers

    • Chrome: (YES)
    • FireFox: (YES)
    • Internet Explorer: (NOT TESTED)

    Operating System and Service Pack

    Windows 10

    Construct 2 Version ID

    Construct 2 r244 64bits

  • Nevermind you're doing something weird.

    Objects don't really exist till the end of their event.

  • It's not a bug, you're just trying to do everything in one tick.

  • You can do everything in the same tick without functions and can't with functions. Objects DO exist at the time they are created.

  • Construct 3

    Buy Construct 3

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

    Buy Now Construct 3 users don't see these ads
  • Nevermind you're doing something weird.

    Objects don't really exist till the end of their event.

    I disagree (Run my Test3). Without functions you can freely modify a created object right after "Create Object" and everything will work just fine.

    If you have the SAME events inside a function it has the strange behavior of changing instance variables just inside the function context for that tick.

    Functions are useless if you have to wait 1 tick to access values modified by them.

    The problem extends not only for objects created in the same tick. If you have a simple function that changes an instance variable value of an existing object, log the new value inside the function and then log the value AFTER running the function you will see that the value is logged correctly ONLY inside the function. The log AFTER the function was called will log the old value until the next frame.

    This is either a bug or a terrible design

  • Actually they don't exist - fully. You can not pick, except by UID, until the next top level event after an object is created. There are countless threads on this - it is just part of the design.

  • Actually they don't exist - fully. You can not pick, except by UID, until the next top level event after an object is created. There are countless threads on this - it is just part of the design.

    With functions not even if you run the function in a separated "top level event" it will not work, you will have to wait until next frame. Without functions it works. Again... either a bug or a bad design

  • It will, but you have to pass in both UIDs and pick by UID.

  • When you create an object that object is picked for that event, and you can do anything you like to that object within that event, so long as the scope is within that tier, or sub tier of that tier. If you create a subevent on the same tier then it is no longer picked. Also, new instances will be picked, and old ones are taken out of the sol.

    If you wish to use functions then you must do something like call a system wait as it takes a tick to register for conditional picking.

    I don't consider the way it is as bad design. Its linear, and easy to follow. You create something, and then you talk about...

    On the other hand, calling functions to modify instances is like nightmare fuel.

    Imo, functions should only be called to reuse code, or to break picking.

    You're doing one of those things.

  • On the other hand, calling functions to modify instances is like nightmare fuel.

    Not being able to modify instances with reusable code is pretty much being left with limited useless functions, sadly.

    Any other professional engine let you instantiate and modify instances in the same tick at any point of the code as long as you call them after instantiating. That`s why it is a bad design of C2. For me it is a bug because that`s not how functions should work but it seems that it is just a terrible limitation of the engine

  • Might want to check out some of the other features such as the "on created" trigger, as well as containers.

  • For a game creation tool geared toward beginners this is a hard to understand and hard to explain quirk of picking. It has everything to do with when newly created objects are pickable.

    What Construct does is keep track of three seperate lists:

    object list (OL)

    new object list (NOL)

    selected object list (SOL)

    Before a event starts the SOL is the same as OL, and the conditions do picking that changes the SOL. So far so good, that's easy to understand.

    When an object gets created it isn't added to the OL right away. Instead it's added to the NOL and the SOL is set to just that new object. The NOL is only added to the OL at the end of a top-level event. Bear in mind a function isn't a top-level event.

    Also the pick by uid condition is special in that it can pick an object at anytime after it was created. This is the simplest way to just ignore this picking mess.

    Anyways that's a bit hard to follow so let's consider the examples in your capx.

    Test1

    global spawnedCard=0
    
    on "spawnCard"
    --- create card
    --- set card.carduid to card.uid
    --- return card.uid
    
    on "setScale"
    pick by comparison card.carduid = param(0)
    --- set card scale
    
    start of layout
    --- call "spawnCard"
    --- set spawnedCard to returnValue
    --- call "setScale" (spawnedcard, 0.1)[/code:3ee4rimf]
    
    [code:3ee4rimf]Start of layout is triggered and the lists are:
    OL=[], NOL=[], SOL=[]
    
    spawncard is called
    OL=[], NOL=[], SOL=[]
    
    card is created and before the function exits:
    OL=[], NOL=[card0], SOL=[card0]
    
    Back in the start of layout event
    OL=[], NOL=[card0], SOL=[]
    
    setscale is called
    OL=[], NOL=[card0], SOL=[]
    
    it tries to pick the card with pick by comparison condition but since the SOL is empty it fails.  The solution here would be to use the "pick by uid" condition.
    
    the function returns and the "start of layout" ends and since it's top-level the NOL is moved into the OL:
    OL=[card0], NOL=[], SOL=[]  [/code:3ee4rimf]
    
    Test2
    [code:3ee4rimf]on setscale
    pick card by comparison
    --- set card scale
    
    start of layout
    --- create card
    --- call setscale[/code:3ee4rimf]
    
    [code:3ee4rimf]start of layout triggered
    OL=[], NOL=[], SOL=[]
    
    new card created
    OL=[], NOL=[card0], SOL=[card0]
    
    setscale function called
    OL=[], NOL=[card0], SOL=[]
    
    pick by comparison attempted.  No objects in SOL to pick from so it fails. Again using "pick by uid" would fix this.
    
    function returns and start of layout ends:
    OL=[card0], NOL=[], SOL=[][/code:3ee4rimf]
    
    test3
    [code:3ee4rimf]Start of layout
    --- create card
    
    trigger once
    pick by comparison
    --- set card scale[/code:3ee4rimf]
    
    [code:3ee4rimf]Start of layout triggered
    OL=[], NOL=[], SOL=[]
    
    new card created
    OL=[], NOL=[card0], SOL=[card0]
    
    start of layout ends
    OL=[card0], NOL=[], SOL=[]
    
    trigger once starts.  The SOL is set to the OL.
    OL=[card0], NOL=[], SOL=[card0]
    
    card is picked by comparison.  This one works because the card we want is in the sol.[/code:3ee4rimf]
    
    The examples in your capx are fixed as i mentioned by using the "pick by uid" condition instead of "pick by comparison".  Again that's because "pick by uid" is special in that regaurd in picking newly created objects.  There are other situations where this picking is annoying to deal with, but in this case it's trivial.
    
    This behavior is a heavily ingrained part of how events work so I wouldn't count on it changing.  Also i do believe it was intentional to avoid some bugs, not to mention i'm not sure a better solution as it relates to the picking system is available.  I don't think something like this is very nice for beginners though.
  • Thanks for the clear explanation R0J0hound. This is a known quirk of the engine so closing as won't fix. FWIW, the reason we can't update the object list directly is because in many cases it would crash or deoptimise the engine. The quirk seems like a less bad option. Construct 3 also has a "pick last created" which helps work around it.

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