Tag: Games

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!


Using Autofac With Unity3D

Autofac With Unity

Why Consider Using Autofac With Unity3D?

I think using a dependency injection framework is really valuable when you’re building a complex application, and in my opinion, a game built in Unity is a great example of this. Using Autofac with Unity3D doesn’t need to be a special case. I wrote a primer for using Autofac, and in it I discuss reasons why it’s valuable and some of the reasons you’d consider switching to using a dependency container framework. Now it doesn’t need to be Autofac, but I love the API and the usability, so that’s my weapon of choice.

Building a game can result in many complex systems working together. Not only that, if you intend to build many games it’s a great opportunity to refactor code into different libraries for re-usability. If we’re practicing writing good code using constructor dependency passing with interfaces, then things really start to line up in favour of using a dependency injection framework.

Getting Set Up

At the end of my autofac primer article, I provided a link to the Nuget package for Autofac. You’ll notice that there’s a version dependency for .NET 4.5, so if you’re not sure how to get Unity3D working with .NET 4.5, you’ll want to check this other article of mine. It’s very simple, so don’t worry!

Unity3D, at the time of writing this and using version 2018.1.1f1, there’s no native Nuget package support. I haven’t spent too much time investigating alternatives, but not to worry. I’ll explain a quick work around. The TL;DR is that we need the binaries from the Nuget package to be loaded up by Unity3D and we’ll miss out on the Nuget-y-ness for now. Not a huge deal since we’ll still have Autofac support!

  • Start a new Visual Studio C# project
    • Ensure that the .NET framework is at least 4.5 and more specifically, the version of .NET that you’d like to use in your Unity3D project
  • Open up the Nuget package manager in Visual Studio
  • Search for Autofac online in the package manager (it should be the same one I referred to above!)
  • Add this package to your visual studio project
  • Compile this visual studio project
  • Assuming you built in debug, go to the output folder (which is in bindebug if you didn’t change anything from default)
  • In the output folder, you’ll find “Autofac.dll”
  • You’ll want to add this into your Unity3D project’s “Assets” folder
    • I like nice folder hierarchies, so I’d suggest making a subfolder inside of “Assets” called “Third Party” or “Dependencies”… Something that’s obvious for what it means
    • Drop in the Autofac.dll file into there
  • Unity3D will add a corresponding *.meta file to go along with this

Great! We’re almost there. If you want to test it out, open up a script from Unity3D. This will launch a new Visual Studio instance if you haven’t opened up one for your Unity project yet. At the very top of your file you should be able to type:

using Autofac;

And the namespace should resolve! If not, sometimes this takes Unity3D a refresh operation to regenerate the project file on disc, so if you switch to Unity3D again and it starts doing some processing, switching back to Visual Studio might resolve this.

Using Autofac With Unity3D

Up until this point, we’ve proven we can reference Autofac. I’m not going to explain all the ins and outs for how you’ll want to organize your Autofac initialization in this post, but we can walk through a quick example!

  • Pick a game object on your scene
  • Add a new C# script to it
    • Call it whatever you’d like, but make sure you know how to open it
  • … now go open it in Visual Studio šŸ™‚
  • We should have a method in there called Start()
    • If not, feel free to add it:
    • private void Start()
      {
        // TODO: we'll add stuff here
      }
  • Let’s use this code to make a new class that you can put inside the same script file for now:
    • public sealed class MyAutofacObject
      {
      
        public MyAutofacObject()
        {
          Debug.Log("Constructor for our object!");
        }
      
        public void DoThing()
        {
          Debug.Log("Test!");
        }
      }
  • Inside this start method, let’s try doing something VERY simple to prove Autofac works!
    • var containerBuilder = new Autofac.ContainerBuilder();
      containerBuilder.RegisterType<MyAutofacObject>().SingleInstance();
      
      var container = containerBuilder.Build()
      var instance = container.Resolve<MyAutofacObject>();
      
      instance.DoThing();

Now if we run our game, here’s what should happen:

  • The script attached to the game object should run
  • The Start() method on the script should be the first thing that goes
  • The code we added should:
    • Make a new ContainerBuilder
    • Register our MyAutofacObject type as a single instance
    • Build the container
    • Resolve an instance of our type
    • Log out a message saying it’s in the constructor
    • Log out a message that says Test!

And voila! It’s simple, but it should demonstrate that Autofac is working!

Next Steps

This is a very contrived example of using Autofac with Unity3D. It proves that the code can be run, but it doesn’t do too much that’s useful. There are going to be many considerations you’ll need to make for how you want to organize your dependencies, register your classes/interfaces, and so on.

I’ll continue to add into this Unity3D series of posts, but let me know what else you’d like to know about using Autofac with Unity3D! I’d be happy to try and answer, or even create an article to help explain.

Thanks!


Unity3D and .NET 4.x Framework

Unity

Unity3D Default .NET Framework

I recently wrote that I wanted to start writing more Unity3D articles because I’m starting to pick up more Unity3D hobby work. It felt like a good opportunity to share some of my learnings so that anyone searching across the web might stumble upon this and get answers to the same problems I had.

Unity3D as of 2018.1.1f1 (which is the version I’m currently using), still defaults to using .NET 3.5 as the framework version. Nothing wrong with that either. I’m sure there are reasons that they have for staying at that version, probably because of Mono and cross platform reasons if I were to guess, so I’m not complaining. For reference, this setting in Unity3D is referred to as “Scripting Runtime Version”. So if you’re googling more about this later, that’s what Unity calls it. For the libraries I was building to use as a game framework, I was using .NET 4.6 and discovered I was going to have a challenge getting them working in Unity3D.

If you want to see what your setting is currently set at, you need to check out the “Player” settings. This was kind of buried in the UI for me so I didn’t know it was a thing that could be adjusted. In Unity3DĀ 2018.1.1f1, click Edit->Project Settings->Player. Here’s what it looks like:

Unity3D - Player Settings

In Unity, click Edit->Project Settings->Player

From there, you’re going to get “PlayerSettings” in your Inspector tab. You’ll need to expand the “Other Settings” to see your scripting runtime version:

Unity3D - Other Settings

“Other Settings” accordion control in PlayerSettings Inspector tab

Once you expand that, here’s the setting you’re interested in:

Unity3D - Scripting Runtime Version

Scripting Runtime Version – The selected .NET version Unity will use

Switching Unity3D to .NET 4.x

Now that you know where the setting is… it’s pretty easy šŸ™‚

Unity3D - Scripting Runtime Version

Use the dropdown to pick which .NET framework version you’d like to use.

You can read more about this setting over at the official Unity3D documentation pages:

https://docs.unity3d.com/Manual/ScriptingRuntimeUpgrade.html

This outlines what things are affected in different platforms and scenarios so YOU SHOULD READ IT to understand what will change.

Hope that makes things a bit easier for you to get up and running with .NET 4.x assemblies in Unity3D!


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