# Unity3D: Dungeon Crawler Movement with Collisions

It’s been almost two years since I wrote “First Person Grid Movement with Unity3D“, in which I showed how to use Unity3D to replicate the grid-based movement typical of “blobbers” like Eye of the Beholder. The most common question I’ve had about that article is how to implement collisions. So that’s what I’m going to show you in this article, using Unity Editor 2021.3.25f1 LTS.

## Creating a Project

Open the Unity Hub and create a new project. Make sure you select the 3D template, and call it whatever you want.

1. In the Assets pane, right-click and select Create -> C# Script. You can call it whatever you want, but I’ll call it Game.
2. Drag it onto your Main Camera object.
3. Double-click the script to open it in your IDE (e.g. Visual Studio Code).
4. In your `Update()` function, paste the following code which is where we left off in “First Person Grid Movement with Unity3D“:
```void Update()
{
if (Input.GetKeyDown(KeyCode.W))
this.transform.position += this.transform.rotation * Vector3.forward;
else if (Input.GetKeyDown(KeyCode.S))
this.transform.position += this.transform.rotation * Vector3.back;
else if (Input.GetKeyDown(KeyCode.A))
this.transform.position += this.transform.rotation * Vector3.left;
else if (Input.GetKeyDown(KeyCode.D))
this.transform.position += this.transform.rotation * Vector3.right;
else if (Input.GetKeyDown(KeyCode.Q))
this.transform.rotation *= Quaternion.Euler(0, -90, 0);
else if (Input.GetKeyDown(KeyCode.E))
this.transform.rotation *= Quaternion.Euler(0, 90, 0);
}
```

So now we can move the camera, but we don’t have collisions yet. In fact, we don’t even have anything to collide with yet.

Unity3D comes with its own set of colliders you can use, but since we’re assuming movement in a 2D grid, then it’s much easier to just store a simple map in a 2D array and check what’s in the destination cell before moving into it. We’ll use this same 2D array to generate walls in the scene rather than putting cubes manually into the scene as we did in the earlier article. The following should do:

```    private string[] map = new[] {
"XXXXXXXXXXXX",
"X          X",
"XX XX  XX XX",
"XX XX XXX XX",
"XX  XXX    X",
"XXX X X XX X",
"X     X  X X",
"X XXXXXXXX X",
"X      X   X",
"XXX XX    XX",
"X    X XX  X",
"XXXXXXXXXXXX",
};
```

Since a string behaves like an array of characters, it’s good enough to use an array of strings instead of a 2D array of characters.

## Generating Walls

After the map, let’s also add a field that we can use to set the prefab we’ll use as a wall:

```    [SerializeField]
GameObject wallPrefab;
```

Back in the Unity Editor:

1. Create a cube (GameObject menu -> 3D Object -> Cube) in the scene.
2. Drag it from the Hierarchy pane into your Assets pane to create a prefab.
3. Rename the Cube prefab in your Assets pane to Wall.
4. Delete the cube in the scene.
5. Select the Main Camera, then drag the Wall prefab into the Wall Prefab slot of the Game script as shown above.

Now that we have the Wall prefab set up, let’s go back into the script and add some code that will create the walls on startup:

```    void Start()
{
for (int z = 0; z < map.Length; z++)
{
for (int x = 0; x < map[z].Length; x++)
{
if (map[z][x] == 'X')
{
Vector3 position = new Vector3(x, 0, z);
Instantiate(wallPrefab, position, Quaternion.identity);
}
}
}
}
```

Because the Y-axis points upwards and we’re dealing with a flat 2D grid, it’s useful to note that Y is always zero and we’re dealing with the X- and Z-axes when moving.

## Positioning the Camera

Press Play and we can get a first peek at the generated walls:

It’s clear that the camera is a little off, but we can already see that we’ve successfully generated some sort of maze. Thanks to the movement script we copied earlier, you can move around (WASD for forward, backward, left and right movement, Q to turn left, and E to turn right) and find a good starting point for the camera, e.g. (X, Y, Z) = (5, 0, 1):

## Implementing Collision Detection

So now we come to the original problem: we’re able to walk through the walls. Now that we have a map, all we need to do to detect collisions is to check what’s in the square we’re moving to, before we move into it. For this, we’ll add a little helper function:

```    private void updatePositionIfNoCollision(Vector3 newPosition)
{
var x = System.Convert.ToInt32(newPosition.x);
var z = System.Convert.ToInt32(newPosition.z);

if (map[z][x] == ' ')
this.transform.position = newPosition;
}
```

This function takes the position of the square we’re about to move into as an input, then if that square is clear on the map, it updates the camera’s position. Conversely, if that square contains an ‘X’, then nothing will happen.

So in the Update() function, instead of updating the position directly when we handle the movement keys, we instead call this helper function to move only on condition that the target square is clear:

```    void Update()
{
if (Input.GetKeyDown(KeyCode.W))
updatePositionIfNoCollision(this.transform.position + this.transform.rotation * Vector3.forward);
else if (Input.GetKeyDown(KeyCode.S))
updatePositionIfNoCollision(this.transform.position + this.transform.rotation * Vector3.back);
else if (Input.GetKeyDown(KeyCode.A))
updatePositionIfNoCollision(this.transform.position + this.transform.rotation * Vector3.left);
else if (Input.GetKeyDown(KeyCode.D))
updatePositionIfNoCollision(this.transform.position + this.transform.rotation * Vector3.right);
else if (Input.GetKeyDown(KeyCode.Q))
this.transform.rotation *= Quaternion.Euler(0, -90, 0);
else if (Input.GetKeyDown(KeyCode.E))
this.transform.rotation *= Quaternion.Euler(0, 90, 0);
}
```

That’s all. If you press Play now, you’ll find that you can roam freely around the map, but you can’t move into walls.

## Conclusion

Collision detection on a 2D grid is pretty easy. You just need to keep track of where you are and what’s in the square you’re moving into.

# First Person Grid Movement with Unity3D

Before 3D took the gaming world by storm, many RPGs used a pseudo-3D engine in which you could move in discrete steps within a grid, with a first person view. Although this was popularised by “blobbers” such as Dungeon Master and Eye of the Beholder, it goes at least as far back as 1979 with Akalabeth.

Blobber: A slang term for party-based games with first-person view, such as Wizardry, Dungeon Master and Legend of Grimrock, where the entire party moves as one, as if it was an amorphous blob.”

The CRPG Book, page 522

Unity3D gives us everything we need to easily set up this first-person grid-based movement.

## Setting the Scene

First, create a new 3D project. Add a few Cubes to the scene so that we’ll have something to see as we move around. You can do this via GameObject menu -> 3D Object -> Cube, although after creating the first one, you can select it and press Ctrl+D to duplicate it. Set their X and Z positions to integer values, leaving their Y position set to zero. Since the Main Camera faces down the Z-axis, it’s also nice to not set X=0 for any cubes, so that we have a corridor that we can immediately walk down.

Optionally, add a few different-coloured materials and apply them to the cubes. This will later help make the movement more obvious, rather than just having a long, solid white wall. Refer to “Simple Brick Wall with Unity3D” if you don’t know how to do this.

Finally, adjust the camera so that its Y-position is zero, aligning it with the cubes.

## Implementing Movement

In my old article “Unity3D: Moving an Object with Keyboard Input“, I showed how `Input.GetKeyDown()` can be used to move an object when a key is pressed. We can use the same thing to move and rotate the camera.

Create a script called “Movement”, and drag it onto your Main Camera. Double-click the script to open it in an editor.

In the `Update()` method, add the following to enable the typical WASD keyboard movement (‘W’ to go forwards, ‘S’ to go backwards, ‘A’ to move left, and ‘D’ to move right, all while facing down the Z-axis):

```    void Update()
{
if (Input.GetKeyDown(KeyCode.W))
this.transform.position += Vector3.forward;
else if (Input.GetKeyDown(KeyCode.S))
this.transform.position += Vector3.back;
else if (Input.GetKeyDown(KeyCode.A))
this.transform.position += Vector3.left;
else if (Input.GetKeyDown(KeyCode.D))
this.transform.position += Vector3.right;
}
```

If you press Play, you can use the WASD keys to move around:

## Implementing Rotation

That was easy enough! The fact that the camera is conveniently aligned with the Z-axis allows us to use predefined vectors to move in specific directions. However, this is no longer the case once we allow rotation. Any movement must be done with respect to whatever direction the camera is currently facing.

