• Home  / 
  • Unity3D
  •  /  How to: Create a Unity3D building placement system for RTS or City builders – Let your player place a 3D object in the world

How to: Create a Unity3D building placement system for RTS or City builders – Let your player place a 3D object in the world

Many ‘sandbox’ type games are built around the idea of letting players place and build things in the world.  Your players might be placing turrets to defend from crazy hordes of orcs, building houses and structures for their virtual families, or just putting up barriers to keep other players and zombies away.  Whatever the game, it’s usually done by putting the object on the mouse cursor and letting the player move it around until it’s in place, then place it by clicking the mouse.  Today, I’ll show you how to get started with your own placement system in Unity3D.  We’ll build a Unity3D Building Placement system that allows you to place and rotate objects with the mouse cursor.

Video Version

Environment & Art

To start, you’ll need some sort of environment to place objects on.  You can grab just about anything from the free environments section of the asset store.  I’ll be using this Free Autumn Mountain.

The mountain does not have a mesh collider though, so I need to add one first

The Camera

In the mountain scene, the camera that’s placed is a bit high, and not tagged as “mainCamera“.  I moved it a bit and set the “mainCamera” tag on it.

Turret

We’ll also need something to place.  We could use a cube or some other primitive, but that’s a little boring, so I’m downloading a free turret from the asset store.

The turret came with some old standard assets stuff that won’t compile, and we don’t need it.. so I deleted those standard assets from the project view

The Code – Ground Placement Controller

To make our placement work, we’ll need a new c# script.  I’m going to name it GroundPlacementController.cs

Let’s take a look at this code and see what’s going on..

We start off with two serialized fields.  One for the prefab we’d like to place and another for the hotkey we’ll use to create a new object.  We keep these in private serialized fields so we can modify them in the editor later.

There are also two private fields, one to hold the object we’re currently placing, and another to deal with rotation.

In our Update method, we call a few things.  I prefer to call a couple well named methods in Update whenever possible, instead of doing actual work.  This makes it easier to see what’s going on at a quick glance and makes the code much easier to read.

Our first method checks to see if the player has pressed our new object hotkey (defaulted to A).  If they do, we either create a new object to place by using Instantiate, or we destroy the current one that’s on the cursor.  This lets our player cancel the placement easily if they change their minds.

Next, we check to see if there’s an object being placed – aka assigned to currentPlacableObject.

MoveCurrentObjectToMouse

If there is, we jump into our movement method.

In here, we do a raycast from the mouse position into the world.  The Camera’s ScreenPointToRay method will generate a ray beaming straight into the scene from our viewport.  This means we’ll get a physics ray that goes exactly where we click.

If we click on something that has a collider, the raycast will return that object in the hitInfo object we declare on line 46, and it will return true, running the code to place our current object at that hitinfo.point.

We’ll also set the rotation of the object using FromToRotation.  This will make the object always point upward, so if we place it on a slope, it’ll look right and not just clip through sideways.

RotateFromMouseWheel

Next, we go into the method to rotate based on our mouse wheel.  This assumes we want the player to be able to adjust the orientation of their placed objects..

In here, we adjust the mouseWheelRotation by the mouseScrollDelta Y value.  Then we rotate the current object using the Up vector and the current value of the mouseWheelRotation.  We also multiply it by 10 to make it a bit faster / more sensitive.

ReleaseIfClicked

The final method is there to ‘place’ or release our object.  All we do here is check for a click, and if we get one, we clear out the currentPlaceableObject.

Adding the Manager

Create an empty gameobject in the scene.

Add the GroundPlacementController component.

Assign the turret prefab (or your own)

Press play!

Conclusion / Extensions

This covers the basics of placing an object with your mouse cursor.  In a bigger game, you may want to extend out the object selection, maybe have an array of placable objects and a hotkey to cycle through them, or even a full UI to select one.  You could also fire some event when the object is released, play an animation.. set it to start firing?  You could also swap the material when the object is being placed and give it a holographic look.

  • This is a really handy starting point but does go rather haywire if the collider for the placeable stretches below the transform’s zero position (sometimes the transform position is at the centre of the mesh, for example). My placeable shelter would fly toward me at great speed as soon as I pressed ‘A’.

    A partial fix seems to be to calculate the vertical offset between the transform y position and the collider’s bounds.min.y (if there is a collider of course) after instantiation then, in

    MoveCurrentObjectToMouse,

    to move the placeable to hitInfo.point + hitInfo.normal * verticalOffset, rather than just hitInfo.point. This mostly seems to work for me, but occasionally struggles on bumpy ground.

    Personally I find it much easier to work from a starting point, like your tutorial, and deal with any small issues rather than just trying to start from scratch, so thank you for this.

    • Ah yea if your pivot point isn’t in the right spot (should be center bottom), it’s gonna place the thing in the ground. There are a couple ways to address that though. You can go into blender and with about 10-15 minutes of messing around you can get it moved (it’s not too complicated, but I never remember the steps when I first jump in).

      Alternatively, you can parent it to an empty gameobject and offset it, then use the empty gameobject as the prefab, which will make the mesh always offset correctly.

      Ideally, I’d give the blender option a shot. Just search for “move pivot point in blender”. Maybe I’ll write up a quick guide for us non-artists to fix that stuff.. would be good for me as well 🙂