Glitchy behaviours just by objects being into a subfolder!!

  • *quote snip*

    I didn't mean "behaviors" in the sense of C2 Behaviors. I meant functionality (through events) shouldn't be affected by what folder something is in. Poor word choice on my part.

    The events are only being indirectly affected. The functionality change isn't related to the events at all. You get different results because the behaviors (both platforms and the sine) evaluate in a different order. This causes the positions of the objects to be different than they otherwise would when the event sheet is evaluated, which then changes the result of the conditions. You can see this when the player 'lags' behind the other sprites. The platform behavior attempted to solve this problem by doing its move logic in 'posttick' while other behaviors use 'tick', but all this really did was move the problem, which is made clear when you have a platform object stand on another platform object.

    There are ways that this could be changed so that you don't have to think about the tick order of behaviors, but I wouldn't expect to see them in Construct 2, what with Construct 3 being the primary development focus now.

  • The events are only being indirectly affected. The functionality change isn't related to the events at all. You get different results because the behaviors (both platforms and the sine) evaluate in a different order. This causes the positions of the objects to be different than they otherwise would when the event sheet is evaluated, which then changes the result of the conditions. You can see this when the player 'lags' behind the other sprites. The platform behavior attempted to solve this problem by doing its move logic in 'posttick' while other behaviors use 'tick', but all this really did was move the problem, which is made clear when you have a platform object stand on another platform object.

    There are ways that this could be changed so that you don't have to think about the tick order of behaviors, but I wouldn't expect to see them in Construct 2, what with Construct 3 being the primary development focus now.

    At the very least, it would be nice for this kind of stuff being consistent so we can work around it. This is pretty serious and I hope it gets fixed on Construct 2 -Construct 3 or not- since it can potentially break a lot of stuff, and kinda penalizes you for trying to be organizated.

    (I have no idea how Construct 2 works internally, but maybe it could be made so the folders are an editor only abstraction thing and doesn't get reflected on the final code in any way).

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • yeah, being able to specify in the events where behaviors tick would make the most sense. It's ridiculous that their order changes like this.

  • > *quote snip*

    >

    > I didn't mean "behaviors" in the sense of C2 Behaviors. I meant functionality (through events) shouldn't be affected by what folder something is in. Poor word choice on my part.

    >

    The events are only being indirectly affected. The functionality change isn't related to the events at all. You get different results because the behaviors (both platforms and the sine) evaluate in a different order. This causes the positions of the objects to be different than they otherwise would when the event sheet is evaluated, which then changes the result of the conditions. You can see this when the player 'lags' behind the other sprites. The platform behavior attempted to solve this problem by doing its move logic in 'posttick' while other behaviors use 'tick', but all this really did was move the problem, which is made clear when you have a platform object stand on another platform object.

    There are ways that this could be changed so that you don't have to think about the tick order of behaviors, but I wouldn't expect to see them in Construct 2, what with Construct 3 being the primary development focus now.

    C2 doesn't export objects in folders, it's all in xml files, where they're stored in the order they've been created, regardless of the "folder" they're tracked in through the IDE.

  • >

    > > *quote snip*

    > >

    > > I didn't mean "behaviors" in the sense of C2 Behaviors. I meant functionality (through events) shouldn't be affected by what folder something is in. Poor word choice on my part.

    > >

    >

    > The events are only being indirectly affected. The functionality change isn't related to the events at all. You get different results because the behaviors (both platforms and the sine) evaluate in a different order. This causes the positions of the objects to be different than they otherwise would when the event sheet is evaluated, which then changes the result of the conditions. You can see this when the player 'lags' behind the other sprites. The platform behavior attempted to solve this problem by doing its move logic in 'posttick' while other behaviors use 'tick', but all this really did was move the problem, which is made clear when you have a platform object stand on another platform object.

    >

    > There are ways that this could be changed so that you don't have to think about the tick order of behaviors, but I wouldn't expect to see them in Construct 2, what with Construct 3 being the primary development focus now.

    >

    C2 doesn't export objects in folders, it's all in xml files, where they're stored in the order they've been created, regardless of the "folder" they're tracked in through the IDE.

    Dude, I know that. I regularly edit the xml myself when I want to change something in a way that the editor won't allow (like moving a member variable between an object and a family).

    To clarify on what Construct 2 does on export, it goes through the xml tree and assigns ID values to the object definitions. Presumably, it assigns them sequentially in the order that it finds them, and this order can be changed by moving objects into subfolders (<object-folder> elements in the xml). These ID numbers are how construct 2 refers to object definitions at runtime, and they can affect the order that behaviors are ticked.

    This is also why you can't create objects by name, as the names you assign in the editor don't exist anymore at runtime.

  • Changing the subfolder an object is in does not change the order in which they're stored in the XML file, or it's ID. You can look at the XML files to see this.

    As for "presumably" - yeah. No. Presumptions don't help solve the issue. Especially when they're not accurate.

  • Changing the subfolder an object is in does not change the order in which they're stored in the XML file, or it's ID. You can look at the XML files to see this.

    Example project posted in this thread without modification:

    <object-folder>
      <object-folder name="New folder">
        <object-type name="Player" sid="461099846823012">
          <plugin id="Sprite" />
          <behaviors>
            <behavior-type name="Platform" sid="684013238865744">
              <behavior id="Platform" />
            </behavior-type>
          </behaviors>
          <animation-folder>
            <animation framecount="1" loop="0" name="Default" pingpong="0" repeatcount="1" repeatto="0" sid="754574662893683" speed="5">
              <frame duration="1" hotspotX="0.5" hotspotY="0.5" />
            </animation>
          </animation-folder>
        </object-type>
      </object-folder>
      <object-type name="Sprite" sid="251897685913489">
        <plugin id="Sprite" />
        <behaviors>
          <behavior-type name="Solid" sid="227558398387300">
            <behavior id="solid" />
          </behavior-type>
          <behavior-type name="Sine" sid="717431858105516">
            <behavior id="Sin" />
          </behavior-type>
        </behaviors>
        <animation-folder>
          <animation framecount="1" loop="0" name="Default" pingpong="0" repeatcount="1" repeatto="0" sid="639043081041614" speed="5">
            <frame duration="1" hotspotX="0.5" hotspotY="0.5" />
          </animation>
        </animation-folder>
      </object-type>
      <object-type name="Sprite2" sid="619511337493328">
        <plugin id="Sprite" />
        <behaviors>
          <behavior-type name="Platform" sid="399711601778041">
            <behavior id="Platform" />
          </behavior-type>
          <behavior-type name="Solid" sid="383344487100023">
            <behavior id="solid" />
          </behavior-type>
        </behaviors>
        <animation-folder>
          <animation framecount="1" loop="0" name="Default" pingpong="0" repeatcount="1" repeatto="0" sid="961475536146256" speed="5">
            <frame duration="1" hotspotX="0.5" hotspotY="0.5" />
          </animation>
        </animation-folder>
      </object-type>
      <object-type name="Text" sid="599919735085155">
        <plugin id="Text" />
      </object-type>
    </object-folder>
    [/code:2vqbv2n9]
    
    After moving player object out of subfolder:
    
    [code:2vqbv2n9]
    <object-folder>
      <object-folder name="New folder" />
      <object-type name="Sprite" sid="251897685913489">
        <plugin id="Sprite" />
        <behaviors>
          <behavior-type name="Solid" sid="227558398387300">
            <behavior id="solid" />
          </behavior-type>
          <behavior-type name="Sine" sid="717431858105516">
            <behavior id="Sin" />
          </behavior-type>
        </behaviors>
        <animation-folder>
          <animation framecount="1" loop="0" name="Default" pingpong="0" repeatcount="1" repeatto="0" sid="639043081041614" speed="5">
            <frame duration="1" hotspotX="0.5" hotspotY="0.5" />
          </animation>
        </animation-folder>
      </object-type>
      <object-type name="Sprite2" sid="619511337493328">
        <plugin id="Sprite" />
        <behaviors>
          <behavior-type name="Platform" sid="399711601778041">
            <behavior id="Platform" />
          </behavior-type>
          <behavior-type name="Solid" sid="383344487100023">
            <behavior id="solid" />
          </behavior-type>
        </behaviors>
        <animation-folder>
          <animation framecount="1" loop="0" name="Default" pingpong="0" repeatcount="1" repeatto="0" sid="961475536146256" speed="5">
            <frame duration="1" hotspotX="0.5" hotspotY="0.5" />
          </animation>
        </animation-folder>
      </object-type>
      <object-type name="Text" sid="599919735085155">
        <plugin id="Text" />
      </object-type>
      <object-type name="Player" sid="461099846823012">
        <plugin id="Sprite" />
        <behaviors>
          <behavior-type name="Platform" sid="684013238865744">
            <behavior id="Platform" />
          </behavior-type>
        </behaviors>
        <animation-folder>
          <animation framecount="1" loop="0" name="Default" pingpong="0" repeatcount="1" repeatto="0" sid="754574662893683" speed="5">
            <frame duration="1" hotspotX="0.5" hotspotY="0.5" />
          </animation>
        </animation-folder>
      </object-type>
    </object-folder>
    [/code:2vqbv2n9]
    
    Clearly, the player object has moved, and as such, the order has changed.
    
    
    

    As for "presumably" - yeah. No. Presumptions don't help solve the issue. Especially when they're not accurate.

    You reeeaaally don't want to go there.

  • And here's why.

    data.js object definitions from unmodified example:

    [
    		["Player", 1, false, [], 1, 0, null, [["Default", 5, false, 1, 0, false, 754574662893683, [["player-default-000.png", 825, 0, 0, 0, 0, 1, 0.5, 0.5, [], [], 0]]]], [["Platform", 2, 684013238865744]], false, false, 461099846823012, [], null],
    		["Sprite", 1, false, [], 2, 0, null, [["Default", 5, false, 1, 0, false, 639043081041614, [["sprite-default-000.png", 825, 0, 0, 0, 0, 1, 0.5, 0.5, [], [], 0]]]], [["Solid", 3, 227558398387300], ["Sine", 4, 717431858105516]], false, false, 251897685913489, [], null],
    		["Sprite2", 1, false, [], 2, 0, null, [["Default", 5, false, 1, 0, false, 961475536146256, [["sprite2-default-000.png", 825, 0, 0, 0, 0, 1, 0.5, 0.5, [], [], 0]]]], [["Platform", 2, 399711601778041], ["Solid", 3, 383344487100023]], false, false, 619511337493328, [], null],
    		["Text", 0, false, [], 0, 0, null, null, [], false, false, 599919735085155, [], null]
    	]
    [/code:3mxbgrbl]
    
    data.js object definitions after moving the Player object out of the subfolder:
    
    [code:3mxbgrbl]
    [
    			["Sprite", 1, false, [], 2, 0, null, [["Default", 5, false, 1, 0, false, 639043081041614, [["sprite-default-000.png", 825, 0, 0, 0, 0, 1, 0.5, 0.5, [], [], 0]]]], [["Solid", 2, 227558398387300], ["Sine", 3, 717431858105516]], false, false, 251897685913489, [], null],
    			["Sprite2", 1, false, [], 2, 0, null, [["Default", 5, false, 1, 0, false, 961475536146256, [["sprite2-default-000.png", 825, 0, 0, 0, 0, 1, 0.5, 0.5, [], [], 0]]]], [["Platform", 4, 399711601778041], ["Solid", 2, 383344487100023]], false, false, 619511337493328, [], null],
    			["Text", 0, false, [], 0, 0, null, null, [], false, false, 599919735085155, [], null],
    			["Player", 1, false, [], 1, 0, null, [["Default", 5, false, 1, 0, false, 754574662893683, [["player-default-000.png", 825, 0, 0, 0, 0, 1, 0.5, 0.5, [], [], 0]]]], [["Platform", 4, 684013238865744]], false, false, 461099846823012, [], null]
    		]
    [/code:3mxbgrbl]
    
    In case you haven't noticed, the order these are stored in matches the order in the XML 1:1. The ID numbers used in the runtime are the indices into this array. The object names only exist unmodified in preview. In exported projects, they are replaced with t0, t1, t2, etc.
    
    Care to tell me I'm wrong now?
  • Sorry for taking so long to get round to this, the launch of C3 has been manic.

    The original .capx is not a very good case - it relies on Platform + Solid on the same object, which has never been a directly supported case in the engine. The engine treats objects as either a moving object or an obstacle; you shouldn't use both. (I might actually block this case in C3 since it's not supported and people keep doing it.) I'd appreciate a different example .capx that shows a similar problem without using this not-really-supported case.

    If we investigate the .capx anyway, the problem comes down to the order of ticking behaviors. Platform has special code to say "if on a moving platform, move with it". Since the .capx uses the unusual case of a platform and a solid, and then another platform on top, it creates a 2-link chain, and the order of updates becomes important. If the bottom object ticks first, it moves to follow the platform, then the top object ticks and follows the bottom object, and everything worked OK. However if the top object ticks first, the bottom object has not moved so it stays where it is. Then the bottom object ticks and moves away to follow the platform, causing a gap to form between the two, which is the problem here.

    There is no obvious way to fix this problem, because we have to tick the behaviors in some order. Any changes we make would just move the problem somewhere else. If we sort by the object name and tick in that order, then renaming objects can change the tick order. If we tick in the order objects were created in the editor, then deleting and recreating an object can change the tick order. There's no gold standard tick order that is the "correct" one. I am also against letting the user customise the tick order; micro-managing such obscure parts of the engine is the exact opposite of the design principles that has made Construct successful.

    I'm also not convinced this is actually a serious problem - C2 has been out ~6 years and we've only just had a report involving an obscure case of using platform and solid at the same time (which is why I'd be interested to see a more convincing example). For the most part, the order behaviors tick in shouldn't matter.

    Even if this does affect a number of projects, it's not clear what to do about it. We have to choose some order to tick behaviors, and that order can probably be changed by something the user does.

  • The original .capx is not a very good case - it relies on Platform + Solid on the same object, which has never been a directly supported case in the engine. The engine treats objects as either a moving object or an obstacle; you shouldn't use both. (I might actually block this case in C3 since it's not supported and people keep doing it.) I'd appreciate a different example .capx that shows a similar problem without using this not-really-supported case.

    Thanks for your anwser, Ashley. But I think you should reconsider your posture on Platform + Solid not working well together and maybe look into making them more compatible (or offering some alternative for solid platformer objects). Also blocking it on C3 could break a lot of old/current projects and negatively impact backwards compatibility.

    While I don't know the inner workings of Construct and assume it may be difficult to fix that incompatibility, think that stuff like pushable solid blocks (for wich using platform behaviour seems like the simplest and more obvious solution so they are affected by gravity, move around with Simulate control when pushed and interact with platforms) are actually a pretty common case on platformers (So there's the reason a lot of us keep doing it! ). Just to name a few examples, Spelunky, some Sonic games (like the first one) or even solid enemies you can stand on like in Super Mario Bros 2, and the list goes on and on.

    For what is worth, as far as I can tell platform + solid currently works pretty well anyways, except on this case (on a moving platform, wich on most games it probably would be considered a rare case)

  • There is no obvious way to fix this problem, because we have to tick the behaviors in some order. Any changes we make would just move the problem somewhere else. If we sort by the object name and tick in that order, then renaming objects can change the tick order. If we tick in the order objects were created in the editor, then deleting and recreating an object can change the tick order. There's no gold standard tick order that is the "correct" one. I am also against letting the user customise the tick order; micro-managing such obscure parts of the engine is the exact opposite of the design principles that has made Construct successful.

    Sure there is. In the Quake engine derived games, moving brushes used a special movement called MOVETYPE_PUSH. MOVETYPE_PUSH entities were responsible for pushing other entities if they were in the way, as well as moving entities that were resting on top of them. Adopting this to Construct 2 would require a few changes (such as being able to specify which objects can be "pushed"), but If you did this, and added a recursive check to it, developers would get the result they want, and the tick order wouldn't matter at all.

  • I am sure there are a number of non-obvious dependency chains, and if they are accidentally set in a circle of dependencies then that cannot be resolved. If you carefully design a game to use the correct attributes on the right kinds of objects as intended then sure, that works, but this is more an issue when you throw in a bunch of objects with various behaviors in a random combination and find there's a tick order dependency somewhere.

  • Platform and Solid are not officially supported?

    , That's a bit strange that construct 2 is shipping with features that are not officially supported in a presumably Full product

  • It is a pretty big issue as projects grow bigger and I am sure there is no need to remind you that people are still working on their years long projects started with C2. Which explains why symptoms like this are being reported now .

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