Fortunately, we already know what direction the camera is facing. That’s its `transform.rotation`. We can change direction by multiplying it by a Quaternion, which we can conveniently create based on an angle in degrees using `Quaternion.Euler()`. Let’s see this in practice by allowing the ‘Q’ and ‘E’ keys to rotate the camera 90 degrees left and right, respectively:

```    void Update()
{
if (Input.GetKeyDown(KeyCode.W))
this.transform.position += Vector3.forward;
else if (Input.GetKeyDown(KeyCode.S))
this.transform.position += Vector3.back;
else if (Input.GetKeyDown(KeyCode.A))
this.transform.position += Vector3.left;
else if (Input.GetKeyDown(KeyCode.D))
this.transform.position += Vector3.right;
else if (Input.GetKeyDown(KeyCode.Q))
this.transform.rotation *= Quaternion.Euler(0, -90, 0);
else if (Input.GetKeyDown(KeyCode.E))
this.transform.rotation *= Quaternion.Euler(0, 90, 0);
}
```

The camera can now turn left and right:

However, this messes things up because the WASD keys still move with respect to the Z-axis, rather than in the direction that the camera is facing. We can easily fix this by multiplying the movement vectors by the camera’s rotation:

```    void Update()
{
if (Input.GetKeyDown(KeyCode.W))
this.transform.position += this.transform.rotation * Vector3.forward;
else if (Input.GetKeyDown(KeyCode.S))
this.transform.position += this.transform.rotation * Vector3.back;
else if (Input.GetKeyDown(KeyCode.A))
this.transform.position += this.transform.rotation * Vector3.left;
else if (Input.GetKeyDown(KeyCode.D))
this.transform.position += this.transform.rotation * Vector3.right;
else if (Input.GetKeyDown(KeyCode.Q))
this.transform.rotation *= Quaternion.Euler(0, -90, 0);
else if (Input.GetKeyDown(KeyCode.E))
this.transform.rotation *= Quaternion.Euler(0, 90, 0);
}
```

And this works really nicely.

Watch the demo video on YouTube to see this in action!

## Wrapping Up

As we’ve seen, Unity3D makes it really easy to set up this simple game mechanic where you have a first person view, move in steps, and turn in 90-degree angles. It does help to be comfortable with vectors. If you’re not, check out my “A Concise Introduction to Vectors” [PDF] at Swords and Software.

If you’d like a little extra exercise, try to make the movement and rotations as smooth transitions. You can use `Vector3.MoveTowards()` and `Quaternion.RotateTowards()` for this. You’ll also need to change your camera’s near clipping plane to zero to avoid weirdness during rotations.

Update 15th May 2023: see “Unity3D: Dungeon Crawler Movement with Collisions” for how to implement collision detection.

# Simple Brick Wall with Unity3D

In Unity3D, we can use prefabs to create a template for an object that we’ll create many times, such as bullets, planets, or – as we’ll see in this article – bricks. Prefabs are handy because each instance will carry the same scripts, materials, transforms, etc. Let’s see how this works in practice by creating a wall made up of many bricks.

To start off, create a new 3D project with Unity3D. I’m using Unity3D 2020.3.13f1 (LTS), although any version is probably fine for this beginner exercise.

## Creating a Brick Prefab

We’ll start off by creating a simple brick, which will be the building block for our wall.

Create a Cube, via the menu GameObject -> 3D Object -> Cube. Rename it to “Brick”. In the Transform portion of the Inspector, set the X component of its Scale to 2, so that it looks elongated like… a brick.

Next, we’ll create a material for the brick. In your Project window, right click on Assets and then go Create -> Material. (You could create an appropriate folder structure to separate things like Materials, Scripts etc, but since we’ll have very few of these in this case, I won’t bother.) Name it “Brick Material”, and then set the colour of its Albedo property to something that looks like brick red (in my case I went with RGB(183, 50, 57)).

Drag the Brick Material onto the Brick (in either the Hierarchy or Scene windows) to apply the colour.

Next, drag the Brick GameObject from the Hierarchy window to the Assets folder in the Project window to create a prefab out of it. Note how the Brick is now blue in the Hierarchy window, and it also gets an “Open Prefab” button in the Inspector.

## Instantiating a Single Brick

