GMS 2 NEW 2.5D (Fake 3D) Depth Sorting - Grid Layers

Discussion in 'Programming' started by MirthCastle, Jul 17, 2018.

  1. MirthCastle

    MirthCastle Member

    Joined:
    Mar 26, 2017
    Posts:
    147
    Hey ALL!

    I wanted to give a shout out to a new 2.5D sorting system I made I call Grid-Layers. :)

    Here is a Presentation File that says what it is: (This is in the video, but I wanted to provide it separate too)
    https://www.dropbox.com/s/jea942d31g6ta2q/GMS2_DepthSystem.pdf?dl=0
    (don't use my PDF without creds!) :cool:

    Grid-Layers works by using a ds_grid to store a reference to a code created layer_id for each Y (depth) of the room. This makes it very easy to move our objects between layers without strings.

    What's more!? The whole system works without having to override any draw_events. YES! We get our draw_events back!!!!

    All of the layers are created dynamically at room start, so no messing with the room editor beyond initial setup. This system also allows for using the room editor layers as normal, so you can add as many layers as you want in the room editor to make your game the way you imagined (barring skill level or course hahaha).

    Using the code created "real" layers means you can use all of the layer functions EG: turn them on and off, move them, and even add layer scripts etc. Especially in the case where you want to use multiple views - you can fairly easily disable these layers while the second view is rolling - thus cutting your draws in half.

    Here is a benchmark (with view culling)
    BenchMark_Long_WView.PNG
    This is with 500 instances in a 2048x2048 room, 7 AI bots, and a Player. About 1/3 of the instances are grass objects that sway back and forth when you collide with them.

    The system above really kicks into high gear because I use the view to deactivate all of the "Static" instances when they are out of the view, and for the "Active" instances, I switch off their Draw_Events (can't see them anyways!). :)

    Here is the benchmark (w\o view culling)
    BenchMark_Long_NOView2.PNG
    STILL super fast (Using the view to cull instances per the tutorial is highly recommended)...

    Once we have our instances place themselves on one of these code-created layers they stay there until they move up or down. Static objects only get sorted once (at creation), while active objects only sort when they move up or down.

    That means there is no looping the grid, or the layers, or sorting! Everything is handled automatically by the regular draw-pipeline the Layers and GMS2 use. If a Layer is empty, it is simply skipped. If it has instances, they are all batched and drawn without any further lookups.


    Youtube Tutorial:


    Here is the Template:
    https://www.dropbox.com/s/uz4s11geprq93wo/Grid_Layers_Template.zip?dl=0

    p.s. The video is my first one ever - I could use come constructive criticism on it please. Is the voice too quiet?? I can't tell - i've listened to it 500 times... I can hear it without volume anymore lolol.

    p.p.s. @Ariak - Would you be willing to add this to the list of sorting systems on your post? I can provide finished version for you to test.

    @Nocturne - It wouldnt let me put this in tutorials?.. wouldn't this go in tutorials?

    Many thanks to @FriendlyCosmonaut - She really helped me get all the pieces together to make my first video. Everything from what programs to use to video making advice. She is super cool! I appreciate all the help Friendly!
     
    Last edited by a moderator: Sep 13, 2018
    Rob, Momfus, NeZvers and 5 others like this.
  2. MirthCastle

    MirthCastle Member

    Joined:
    Mar 26, 2017
    Posts:
    147
    Thank you all for being so kind and receptive!
     
    Last edited: Jul 18, 2018
  3. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    1,036
    It looks good! I'm not sure exactly what it does but I get the jist of it :)
    It seems like your overriding gm's built in system for(n) and making it a hell of alot faster, nothing new lol! but this isnt a negative against you, the opposite lol (yyg, sort your sh** out)
     
    MirthCastle likes this.
  4. MirthCastle

    MirthCastle Member

    Joined:
    Mar 26, 2017
    Posts:
    147
    Thanks for the feedback!!! I think I get the jist of what you are saying too - I don't think i actually say in the whole post what it actually does! hahaha (fixing that)

    Check out the PDF - I break it all down in there too.
     
  5. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    1,036
    Cool cool, I think I get the jist of what your saying too :) But it sounds like a classic thing where someone makes something with gamemaker that those scotish people didnt think of : '))))
     
    MirthCastle likes this.
  6. Edwin

    Edwin Member

    Joined:
    Jul 15, 2018
    Posts:
    417
    But you can use
    Code:
    depth = -y;
     
  7. MirthCastle

    MirthCastle Member

    Joined:
    Mar 26, 2017
    Posts:
    147
    Thanks Edwin! - However, depth =- y is depreciated and going away eventually - it uses "Managed" temporary layers - and they don't have half the features of real layers - Plus if you make your game with more than one view, you have no way to disable the instance from drawing on both views.

    Using the code created "real" layers means you can use all of the layer functions EG: turn them on and off, move them, and even add layer scripts etc. Especially in the case where you want to use multiple views - you can fairly easily disable these layers while the second view is rolling - thus cutting your draws in half.
     
    Last edited: Jul 17, 2018
    Edwin and Joe Ellis like this.
  8. TheSnidr

    TheSnidr Heavy metal viking dentist GMC Elder

    Joined:
    Jun 21, 2016
    Posts:
    475
    I'll give the video a watch when I'm done at work! I'm wondering though, what does this do differently from the z-tilt technique? The video prolly answers this question, but I'd like to know anyway :p
     
    Joe Ellis and MirthCastle like this.
  9. MirthCastle

    MirthCastle Member

    Joined:
    Mar 26, 2017
    Posts:
    147
    Thanks for the reply @TheSnidr - I did not address his system in my PDF because it uses shaders.

    It's a lot different though. It doesn't use GPU\Shaders, LayerScripts, or vertex buffers. There are no overrides either (like the alphablend on\off stuff in his). Nor did I do any testing against his for that reason.

    It leaves the whole draw_pipeline wide open for you to make your game by capitalizing on GMS2 normal behaviours. Instead of trying to recreate the whole draw pipeline yourself.
     
    Joe Ellis and Pfap like this.
  10. BPOutlaws_Jeff

    BPOutlaws_Jeff Member

    Joined:
    Jul 26, 2016
    Posts:
    48
    Really well done video! Sounds good and the visuals & extra text to pause & read make everything clear. Enjoyed seeing your Layer spreadsheet at 5:55 with examples of what kind of things would go on each layer too. I only had time to watch the first 10 min but I'm going to come back to watch the rest when I can sit down and pay close attention.
     
    atmobeat, MirthCastle and Joe Ellis like this.
  11. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    1,036
    It sounds incredibly logical! and something probably loads of us have overlooked.
    after reading the whole first post and taking it in properly and understanding it, This sounds like an actual Fernominom, (I cant spell it lol, even tho I can (I'm clever you see))

    This is actually pretty ground breaking, no wonder your nervous!
    but i can relate to that cus i just released my 3d game engine on the marketplace (SHAMELESS advertising! I dont care!. if people buy it thats good for me, if they dont then i'll just have to stay on wellfare cus of my autism
     
    MirthCastle likes this.
  12. MirthCastle

    MirthCastle Member

    Joined:
    Mar 26, 2017
    Posts:
    147
    OMG thank you guys for all this positive response! Many thanks to @Nocturne and @GMWolf for prodding me into start posting on here.

    @BPOutlaws_Jeff - serious high five
     
    Joe Ellis likes this.
  13. Pfap

    Pfap Member

    Joined:
    Apr 30, 2017
    Posts:
    552
    I really like the pdf and any documentation that can be consumed at your own pace without pausing and rewinding is generally what I prefer. I did skim through your video to see it in action and it seems good. From the pdf I understand what is going on and all the diagrams are helpful. I've never made a game where I needed depth sorting; I have a top down game in the works though, and from your presentation I'm sold.

    Is there a way to exclude layers from the depth sorting? I have my collision "walls" on a tile layer and they are always invisible. Maybe you answered it already and I just overlooked it.

    Anyways, in my current project I'm using a mix of depth and layers and I really should think about switching over to layers completely. So I'll have to give your content another look when I'm ready :)
     
    MirthCastle and Joe Ellis like this.
  14. BPOutlaws_Jeff

    BPOutlaws_Jeff Member

    Joined:
    Jul 26, 2016
    Posts:
    48
    This is the main difference that caught my eye, not having to use a draw controller object and basically remake the draw pipeline lol I'm not a very advanced coder so hopefully the more skilled coders can check this out and give their thoughts on it :)
     
    MirthCastle and Joe Ellis like this.
  15. MirthCastle

    MirthCastle Member

    Joined:
    Mar 26, 2017
    Posts:
    147
    @Pfap - Yeah it's addressed in the PDF and Video - Game Maker (for lack of a better term) "Skips" layers where there isn't anything to draw automagically.

    You can also through code set that specific layer to disabled if you like.

    layer_set_visible(layer_id, visible);

    you only have to do that once at the beginning. This will tell the layer to skip all of the draw_events for that layer, while keeping all the layer data.

    I would use a static "room_created" layer for your collisions (that's what i do), and not one of these dynamic layers btw.
     
    Joe Ellis and Pfap like this.
  16. Pfap

    Pfap Member

    Joined:
    Apr 30, 2017
    Posts:
    552
    Yes, I've been coding for a few years and I'm sure if I gave shaders some time I could figure them out, but it does seem rather daunting at times.
     
    Joe Ellis and MirthCastle like this.
  17. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    1,036
    Well I can, I;'ve made a whole 3d rendering system thats faster than any alternative, and this is Flawless!
     
    TheSnidr and MirthCastle like this.
  18. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    1,036
    Shaders are easy once you learn how to code them, honestly theyre alot easier than game code, cus theres normally one objective thing that you want to do,, just work out how to do it and your sorted!
     
    MirthCastle and Pfap like this.
  19. MirthCastle

    MirthCastle Member

    Joined:
    Mar 26, 2017
    Posts:
    147
    edited
     
    Last edited: Jul 17, 2018
    Joe Ellis likes this.
  20. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    1,036
    edited
     
    Last edited: Jul 17, 2018
    MirthCastle likes this.
  21. MirthCastle

    MirthCastle Member

    Joined:
    Mar 26, 2017
    Posts:
    147
    edited
     
    Last edited: Jul 17, 2018
  22. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,496
    Oh cool! Depth sorting is always tricky business so I will have to check out this video!
    Thanks for sharing!
     
    MirthCastle likes this.
  23. Pfap

    Pfap Member

    Joined:
    Apr 30, 2017
    Posts:
    552
    Gotcha, but just to clarify if I made a "room_created" layer and then unclicked the eye icon in the room editor it would have the same effect as setting it in code? I guess, my question is that what if the player character gets onto the layer I have set as being invisble? Wouldn't that make the character invisble too? I haven't worked with layers yet, besides swapping backgrounds for a puzzle game; so you could say I have a "bit" to learn lol.
     
  24. Ariak

    Ariak Member

    Joined:
    Jun 20, 2016
    Posts:
    91
    Hey @MirthCastle ,
    nicely done! The tutorial goes into a lot of detail.

    If I were to give your technique a name I would call it `layer=-y`, as at its core it simply replaces the depth component of depth=-y with layers in a grid.
    As you've pointed out, under the hood gms2 will create and drop engine managed layers when using depth. In GMS2 these depths are also forced to be integers (as opposed to gms1), implying that all objects placed at the same depth end up on the same layer.

    Youre technique nicely phases out the old system of depth, and replaces it with user, rather then engine manage, layers - and opens up the functionality this entails (mostly layer scripts). Consquentially you forgoe any gml sorting and nicely tie into the existing gm-engine sorting in the background, which is miles faster then anything we could code in gml. You would still need a controller object / some code to run on create to assing layer sprites to their correct layer on room start.

    Aside from the gained new functionality of user managed layers, this system should be on par with depth=-y in terms of speed. We trade some engine side managed_depth_layer checking for an additional ds_grid lookup.
    Even without any testing I can definitely see this being much faster than my binary list approach. I will definitely make an edit to my depth sorting post and link here.

    These days I mostly use the binary list for general purpose sorting since it beats priority lists (provided all elements are supplied in advance > sort once > read out all elements).
    Binary list... odd name for that really... should be bitwise since I merge two values into one using bitwise logic for sorting and then inverse the operation once sorted... what have i done...

    Now the comparison between ztilt and your system is another beast entirely, since the usecases are very different.
    `layer=-y` is perfect for all games that operate on a single level of height, which lets face it are almost all GM 2.5d games. The world is flat, the player, can not really walk up and down. The assets make us believe we see the world from an angle and want some depth ordering to not break the illusion.

    I had to implement ztilt/billboarding in my game because it operates on multiple levels of height. There is a z-axis and the player can move up or down. If we used flat images in the correct order we would very quickly break this illusion. My ztilt blog post has a little gif on this that demonstrares why for my purposes depth or layer-=y wont work ( i called it "narrow canyon problem" in the blog: https://www.yoyogames.com/blog/458/z-tilting-shader-based-2-5d-depth-sorting). You could in theory get around this by creating MANY tilelayers for every Y position - and god forbid some people have actually done that...- but this is obviously extremely memory hogging.

    While being difficult to set up and requiring some more advanced GM knowledge, especially in regards to 3D, ztilt allows for some amazing stuff that depth=-y equivalents do not. A major downside to depth-=y comes into play when we deal with elements from mutliple texture pages or we want to set shaders for some of our objects. As they are drawn in order of depth we get plenty of cases where we draw a tree > player > tree > player > tree > particle effect > object with shader > tree etc. Changing the draw setting back and forth all the time is very time consuming (breaking batches by texture swaps, setting /unsetting shader, etc.). Using 3D the ztilt system is able to draw all tiles, then all trees, then all the characters. Regardless of how many players/trees there are, we need only change the draw settings a fixed number of times. Static geometry can also be submitted as one single vertexbuffer (eg thousands of grassblades), which we cannot do in depth=-y. Instead we would need a vertexbuffer per y coordinate to uphold the order - I advise not going down that road.... :) Pulling of silhouetting with ztilt is also rather striaght forward, and we do not need to rely on an masking surfaces, which require redrawing all the masking assets.
    I will not make a statement about speed of the two methods in comparison, since it depends on way too many factors. For my personal usecase, especially with grass vertexbuffers and the narrow canyon problem in mind ztilt is powerful and provides extra functionality that depth=-y simply does not.

    To sum it up: ztilt is great for multiple levels of height and some more advanced render pipeline design - if you know its limitations and are fine with them.
    For anything else I would defintely recommend rolling with your system, especially since its very beginner friendly. Owing to its similarity to depth=-y long time gm users will feel right at home. The responses in this thread so far clearly show that! :)

    p.s.: showing us the fps in the debugger is no indication of performance, as this is super dependant on what kind of pc you have. Make a direct comparison to other systems instead. The view optimization is a nice addition, but does not mean one system is faster over the other, since it can be applied to all of them. I did mention this a couple of times in the post you where referring to: https://forum.yoyogames.com/index.p...rity-list-nested-list-grid-binary-list.13425/
     
    Last edited: Jul 17, 2018
  25. MirthCastle

    MirthCastle Member

    Joined:
    Mar 26, 2017
    Posts:
    147
    @Ariak - Thank you for the nice long post! Ill have to digest further it soon as I get off work. I really appreciate the time and effort you put into it.

    I wanted to jump in right away for this:
    :eek: I think it is important we do NOT call it layer=-y (it is not, but I understand your thought) because that may crash GameMaker (and simply won't work) trying to sort to a layer that may not exist. So pretty please lets not call it that because that is an oversimplification, and I don't want folks getting the wrong idea or crashing their game.

    Yeah I made an attempt to point out the differences to @TheSnidr. They are two entirely different things, which is why I decided not to include it in this tutorial. :) If you would like me to correct anything in my post to him let me know.

    I agree - Not only that - depending on the mood of my computer at the moment it may be half those FPS for no reason - Since "fast" is a relative term - I updated the title of the post. Thanks for pointing that out.
    I was also mostly trying to show the Call Count and the Time(Ms) as those tend to have a more reliable indication of performance for me when testing.
     
    Last edited: Jul 17, 2018
  26. MirthCastle

    MirthCastle Member

    Joined:
    Mar 26, 2017
    Posts:
    147
    @Pfap - Unfortunately that little eye is only for while you are in the room_editor - it wont do anything while in game. :/

    Yes, if your player ended up on a layer that was set to invisible he would disappear too. I usually put my "collision" layers towards the bottom of my room_editor stack so that wont happen.

    When it comes to Grid-Layers - I use the sort_begin and sort_end layers to "lock in" the the layers I am sorting to so my characters and other things won't end up where they aren't supposed to.
     
    Pfap likes this.
  27. Pfap

    Pfap Member

    Joined:
    Apr 30, 2017
    Posts:
    552
    it's a little difficult for me to think about I would need to play with it, but just using objects to run your collisions solves that problem so it's really a non issue. I just had a project where I would "paint" with an invisible tile to use for pathfinding and that's where my question came from. Still a clean self contained system you can set and forget, thanks for sharing.
     
    MirthCastle likes this.
  28. BPOutlaws_Jeff

    BPOutlaws_Jeff Member

    Joined:
    Jul 26, 2016
    Posts:
    48
    Haven't had a chance to watch the full video yet so this might be answered in it (forgive me! lol) but just a quick question while I was thinking back over the first explanation part: is this a thing that will work down to the pixel? Like the visual examples at the start of the video use thick "bands" of Layers, but if two objects are on that same grid layer but a few pixels above/below eachother, will they depth-sort properly with this? Or is it only when the object crosses into the next "band"? Or would you have a layer for every pixel on the y axis (like 768 grid layers for a 1024x768 game lol)?

    Like the classic depth = -y; sorting (conceptually, I know that doesn't work anymore) would handle things down to the pixel so if you had two NPCs walking vertically past eachother one pixel per frame, they would sort properly anywhere on the screen, but what would happen in this system? If a grid layer was 32 pixels high and two NPCs were on the same grid layer but with only a 4 pixel difference between them and neither crosses into another grid layer, will that mess up? Just trying to picture what type of games this would work best for and what sort of limitations there would be with it (like a Final Fight brawler instead of an RPG)

    Has she made that advice public anywhere (blog, vid, etc)? Your video came out great especially for your first one, I'd love to see more people in the community doing good high-quality tutorials :)
     
    MirthCastle likes this.
  29. Pfap

    Pfap Member

    Joined:
    Apr 30, 2017
    Posts:
    552

    Ehhh, feeling kind've guilty here as I nabbed @MirthCastle 's dropbox before he deleted it.... but it does indeed look like it creates a layer per pixel.
     
    MirthCastle likes this.
  30. MirthCastle

    MirthCastle Member

    Joined:
    Mar 26, 2017
    Posts:
    147
    @BPOutlaws_Jeff - They were private messages between her and I - Ill ask her if it is OK to share them (minus personal details). But I would be happy to shared what I learned with you if you are interested. (not in this thread though lol).

    I am really glad you brought that up - the answer is YES! it will work fine!

    In the project in the video I am doing the layers at 4px spacing "per band" - there isn't anything stopping you for using 1px spacing - but you probably don't have to. If your characters move around at 2 or 4 that's all the spacing you need. If they move at 3, bump it up to 4 (imho) - Using power of 2 numbers will make your whole project easier. Including Collisions.. If you use that system most do with the place_meeting for the "pixel_perfect" collisions, and you place all your objects (99.9999% do) in the room editor using the even grid spacing there, your "pixel perfect" collisions would finish twice as fast.

    Back to your question - with a final fight type thing, you wouldn't even have to "make layer bands" for the whole room, just the area the characters are in... see below.

    Below, would take an alteration of the math for laying the layers down. If that's hard to imagine, easiest would be to still make a grid the size of the room, but only create all the layers for the red area - say between grid[0, 512] and grid[0, 768].
    Capture.JPG
     
    Last edited: Jul 17, 2018
  31. BPOutlaws_Jeff

    BPOutlaws_Jeff Member

    Joined:
    Jul 26, 2016
    Posts:
    48
    Me too ;)

    Perfect, just what I was wondering. At first the idea of such a huge grid list seemed crazy but really if it's only updating the moving actors then ya it shouldn't matter how many you have. The concept itself seems pretty simple once you wrap your head around it and I can see a lot of uses for this, definitely going to give it a whirl in any projects where I need to do a lot of vertical depth sorting...with credit of course ;)

    Also it would be cool to hear from anyone on the YoYo team's thoughts on this and how it integrates with the new layer system etc...anything being overlooked here?
     
    Last edited: Jul 17, 2018
    MirthCastle and Pfap like this.
  32. MirthCastle

    MirthCastle Member

    Joined:
    Mar 26, 2017
    Posts:
    147
    haha thanks! I was referring to the PDF i was sharing. you don't have to give credit for the depth system itself lol!!!

    (I fixed that verbiage thanks for pointing that out)
     
  33. Nakwatuk

    Nakwatuk Member

    Joined:
    Sep 29, 2018
    Posts:
    5
    MirthCastle, cheers for putting this out there. I'm digging in myself and am finding some difficulty in getting this to work for multiple room scenarios. Usually for control objects I have them persistent and sitting in an room_init that leads to the other rooms of the game. But putting the obj_layerControl into the init room is breaking in saying variables have not yet been defined for the globals (GRID, GRID_H, and the ds). Anyway, just wondering if you had any input on multiple room handling using this method?
     
  34. Michael Stearns

    Michael Stearns Member

    Joined:
    Jul 3, 2017
    Posts:
    22
    Hey I'm quite late to this thread, but if I could still offer a little feedback--

    The video was great. I admit this grudgingly, because I came in here really frustrated (having discovered my GMS1.4 tricks no longer worked) and looking for something fast to implement, and a 30 minute video spent pausing, rewinding, and jumping back and forth between my code and the video is not my idea of fast or a good time. But it was easy enough to follow along and I feel like I learned a lot along the way once I got patient. Taking the time to learn a thing is good.

    My problem though is that I mistyped a few things along the optimization step and am taking forever going back through and finding out what they all were. If this took a written format instead of video or even screen caps (in fact I think screen capping the video is going to be my solution here) then tracking down the issues would be a lot lot faster. I guess the other suggestion I'd make is since there is room for error and it's a rather long step, if you do videos in the future, breaking that kind of thing up into "testable" chunks would be a good for us accident-prone types.

    Thanks! (....as soon as I get all these grass objects to stop disappearing, anyway!)

    (Edit, got it! I'd blame it on GMS2's improved autofill options but I know it was just me trying to be in a hurry..)
     
    Last edited: Apr 1, 2019
  35. MuddyMuddy

    MuddyMuddy Member

    Joined:
    Mar 2, 2017
    Posts:
    184
    I have tried a similar but more basic method that seems to work ok (so far)

    The idea is that I use the beginning sort layers in room editor eg. ‘lvl1’, ‘lvl2’ etc. Then I take that layer depth (layer_get_depth(lvl1)) then - the y.

    Code:
    //start lvl depth
    dpth = layer_get_depth(“lvl1”);
    
    //final depth
    Depth = dpth - y;
    So essentially each object depth is between the base layers. So you can still use the main layers.

    Any downsides to this method vs MirthCastle?
     
  36. gnysek

    gnysek Member

    Joined:
    Jun 20, 2016
    Posts:
    1,341
    It will be still a temporary layer, not a "true" layer. The more objects you have, the more those temporary half-layers will be created.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice