Placing Items via Mouse Click

Hello,

I’m currently working on a small, one-man-developed Tower Defense game. I was hoping to avoid asking for help on these forums -not because I don’t like you! -, but because I wanted to figure things out on my own. However, I’ve come to a place that I find myself having the need to ask for help, so hear me pleas!:slight_smile:

I have created the path finding code that the creeps use to navigate the maze as well as a Tower AI code that finds all enemies within its range and determines which one to attack. The code also inflicts damage, kills, and destroys the creep after a couple second delay to allow for a death animation/special FX.

However, I currently am stumped on how to go about placing my towers! I’m a bit confused on the logic behind their placement, and the code required to place them. I read the few questions and answers I could find and realized that ray-casting should be utilized, but I still have a couple of questions.

While I currently only have one type of tower programmed, I plan to have three different ‘classes’, if you will. Class 1 will only be able to be placed on land, Class 2 in the water, and Class 3 in the air (some environments are in the sky and the like). I was looking up using a sort of grid system, but couldn’t find much. If I missed an answer or resource that is glaringly obvious, please forgive me.

However, I should also add that in some levels, there are changes in elevation so what might be good elevation-wise in one part of the level might be off on another part. Because of this, using a plane for the entire grid is out of the question.

My idea is kind of simple, and I ask that somebody either confirm or reject my logic. I would create three different prefabs -one for each tower class-. The prefab would be a square plane that I could manually place through the level. I could line up and place each ‘tile’ appropriately depending on the area (ground, water, sky). Each tile would also be textured as well and tagged either Land, Sea, or Air.

Mesh-render would be turned off until the player went to place a tower, on which it would be turned on revealing all of the possible placements of the tower depending on the tower’s tag. Once the player was finished placing towers, the mesh-render would be turned back off.

With that theory/logic out of the way, I have one more question assuming what I have thought up is plausible/do-able. Placing the towers is currently presenting more of the problem for me. From my understanding, using raycast to place on object via a mousclick is kind of… too precise. For instance, if one of my grid tiles is located at 0,0,0, and I click at .3,0,.1, the tower will be placed there instead where the grid is (0,0,0).

Does unity have a “place on” function of sorts? I’d like it so that if I clicked within the collider/area of the grid tile, it would spawn the object in the exact same place as the grid tile, almost like it’d be using the tile as a spawn point.

There’s also the issue of choosing the tower to place. I’d like to have on-screen buttons that the player can click to choose the type of tower they wish to place. When the button is clicked, the tower will appear over their cursor with a ‘ghosting’ material. I figured I could use raycasting to project the ghosted tower; to show the player which grid they would currently be building on, the grid tile would light up or do something similar to signify that it is the active grid tile. When the tower is placed, it would snap to a precise location and the normal material would be applied.

Now that I’m typing this, everything seems a bit more clear. Maybe I just had to write it down for it all to make sense, but any help would be greatly appreciated. I’m not asking for code; I’m just wondering if my logic is sound and am asking for some pointers in the right direction.

Thank you all!:slight_smile:

There may be better solutions for this than the one I will present you but I think you only need some directions for this, so thats ok.

You mentioned a Grid System and different heights, so I suggest that you create a new prefab with no (or deactivated so that you can create some kind of building place preview later) MeshFilter/MeshRenderer attachted to it, but with a BoxCollider, this box collider has the dimensions you need for your grid cell sizes.

On the prefab you can attach a custum script which reacts to:

In these functions you can add the logic for the ghosting and building of your towers.

Ghosting goes to OnMouseEnter: create and store the unfunctional ghost version of the currently selected tower, store this ghost version in a variable.

Remove the stored ghost version in OnMouseExit.

Create the final tower and remove the stored ghost version in OnMouseUp.

On all places you want to be able to build you can now instantiate this prefab and voila finished.

Unfortunately I can only be brief as I’m on my lunch break. Select the objects with a GUI button. Ensure that you use something like**if (rect.Contains(Input.mousePosition)) to avoid Raycasting your terrain. Activate a placingmode in Update with a boolean and feed your ghost object the mouseposition in worldspace for the duration of your placement period so you can move the object with the cursor. I have some code but not on me, sounds like your more than able though. For the precise placement you could use the distance to some sort of hidden placement marker. On my iPhone so hopefully that made sense.*

Thanks for the replies. Unfortunately, I must go provide “world-class customer service” at my place of employment for the next ten or so hours, so I won’t be able to try anything until then. I’ll see what I can do with the suggestions/pointers, thanks!

Mathf.Round( float )
would be useful here for grid locking.
you would take the round to get an integer. Mod the int (%) to get the remainder. Multiply that by the size of your tiles to get their placement in world space. If you were to do it that way.

I would stick with getting the hit info and rounding it to the grid points then drawing my prefab ghosts at those points.
I would also use a state machine for the mouse input.

        public enum InputState
        {
            NONE,
            PLACING_TOWER,
        }

soemthing like that for doing click only input. If you want drag and drop (drag from button to world for placement), you may want to use a different input state then.

Basically what i’m trying to say is that yes, everything you want is possible.