We now have two concepts of “Brick” in this project: the original Brick GameObject (as seen in the Hierarchy and Scene windows), and the Brick prefab (in the Assets folder of the Project window). The Brick GameObject is an instance of the Brick prefab. We can create more instances of the Brick prefab, and they will have the same components (such as materials and transforms) unless we specifically change them.

This makes it very easy to write a script to create lots of bricks using the Brick prefab as a template. In fact, we don’t need the Brick GameObject any more. Go ahead and delete it.

Right click on the Assets folder of the Project window, select Create -> C# Script, and call it WallGenerator. Double-click the script to open it in your script editor.

Add a serializable field for the Brick prefab at the beginning of the class:

```public class WallGenerator : MonoBehaviour
{
[SerializeField]
GameObject brickPrefab;
```

Save the script, then go back to the Unity3D editor. Then:

1. Drag the WallGenerator script onto your Main Camera.
2. Notice the Brick Prefab property for the script in the Inspector.
3. Drag the Brick prefab from the Project window into that slot in the Inspector.

With this set up, we can start creating instances of the prefab from the script. Go back to the script editor, and add a call to `Instantiate()` in the `Start()` method as follows:

```    // Start is called before the first frame update
void Start()
{
Instantiate(brickPrefab);
}
```

Back in the Unity3D editor, press Play to run the game. You’ll see that a brick is actually generated at runtime, even though we don’t have any in the Scene window in the editor:

## Building a Wall

Now that we know how to create a single brick from a script, we can use simple loops to create more. Let’s create a 5×5 wall by using a different overload of `Instantiate()` that also takes a position (which we’ll provide) and rotation (which we’ll ignore):

```    void Start()
{
for (int y = 0; y < 5; y++)
{
for (int x = 0; x < 5; x++)
{
Vector3 position = new Vector3(x * 2, y, 0);
Instantiate(brickPrefab, position, Quaternion.identity);
}
}
}
```

If you press Play, you’ll see the wall, although it’s a little hard to distinguish the bricks because they’re touching each other:

You can tweak the scale of the Brick prefab to get some space between the bricks. For instance, this is how it looks with a scale of (X, Y, Z) = (1.95, 0.95, 1):

Finally, just to give it a bit more style, let’s change the script so that it generates alternating patterns of bricks:

```    void Start()
{
for (int y = 0; y < 5; y++)
{
int xOffset = (y % 2 == 0) ? 1 : 0;

for (int x = 0; x < 5; x++)
{
Vector3 position = new Vector3(x * 2 + xOffset, y, 0);
Instantiate(brickPrefab, position, Quaternion.identity);
}
}
}
```

All we did here was use the modulus operator (`%`) to check whether the row is an even-numbered one, and if so, add an extra 1 to the X position of each brick. This results in the following wall, better than any that Donald himself could ever hope to build:

## Summary

A prefab is a template of a GameObject used to create instances of it that share the same or similar components. As we have seen, we can easily call the `Instantiate()` method to create lots of instances of a GameObject from a script, making this one of the cornerstones of dynamic behaviour in Unity3D.

# Simple Planetary Orbit Simulation with Unity3D

In this article, I’m going to show you how to make a very simple simulation of planets orbiting the Sun, as well as rotating about their own axes. Even if you’re a beginner, you’ll be surprised how easy this is to set up. Just to set expectations, though: we’re keeping things simple to have fun and learn, so if you’re looking to create a realistic and accurate simulation of the Solar System, I’m afraid you’ve come to the wrong place.

Having said that, create a new 3D project with Unity3D, and let’s get to it! I’m using Unity3D 2021.1.10f1, which is one of the latest versions, but it’s also fine if you use an LTS version.

## Creating the Sun and the Earth

From the GameObject menu (or by right-clicking in the Hierarchy window), click “3D Object” and then “Sphere” to create a sphere. Name it “Sun”. It should be positioned at the origin (0, 0, 0) by default, and that’s where we want it.

Repeat this process a second time, and name the second sphere “Earth”. From the Inspector window, set the “Y” component of its position to 5.

In order to make the Sun and the Earth look like the real deal, we’ll need textures. A texture is just an image that gets wrapped over the surface of a 3D object, so in our case we want a flat map of the Earth, and an equivalent for the Sun. You can find several on the internet, and in my case I’m using these Solar Textures which look pretty nice. The resolution doesn’t really matter, so pick whichever you like.

