Containers and Pins Problem

  • I'm trying to create a simple popup which moves into view when a function is called. (A standard game hint for example)

    The object comprises of a background 'panel' and two pieces of text; a title and the text body for the message.

    The panel is a 'container' which contains the text objects and in my layout I have arranged then with the Title at the top and the text centred etc so it looks nice.

    When I run my function to create the object I pin those text objects to the panel background with an event/action.

    However, when I run the game and create the object, both text objects appear in the center of the panel and the layout is lost. It seems that when creating a new object that is a container (using event:On Created) C3 centers every child of that container and ignores the placement that was originally created for the object in the layout view.

    How can I fix this? This method seems quite over complicated and unreliable.


  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • [quote:18m3avq6]Placing objects in a container has the following effects:

    If one object in a container is created, every other object in its container is also automatically created.

    If one object in a container is destroyed, every other associated object in its container is also destroyed.

    If a condition picks one object in a container, every other associated object in its container is also picked.

    Containers do not care about layout arrangement. You should place and pin each object when any single object in the container is created (which creates all the other object in the container. You just need to add two extra actions to set the position. Imagepoints on your background object are useful for this, or you can use a specific offset from origin. I've shown both ways below.

    So on trigger:

    Spawn BackgroundPanelObject

    Set TitleTextObject to BackgroundPanelObject Imagepoint1

    Set BodyTextObject to position BackgroundPanelObject.X+10, BackgroundPanelObject.Y+30

    Pin TitleTextObject to BackgroundPanelObject

    Pin BodyTextObject to Background PanelObject

    All the correct relevant objects will be picked already because of the container, so it won't affect other tooltips if you have them on the layout.

  • Yeah, this is one of Construct's biggest limitations imo - the inability to build prefabs beyond containers. Workflows in Flash, Godot, Unity and Unreal lean heavily on this concept. I'm desperately hoping Scirra will implement a scene graph once the C3 runtime is up to snuff. The suggestion for that is already logged and has a ton of support from the community, and it sounds like they plan to look into it, but a few more votes wouldn't hurt... <img src="{SMILIES_PATH}/icon_e_wink.gif" alt=";)" title="Wink">

    In the meantime I have been looking into various ways to deal with this problem in my own project, which requires quite a few composite objects of the type you're describing. The suggestion to hard-code each one is the simplest and if you're fairly new to Construct or if you don't have many of these object groups that's what I'd suggest too.

    Another (considerably more complicated) method to consider if you want to push things further would be to build an object editor for your project. Basically you'd create a level editor, but for objects. The short and incomplete version is you'll loop through the objects in your group, then save the data for each object into an array or dictionary using a combination of the objects' names and the asJSON system expression. Then you'll write the array or dictionary to a file (you will need to export to NWjs for this). Then at runtime you can recreate the object(s) from the file(s) using AJAX to load the file, create object by name to grab each object name from your array, and loadfromJSON to set all their properties like position, etc. Finally you pin them together, if that's needed - this also requires you to track some kind of pin target uid when you create the objects.

    I would suggest using families for all this to make such things easier - for example, I'm using a "Serializable" family with an "ObjectType" variable to store the object names, and a "Pinnable" family with a Pin behavior for all the things that need to be pinned. This way you can use functions to simply get "Serializable.ObjectType" for every single object in your group, and loop through them more easily. I'm currently hard-coding what things in a group get pinned to based on their object types, but there is probably some good way to abstract this further with yet another family ("PinTarget" or something).

    Anyway, it's a little complicated and difficult to explain fully in a short paragraph like this, and it's probably overkill for your problem, but that's the basic idea.

  • Thanks for your feedback guys. In the end for my purpose I've just added a couple of lines of code on the creation process to manually move into position before the pinning takes place, but I will look at some of the other things you suggest (especially imagepoints which I never heard about).

    Many Thanks for your solutions, and lets hope this aspect of C3 will improve in the future.

    Personally I think if there was just a checkbox next to each object in a container which said 'Maintain Relative Position' and possibly more claririty on parent child relationships (like Unity) this would do.

    I also think that the 'Pin' behavior should have a 'Automatically Pin on Start Of Layout' checkbox so we didn't require separate actions for this all the time.

    Anyway. I will go cast my vote. Thanks

  • Cool, glad you settled on a solution that worked.

    Personally I think if there was just a checkbox next to each object in a container which said 'Maintain Relative Position' and possibly more claririty on parent child relationships (like Unity) this would do.

    I also think that the 'Pin' behavior should have a 'Automatically Pin on Start Of Layout' checkbox so we didn't require separate actions for this all the time.

    I love the simplicity and ease of use of your container suggestion. It has the disadvantage (which is really a disadvantage of containers, not your suggestion) that one would still need to create a set of unique object for every single combination of objects, even if some of the sub-objects look and behave identically. So if you have a bunch of slightly differently designed dialog boxes like the one you are making, and they all use mostly identical elements, like a text object, you'd need to make a different text object for every single container rather than having a single text object that can be reused all over the place. This is one place where containers fall apart compared to more sophisticated implementations like Unity has. All that said, I'd still kill to get what you just suggested.

    Unfortunately there is no parent child relationship in Construct per se right now, but you can however fake it a bit with pins and instance variables. The Pin behavior has "Pin.PinnedUID", which will return the UID of the object the Pin is attached to. So in a condition you could do something like Button -> PickByUniqueID -> Button.Pin.PinnedUID, and that will pick your frame. For the "parent" storing references to its children, you'd have to use an instance variable to store the child's UID. So you'd add "ButtonUID" number variable, and then when your button is being set up, either at runtime or design time, you'd do something like Frame -> Set Instance Variable -> Set ButtonUID to Button.UID. Then in the future you could use Frame.ButtonUID to pick the button if you needed to.

    And yeah, setting Pins at design time would be pretty handy for some situations. I found it confusing that this wasn't possible when I first started playing with Construct.

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