Tag: Unity2D

TileMap – How To Get ALL The Tiles

If you’re building a 2D game in Unity3D, odds are you’ve come across the TileMap component. The TileMap is a powerful tool that allows you to create a grid of tiles that you can render your tiles with instead of hand-placing individual game objects with sprites. It has a host of built in functionality that you might otherwise find yourself manually writing, like mapping coordinates to particular cells on a map. And what’s even cooler about using a TileMap? You don’t need to handroll your own editor to paint tiles! I think I’d pass on having to do that. But have you found yourself in a situation where you want to get all of the painted tiles on a TileMap? You may have found it’s not quite as obvious as you’d have hoped!

What We Have To Work With On A TileMap

As I mentioned, a TileMap can do a lot for you. In particular, I found myself wanting to get all of the cells that have a Sprite associated with them and what that Sprite actually is. We can use the built in method GetSprite for this:

var cellPosition = new Vector3Int(x, y, 0);
var sprite = tilemap.GetSprite(cellPosition);

Simple enough. But how do we know which coordinates to use for x and y? Is it good enough to just go from 0 to a really high number on the x and y axes with two loops and hope it’s good enough? We can do better than that! The TileMap class has a handy property on it called cellBounds. This gives us an integer rectangle that defines the bounds of all of the TileMap cells that have been modified:

tilemap.cellBounds

If you have found you’re doing a lot of editing on a TileMap, you may be erasing sections to focus on another area. If that’s common, you may benefit from calling CompressBounds() to shrink this back down to the currently assigned cells:

tilemap.CompressBounds()

And with all of these, we can approach how we might tie them all together to get what we need!

Be Careful With TileMap.cellBounds And Starting From Zero!

If you have a keen eye, you’ve probably realized that we want to use two loops to go through the cell bounds on the x and y axes to get the cells we’re interested in on the TileMap. You’re spot on! But there’s something we should be careful about here!

It’s an easy mistake to make because it’s how we commonly write loops:

for (int x = 0; x < bounds.max.x; x++)
{
    for (int y = 0; y < bounds.max.y; y++)
    {
        // do stuff
    }
}

But what’s wrong with this? The starting value! You need to be careful when working in 2D space like in Unity. There’s nothing that actually guarantees your Tiles have been drawn starting from position zero on the TileMap and only going in a positive direction. In fact, in my game I had no tiles on the positive y axis! So a simple change to make sure you don’t mess up is use the MINIMUM as your starting point:

for (int x = bounds.min.x; x < bounds.max.x; x++)
{
    for (int y = bounds.min.y; y < bounds.max.y; y++)
    {
        // do stuff
    }
}

Simple as that!

Wrapping It All Up

You’re probably looking for a full-blown code snippet by now. Fair enough. Here’s what I whipped up:

public static class TileMapExtensionMethods
{
    public static IEnumerable GetAllTiles(this Tilemap tilemap)
    {
        // note: optionally call tilemap.CompressBounds() some time prior to this
        var bounds = tilemap.cellBounds;

        // loop over the bounds (from min to max) on both axes
        for (int x = bounds.min.x; x < bounds.max.x; x++)
        {
            for (int y = bounds.min.y; y < bounds.max.y; y++)
            {
                var cellPosition = new Vector3Int(x, y, 0);

                // get the sprite and tile object at the specified location
                var sprite = tilemap.GetSprite(cellPosition);
                var tile = tilemap.GetTile(cellPosition);

                // this is a sanity check that i've included to ensure we're only
                // looking at populated tiles. you can change this up!
                if (tile == null && sprite == null)
                {
                    continue;
                }

                // create a data-transfer-object to yield back
                var tileData = new TileData(x, y, sprite, tile);
                yield return tileData;             
            }
        }
    }
}

public sealed class TileData
{
    public TileData(
        int x,
        int y,
        Sprite sprite,
        TileBase tile)
    {
        X = x;
        Y = y;
        Sprite = sprite;
        Tile = tile;
    }
    
    public int X { get; }

    public int Y { get; }

    public Sprite Sprite { get; }

    public TileBase Tile { get; }
}

The above example provides a nice extension method to get you back a TileData instance for all the populated cells on your TileMap!


RPG Game Dev Weekly #1

As I’ve been trying to get more YouTube content put together more steadily, one of the themes I’m interested in is doing some behind-the-scenes of the role playing game (RPG) I’m making with some friends in Unity3D. I’ve found that being able to work on an RPG outside of my regular day job is a really awesome way for me to keep up on my technical skills. I love coding, and the further along I move in my career as an engineering manager, the less time I actually spend writing code myself. I pride myself in being a technical engineering manager, so for me working on this RPG is a great outlet for creativity and practice. I mentioned this in my LinkedIn post here:

Persisting Game Objects Across Maps

In this video, I focus on one of the challenges the game was facing due to how objects are materialized onto the playable map. The map that we load from disk to be shown and interacted with in the playable RPG commonly has “templates” and “spawners”. Both of these are responsible for creating objects at runtime given some criteria. As a result, uniquely placed game objects appear on the playable map for the player to interact with.

Sounds good then, right? Well the two challenges I focused on addressing were:

  1. If we leave the map and go to another one, there’s no way to persist the player across maps! That means you get a brand new character every time you transition maps. In an RPG, this is definitely not going to work out.
  2. If we return to an existing map, we expect it to be in the same state as when we were last on it. This means that the objects generated from templates or spawners must remain and NOT be respawned (which would effectively make completely new game objects).

Check out the video below:

RPG Dev Log 1 – Persist Game Objects Across Maps

Persisting Map Game Objects in a Cache