In the Project window in Unity3D, create three folders under Assets:

• Materials
• Scripts
• Textures

Drag the Sun and Earth textures from wherever you downloaded them onto the Textures folder you just created, and they will get added to the project there. Next, drag the Sun texture (in my case it’s called “2k_sun”) onto the Sun GameObject in either the Hierarchy or Scene windows. You’ll see that this automatically creates a material in the Materials folder, and the Sun sphere in the Scene window now actually looks like the Sun. Repeat the process for the Earth.

As a final touch, set the Sun’s scale to 2 (i.e. all of the X, Y and Z components). Press Play to admire your work so far:

We’d like the Earth to orbit the Sun, so let’s add a script to do that. Right click on the Scripts folder we created earlier, and select “Create” and then “C# Script”. Name the script “Orbit”. Double-click it in the Project window, or click “Open” in the Inspector window to open it using your default script editor (if you want to change this, go to Edit -> Preferences -> External Tools -> External Script Editor).

In the Update() method, add the following code to implement the orbiting behaviour:

```    void Update()
{
var sun = GameObject.Find("Sun");
this.transform.RotateAround(sun.transform.position, Vector3.forward,
100f * Time.deltaTime);
}
```

The first line gets a reference to the Sun GameObject via its name. The second line uses the RotateAround() method to make the Earth (`this.transform`) rotate around the Sun (`sun.transform.position`) around the axis that the camera is facing in (`Vector3.forward`) at an angle of `100f * Time.deltaTime`.

Wait, why `100f * Time.deltaTime`? The Time.deltaTime is the time that elapsed since the last frame was rendered, so with each frame, the Earth will rotate a bit more around the sun. But `Time.deltaTime` alone makes the orbit a little too slow, so I multiplied it by an arbitrary number, and by trial and error, I settled on 100f. This is actually a common practice, and can be done quite conveniently from the Inspector window if we make a small change to our code.

```public class Orbit : MonoBehaviour
{
[SerializeField]
float speed = 100f;

// Start is called before the first frame update
void Start()
{

}

// Update is called once per frame
void Update()
{
var sun = GameObject.Find("Sun");
this.transform.RotateAround(sun.transform.position, Vector3.forward,
speed * Time.deltaTime);
}
}
```

By declaring a speed variable within the script’s class, marking it with the `[SerializeField]` attribute, and then using it within the script, we’ve created a parameter that we can configure from the inspector.

Save the script from your editor, and go back to Unity3D, which will pause momentarily to reload and recompile the script. Drag the Orbit script onto the Earth in either the Hierarchy or the Scene window, and you will see it gets added as a component in the Inspector window. Interestingly, you will also see the Speed parameter:

If you click Play, you should now see the Earth orbit the Sun. You can also change the value of Speed (even while the game is running), see what difference it makes, and adjust it until you are happy.

To make the Earth (and, later, the Sun) spin around its own axis, we just need to follow the same steps as for the Orbit functionality, with a slight change to the script.

2. Open the script.
3. Add the code below in the `Update()` method.
4. Drag the Rotation script onto both the Earth and the Sun.
```    void Update()
{
this.transform.RotateAround(this.transform.position,
Vector3.up, 200f * Time.deltaTime);
}
```

Here, the Earth or the Sun (`this.transform`) will spin around itself (`this.transform.position`) about the Y-axis (`Vector3.up`) at an angle of `200f * Time.deltaTime`. Again, the choice of speed for the angle is arbitrary. As with Orbit, you can expose it to the Inspector and adjust it if you like.

Note that it probably makes sense to use Prefabs rather than attaching the script to each GameObject, but since we don’t have many, I prefer to keep things simple in this particular example.

If you press Play, you should now see the Earth orbiting around the Sun, while both spin independently at the same time.

## Finishing Touches

In this section, we’ll make a few tweaks to the project settings to make things look a little nicer.

First, let’s disable the Skybox. To do this, open the Window menu, then click “Rendering” and Lighting:

In the Lighting window, switch to the Environment tab. The Skybox Material has a value of Default-Skybox. Click on the little circle next to that value and it select None from the new window that comes up.

