Tokinsom's Forum Posts

  • DiegoM Well, on the editor side at least it would still work "exactly" as Global Layers do—Create some layers on a dummy layout, set them to "Template" or whatever, and then when a user makes that same layer elsewhere, its properties and sublayers propagate from the master. Beyond that they're just your typical layers. I would think some of the global layer bones could be reused here, but you know better than me of course.

    To be frank, I know it sounds extreme the absence of this feature alone makes me consider different game engines for level-based games. It's been requested many times over the years and Construct users just deal with it. It's kind of a terrifying thought to have 100+ levels that are wholly unique on a technical level. It's just unwieldly.

    My current project only has 15 layouts, very large and dynamically loaded with scripts and zone objects, and it's already a big hassle to change up a few things with the layers.

    Imagine I had 100+ levels share parallaxing background layers and I decide I want to change the parallax values a little bit for all of them? There are plenty of very normal cases like this that shouldn't be days worth of work and risk a repetitive strain injury in my hand ^^;

  • Have you tried working with the .json files?

    It would take some pretty hacky scripts to batch process layout .jsons in this manner. Not to mention managing objects in some cases, sids, and it generally being an awful workflow.

  • Hey Ashley and DiegoM. I would like to discuss a long-standing issue I've had with Construct, and hope to resolve once and for all. In all my time using Construct engines the only solution I've found to this is meticulous planning, brute force, or utilizing an external level editor, but I think it's worth seeing how it can be addressed internally instead.

    Scenario

    Say you have a level-based game with a ton of levels. Demonoire is a good example, although a full-scale game will have magnitudes more!

    Each level is a layout.

    Each layout has a set of essential layers: background, tiles, objects, foreground, etc.

    ...But now you want to add, delete, move, or rename one or more layers.

    Existing Solution

    Your only option is to do this, by hand, for each level. Every single of them. Every time you want to refactor your layers in some way. Potentially hundreds or thousands of manual operations.

    Close-But-Not Solutions

    Global Layers are a way of solving a similar issue, where you want a static set of objects to appear in multiple layouts, like an HUD or Pause Menu. They do not, however, serve as a template to organize, manage, or refactor layers on a grand scale.

    Actual Solutions

    Recently, the layers bar was updated to display a global layer's sub layers, but they are grayed-out.

    Funnily enough, allowing us to place objects in those grayed-out layers, while leaving the master layers empty, would be a legitimate solution here.

    With this I'd be able to establish a global "LEVEL" layer, with background/tiles/objects/foreground as sublayers. Simply adding this "LEVEL" layer to each of my layouts gives me my template, and it can be easily refactored by adjusting the master layers.

    Of course, I understand that the layers are grayed-out to prevent unexpected behaviors. I only present this as one possible solution that utilizes the existing global layer system.

    Soooo maybe we can either...

    A) Keep everything as it is but give global sublayers an option to not be grayed-out in other layouts. An "only do this if you know why" kind of thing.

    B) Introduce an alternate type of global layer...perhaps a "Template Layer" that functions like a global layer but does NOT inherit the objects from the master layer, and whose sublayers are not grayed-out in other layouts.

    Ideally we'd still be able to, in any given layout, add a unique layer into this "template." This way you can have your basic level template but allow special cases where needed.

    Final Thoughts

    Of course there are maybe other solutions, I'm just trying to think within the box of existing systems. As noted, Global Layers are very close but serve a different purpose. I am not trying to inherit objects here, I just want a sort of Layer Template/Set that I can easily manage and refactor on a grand scale, saving me literal days of arduous work in some cases. Thanks for reading and I look forward to your response!

  • Listing all templates is also an interesting idea, but I think it's a slightly different use case. Should all those templates be in a separate section of the Project Bar? If so, there's still the problem of what happens when you drag in a new instance from the Object Types folder. Should templates appear as child items of object types in the Project Bar? If so presumably you can still drag from the object type itself, and the same problem comes up. So while I think that may well be worthwhile as well, it's probably best thought of as a separate addition.

    Templates should probably have their own root folder as they could also contain hierarchies comprised of numerous objects that may already be organized in a variety of folders, or object permutations that are best organized in their own way. Also, personally, I don't want a hired level designer for example rummaging through standalone objects—they would almost exclusively use the much safer and curated templates folder for all available object permutations with brown highlights alerting me of any values they change. Of course this varies with dev teams but that's how I would do it.

    I figured you'd want to leave the "non template default instance" alone in light of this solution. Yes it is a quirk, but the template folder is a way of solving it with templates as you wanted. The other template-involved method you suggested strikes me as a major case of crossing wires, especially with the likelihood of an upcoming templates folder. Perhaps I'm just not fully understanding it but it sounds confusing and doesn't actually address the issue because at the end of the day it's not actually changing the default instance, it's just creating a template called "default" and making it what is pulled from the project bar. This, again, will be extra confusing with actual templates in the project bar.

    So then I would still argue that the the instance that is pulled from the property bar object type can simply be determined via a right-click menu option on the instance you want. Call it a "Root/Prime/First/Initial/Editor" instance or something instead, I don't know. Solves the issue right at the core though without bloat or new workflows or involving templates at all, and lets the user change it on the fly, to boot.

  • Ashley skymen

    Thank you both for your insights. I'm glad we can have this discussion and I think we're on the right track.

    After considerable thought, I think Skymen hit the nail on the head and everybody wins with his proposition.

    None of this noise about default instances matters at all if we can just establish templates, default or otherwise, and have them all in neatly organized folders in the project bar.

    -It is hands down the most intuitive, safest, and versatile option.

    -It does not change or break anything for existing projects.

    -It does not interfere with anyone's usual workflow, they can decide if they want to use templates from the project bar or not.

    -There is no bloat or "hidden" functionality to it.

    -Has the added benefit of pulling hierarchies from the project bar. Essentially prefabs as Skymen noted.

    I'm fairly positive this is already a desired feature for many users, and it so happens to completely solve my longstanding "default instance" issue as well—in a very different way than I had expected—but one that is in fact actually better!

    What do you think?

  • > B) Make it so new instances pulled from the project bar automatically become replicas of the "default" template if it exists.

    This design makes it a bit of a hidden feature, and hard-codes an English string which isn't great for non-English users. What about a property to choose the default template name used for new instances? This seems like a good solution as templates are the feature intended to be used for determining initial properties.

    I agree that "B" is not ideal, and would still much prefer "A". I think the feature you mention here is a welcome addition to the template/replica system, but it is not a good solution for this particular issue. Please let me explain:

    My issue with your proposed solution is every single instance pulled from the project bar would then need to be manually set as a replica—an error-prone or easily forgotten step that my level designers should not be expected to do. I don't know that there is a suitable way to make that process automatic.

    Furthermore, it forces object instances to become part of the template/replica system which, yes, gives a similar result, but is a completely unnecessary workaround!

    Look, the "Default Instance" is already a real thing that Construct does automatically—It is not a new thing or new feature that I want. The problem is that it's ambiguous, most people aren't even aware of it, they have no control over it, and it's not explained in the manual. I am merely asking for a way to choose which instance it is.

    As such, I find it hard to understand any reasonings against a very simple and intuitive "Make Default Instance" button in the editor category (or in the right-click menu), with a tooltip like "Makes this the default instance", and a manual entry describing—at long last—that the default instance is the one that all new instances get their initial properties from. I understand that there is a little bit of overlap with the template/replica system, but that is simply not what is being discussed here and it's fair to trust Construct users to discern the difference.

    (For what it's worth, personally I think the template/replica system should be baked in to all objects, with the "default" template being the first instance, and the "default" replica being all instances that follow. This way we can easily determine and change the default instance, and automatically reap the benefits of the whole template/replica system. But that probably ain't happening!)

  • dop2000 Yes I agree the ability to copy JSON as plain text should remain. I propose this as an additional feature.

    I didn't mean it was literally read-only! Just that its form in the debugger isn't exactly suitable for modification. I have edited the OP to prevent confusion.

  • The Instances bar largely solves this.

    You can copy and paste an instance from it, or drag it into the layout to create a copy of it.

    Create sub folders to group the ones you know will be used frequently, that way you don't need to actually look for them in the layout.

    Respectfully, that is not an adequate solution. That's basically just copy/pasting a particular instance from one layout to another which is hardly a reasonable workflow, and completely ignores my already-well-organized object folder structure in the project bar.

    The project bar has an objects folder for a reason. I expect to be able to pull object instances from it with consistent results, and determine the default properties of said instances at will. This is the case with basically every game engine except Construct.

    The way Construct handles this is bizarre, unintuitive, and problematic especially when collaborating with a team over GitHub. I should not have to explain all of these oddities to them—they should be able to simply locate an object in the project bar, and pull an instance from it with initial properties that I chose by way of a default instance - NOT from the first instance ever created (or the second if it got deleted and so on.)

    I really hope I am getting my point across here. This editor design quirk has plagued me and my team for ages, and others too but we have "just put up with it" for so long. It can be very easily fixed with a simple button as described in the original post. Please give it your consideration.

  • Ashley

    When you pull a new instance out of the project bar, its initial properties are determined by the first instance ever created—I will refer to this as the "default instance."

    As such, most Construct users create an "Object Repository" and put the very first instance of an object in there, thus establishing the default instance for that object. Modifying this particular instance is the only way we can control the initial properties of new instances pulled from the project bar.

    The problem is if this default instance gets deleted, or was never established in the first place, then the initial properties of all future instances pulled from the project bar are determined by, essentially, a random instance elsewhere in the project. This is a very undesirable outcome and Construct provides us with no way of fixing it.

    Here is a great example of why this is problematic: Let's say I'm working on a level and go to pull a tilemap from the project bar, expecting a clean and blank "default" tilemap. Instead, it actually created a copy of a previous tilemap from another level! Now every time I want to use this tilemap, I have to erase all of the tiles and change its size first. Now extend this problem to literally every instanced object in the project! The only reason this happened is because a default instance was not established in the object repository...but now it's too late, the only way of fixing this is to delete every single tilemap instance and establish the default instance in the object repository, or somehow locate the first-ever instance and transfer that to the object repository.

    Technically yes I could create a template called "default" but I should not have to then go through the steps of making every single new instance a replica of it. This does not fix the core issue (and there's a bug where it doesn't work on tiles anyway).

    So I propose one of two solutions:

    A) Give the property bar a new "Make Default Instance" button in the "Editor" category. Clicking this ensures that all new instances pulled from the project bar start with the properties of this particular instance.

    B) Make it so new instances pulled from the project bar automatically become replicas of the "default" template if it exists.

    I have made a suggestion for this here but this is such a frustrating and longstanding editor quirk that I am hoping to bring it directly to your attention here first.

    https://github.com/Scirra/Construct-feature-requests/issues/405

  • Ashley

    In the debugger, arrays & dictionaries get a nice little interface to view and modify values. This is incredibly useful for a variety of reasons—I need not state the obvious!

    So then why does JSON—the generally superior alternative that can do both arrays and dictionaries of its own—not get any similar functionality? It is treated as a big, ugly, condensed, plain text string that is practically impossible to navigate or modify in any meaningful way.

    I'm well aware that JSON is often used as static data, but it is equally useful as dynamic runtime data (and can be substantially cleaner and more organized than a mountain of separate array & dictionary objects) yet this side of it has gone completely ignored.

    As such, I implore you to consider a sort of "JSON Tree View" inside the debugger with modifiable values. I have made a feature suggestion with additional reasonings and details here: https://github.com/Scirra/Construct-feature-requests/issues/356

  • Note that in general if you have a feature request you can submit it here.

    I suggested this like 4 years ago and it got tons of upvotes 🥴

    Ain't happening.

  • That sounds about right. There are still far too many things tied to the .c3proj to safely have more than 1 contributor add content to a project at a given time.

    The other killer is modifying objects that exist throughout the project. For example, if Contributor A adds a variable to an object which exists in all layouts, then all of those layout files get updated. This means no other contributor can edit any one of those layouts without resulting in a conflict.

    At least, that's how I remember it happening. Only solution there is Contributor A has to inform others about it so they can push & pull the new object variable before resuming work.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • Yeah this is an extremely long-standing issue with new pages in chrome defaulting to white. I've actually developed muscle memory to close my eyes when opening chrome/C3 for the first time lol. Apparently it's much more difficult to fix than one would think. I thought it only happened when entering a new domain, however...

    Searching something along the lines of "white flash when opening chrome" will give you a lot of results, but no permanent fixes it seems.

  • The new random UID option is a life saver. Thanks Ashley.

    It should only be a conflict if two people both try to commit changes at the same time that both affect the same line (e.g. both adding an object to the same folder).

    Ah you know what in all my testing I was just adding objects to the root objects folder, so that would explain that. Wouldn't introducing new effects/behaviors to the project go on the same line though? I will do some more testing...

  • Ashley

    It seems that C3 is still mostly unusable with source control on account of the .c3proj file and UID shuffling.

    The .c3proj

    If more than 1 collaborator adds a new behavior, effect, object type, family, layout, event sheet, script, or timeline, it modifies the .c3proj and creates a conflict. This might be the case with removing and renaming as well. This can be resolved by hand, but is obviously very error prone and can easily corrupt the project.

    As it stands, all users except one must basically only touch existing contents.

    I'm not the expert here but one potential solution that comes to mind is replacing the .c3proj entries with individual files and populating the project bar etc. from those instead (basic project properties can remain as one file). Each object already has its own .json file anyway so why not just extend this format to the aforementioned assets instead of making lists inside the .c3proj?

    UID Shuffling

    Furthermore, UID shuffling can be detrimental and risks breaking many things in your game or outright corrupting it. UIDs are the only auto-assigned reference that instances get which are identical in both the editor and runtime. They are often used extensively to manage objects in save data or managing connections between objects in and across layouts. The only alternative is manually-assigned instance variables but...imagine a Mario level with hundreds of coins per level or a Metroidvania with hundreds of items scattered throughout the world, each one given a manually assigned variable to prevent from respawning or what have you. That is just insane, but there are C3 users who are doing just that to prevent their objects' only real IDs from being scrambled.

    Again, not the expert here, but sequential UIDs might not be the safest approach. I believe skymen had proposed some sort of UUID but he would need to elaborate on that.

    Taking a quote from your GitHub tutorial: "Source control is widely regarded as mandatory for any kind of professional development." I strongly agree with this sentiment but as it stands even small teams cannot use C3 together with confidence. I see that improvements have been made over C2, we aren't quite there yet. If Construct 3 is to be viewed as professional software, especially with paid tiers and increasing prices, then its compatibility with source control needs to be locked in. Thank you for reading and I hope you give these issues your consideration.