Next up was actually implementing some of the changes being discussed previously. In order to make this work in our RPG, my goal was to:

  1. Allow maps to save a lookup of the unique IDs for game objects that were generated
  2. Save the list of game objects generated into a “cache”
  3. Upon revisiting a map, tap into the “cache” to reload the existing game objects

One of my mental hurdles with this was acknowledging that we don’t yet have a solid serialization foundation for our game. I was thinking I’d want to serialize the game data to something persistent to make this work, but I was also worried writing things to disk would be overkill (and how does this mix with save game concepts?). Instead, I opted for the lightweight approach was “get something working” and I can revisit this later to extend it to persist things to disk if necessary.

Check out the video below:

RPG Dev Log 2 – Persisting Map Game Objects in a Cache

Which Domain Does This Belong To?

We’ve been trying to practice Domain Driven Design (DDD) concepts in our game. One pattern I’ve taken to an extreme is over-separating domains into very granular pieces and the result is that we have HUNDREDS of C# projects. It’s overkill, for sure. However, I feel that it’s offered some flexibility in having boundaries we can collapse later. My experience so far has told me it’s easier to collapse boundaries than it is to split.

This is all and well until we have situations where I need a class that has knowledge of two domains. That’s what this next video was about. I talk through acknowledging that I don’t know what to do and that I’ll move ahead with something best effort. I think the answer to my dilemma is that I need to translate things into a new domain for usage, but it feels like overkill. If you have thoughts on this leave a comment on this post or on the video!

Check out the video below:

RPG Dev Log 3 – Which Domain Does This Belong To?

Death Animations For All!

Finally, this last update was about something hopefully less boring… Death animations! I worked through how:

  1. I can extend our reusable sprite animation factory to create a death animation to be reused by ALL our actor sprites
  2. I can build a system that checks actor life and changes the animation as necessary to death

Unfortunately I had some hiccups the first time through recording this, but I wanted to code the whole thing live. After a Blue Screen of Death interrupted my first attempt, my second attempt I think worked pretty well! Without much code at all we could get this system fired up and it worked the first time! Well, close. I didn’t realize that our animation system already supports an animation that has an “infinite” duration final frame (in this case, the body laying on the tile). This is handled by a null value instead of a set length in seconds. I fixed it right after recording! Overall, I was incredibly happy with the result.

Check out the video below:

RPG Dev Log 4 – Death Animations For All!

NoesisGUI – The Unity UI Framework That You Probably Aren’t Using!

If you’re like me, trying to create user interfaces in general is a challenge. So when it comes to working in tools that you’re less familiar with, that challenge basically grows to a level where it’s a roadblock. For me, trying to create user interfaces in Unity3D is basically the perfect example of hitting this roadblock! That’s not to say the UI tools that are available in Unity3D are bad, but my skill level is essentially reset to zero when working with these tools. Fortunately I came across this little gem called NoesisGUI that enables WPF inside of Unity3D!

I plan to do a few updates on this either via YouTube or short blog posts, but NoesisGUI has essentially unlocked my ability to create user interfaces inside of Unity3D. You can find my intro video here, or watch it directly below:

Now I’m still not a UI expert by any means, but at least I get my familiar environment back. NoesisGUI has two primary benefits for me as a software developer:

  • I have access to all the WPF controls, XAML syntax, and styling capabilities that I know and love.
  • I can use tools/IDEs I’m familiar with, not sacrificing years of experience using these tools.

On the first point, for me I find it very tedious to create UI elements in Unity3D. For some good examples, I consider trying to do two pretty common things: control layout and lists of items. On control layout, I find the anchoring system and transforms a total pain to work with in Unity3D. It’s a personal preference sort of thing, but I find it difficult to navigate and get things to work as I expect. However, I know thanks to NoesisGUI I can leverage things like grids and flowing panels so I can use what I know and not try to design a layout system from scratch. Same thing goes with lists! I can use a ListView control thanks to NoesisGUI and then style/template all the controls inside of it leveraging XAML. Effectively, being able to leverage NoesisGUI to enable my experience with WPF means I can struggle with UI design instead of struggling with UI design AND how to make the UI framework work! It doesn’t fix my poor UX abilities, but NoesisGUI does allow me to do my best work at least.

The second point is around tooling. The Unity3D editor is powerful and if you watch any amount of tutorials from YouTube you’ll know that there’s no shortage of people showing how to drag and drop objects into the scene to get the result you’re after. But this doesn’t work well for my design approach because I don’t want my game to be coupled to the Unity3D engine (which I’ll need to write more about later). In fact, the more things I place concretely in the scene, the more it couples my game to Unity3D and it’s just not something I want to commit to. As a result, to decouple my UI code I found myself trying to programmatically make Unity3D UI elements and started to dream up some templating language.

Nonsense. NoesisGUI puts me back in my comfort zone and allows me to use familiar tools like Blend where I get my visual editor for my WPF controls as well as the split view with the XAML editor. Aside from a couple of minor quirks, I was able to get Blend to show things exactly as Unity3D shows them. That means I can rapidly develop my game UI inside of Blend. Along with with a bunch of other design philosophies (i.e. decoupling from Unity3D engine), this means we could literally write a couple-of-line game entry point with a WPF UI overtop of it directly in Blend and have it map to expected behavior in Unity3D. Again, more on some of those design philosophies later, but NoesisGUI really took it to the next level by allowing us to decouple the UI completely from Unity3D restrictions.

I plan to create more writeups and videos on how we’re using NoesisGUI in our RPG project, so stay tuned!


  • Copyright © 1996-2010 Dev Leader. All rights reserved.
    Jarrah theme by Templates Next | Powered by WordPress