Changing the Skybox has changed the fields in the Environment tab of the Lighting window. There is now an Ambient Color field. Set its value to white (by clicking the top-left part of the colour-picker square, or by setting each of the (R, G, B) values to 255. This makes the objects in the scene somewhat brighter:

Next, we’ll get rid of the annoying blue background colour, which looks as odd in outer space as the Skybox. To do that, select the Main Camera from the Hierarchy window, click on the value of its Background property, and set it to black by either clicking on the bottom portion of the colour-picker square, or by setting each of the (R, G, B) values to zero:

The last thing that’s looking awkward is the lighting: we have a Directional Light that came with the project template, and it’s illuminating both the Sun and the Earth. Delete it.

By either clicking the GameObject menu or else right-clicking inside the Hierarchy window, select Light -> Point Light to create a light that gives off light in all directions.

If you press Play, you’ll notice that the light is a little bit weak, so bump up its Intensity to 10. Then you should see a highlight shine off the Earth.

Finally, to make things a little crazier, I suggest adding another planet, such as Venus. To do this, follow the same steps you took when creating the Earth, with a few differences:

1. Create a new sphere, and name it “Venus”.
2. Set the Y component of its Position to 3.
3. Find an appropriate texture and drag it onto the Textures folder.
4. Drag that texture onto the Venus GameObject in either the Hierarchy or Scene window.
5. Drag both the Orbit and Rotation scripts onto Venus.
6. In the Inspector window, change the Speed setting on the Orbit script so that it is faster than the Earth’s speed, e.g. a value of 150.

Press Play and watch as Earth and Venus orbit the Sun with different speeds!

## Going Further

This simulation, while very simplistic and not really representing the real behaviour of heavenly bodies, is a fun little exercise showing what you can do in Unity3D with very little effort. There are lots of ways you can take this further. Here are a few ideas:

1. Learn about Prefabs, use them to create a template for the planets, and create the remaining planets of the Solar System.
2. Add the Moon orbiting the Earth. Use the same Orbit script, but modify it so that you can plug which GameObject is orbited via the Inspector.
3. Instead of specifying a different speed for each planet, try to calculate it based on the distance between the planet and the Sun.
4. Tilt the Earth so that it rotates on something closer to its real axis.
5. Experiment with elliptical orbits.

# Getting Started with Unity3D on Linux

If you have any sort of interest in game development, you’ve probably heard of Unity3D. And if you’ve used it before, you probably know that it has for a long time been restricted to Windows and Mac in terms of development platforms. That changed recently, when they added support for Linux. In this article, I’ll show you how I set up Unity3D on my Kubuntu 20.04 installation, and if the distribution you’re using is close enough, the same steps will likely work for you as well.

First, go to the Unity3D Download page and grab the Unity Hub.

Update 14th May 2023: if you get an error saying the repository isn’t signed, check out this forum post for a solution.

After Unity Hub has finished downloading, run it. It’s a cross-platform AppImage, so you can either double-click it or run it from the terminal.

Now you’re back in the Licence page of Unity Hub. Wait a few seconds for it to activate, then click the “Activate New License” button:

In the next window, select whichever options apply to you. If you’re just a hobbyist, Unity3D is free, so you can select the radio buttons as shown below. Click “Done” when you’re ready.

You now have a licence! Click the arrow at the top-left to go to the Projects section.

If you try to add a new project, you’ll realise that you need to install a version of the Unity3D editor first. Head over to the Installs section to do this.

In the Installs section, click the “Add” button:

Choose whichever version you prefer. The recommended LTS version is best if you need stability; otherwise you can use the latest and greatest version with the newest features.

Click “Next”, and you can now choose which platforms you want your builds to target and what documentation you want. If you’re just starting out, keep it simple and just leave the default “Linux Build Support” enabled. You can always add more stuff later if/when you need it.

Click “Done”, and wait for it to install…

When it’s done, head back to the Projects section. Click the “New” button to create a new project.

In the next window, select the type of project (3D by default), give it a name, and select a folder where your Unity3D projects will go (the new project will be created as a subfolder of this). Then click the “Create” button:

Wait for it…

And… that’s it! The editor then comes up, and you can begin creating your game.

If you need a quick place to start, check out my “Unity3D: Moving an Object with Keyboard Input” tutorial here at Gigi Labs, as well as my early Unity3D articles at Programmer’s Ranch.