How can I detect which face of a voxel block was hit using a Raycast in Unity?

I’m working on a voxel-style building game in Unity (similar to Minecraft), and I’m trying to determine which face of a cube (block) the player is pointing at using a Raycast from the camera.

Here’s what I’m trying to achieve:

When the crosshair (centre of the screen) points at a cube, I want to detect which face of that cube was hit (e.g., Top, Bottom, Left, Right, Front, Back).

Once I know the face, I can calculate the correct placement position for a new block adjacent to that face.

For example, in the image above, the crosshair is pointing at one face of the cube — how can I determine which face it is, and how do I find the exact world position where the new block should be placed?

Thanks for any help or suggestions! I really appreciate your time :blush:

What I’ve tried:

I’m using a standard Raycast like this:

if (Physics.Raycast(camera.position, camera.forward, out RaycastHit hit, range))
{
    // I can get hit.normal here
}

I know that “hit.normal” gives me the direction of the surface normal (like Vector3.up for the top face), but I’m not entirely sure how to reliably use it to calculate the correct adjacent block position — especially when looking diagonally (e.g., 45° angles).

How can I accurately determine the block face and place a new block next to it without misalignment or glitches?

I’m not too sure how it’s done efficiently, but adapting what you already have you should be able to use something like

Vector3 placePosition = hit.transform.position + hit.normal;
Instantiate(cubePrefab, placePosition, Quaternion.identity);

As long as your cubes aren’t rotated and are placed 1 units apart, the above should work I believe.

If your blocks are not placed in a (0,0,1) , (0,0,2), etc basis then the above will need tweaking to fit your unit size. The reason for this is hit.normal will return -

  • (1, 0, 0) → right face
  • (-1, 0, 0) → left face
  • (0, 1, 0) → top face
  • (0, -1, 0) → bottom face
  • (0, 0, 1) → front face
  • (0, 0, -1) → back face

Again, all untested but I think you could remedy this by multiplying the hit.normal by a sizeInt.

You don’t need to know the specific face. If you’re making a Minecraft style game, you should have a pure data layer for the voxel data. With you raycast hit, you can add the normal to the hit point (hit.point + hit.normal) to get a point that should be within the cell of the block you want to place.

You use this position and convert it to a coordinate position, update the block at that coordinate, which then gets updated by your visual layer.

To add to @spiney199 's answer:

The normal has a length of 1, so you may wish to multiply it to ensure it always will be clearly within the adjacent tile. If the voxels are 1x1x1 within the coordinate system, this might mean halving its length. Then you clamp the value to the coordinate system (i.e. floor or ceil in the case that each voxel is length of 1 on all sides) which gives you the coordinates of the new tile.

If you need to highlight the face you are going to be attaching the new tile to, iirc Minecraft’s old trick was to have a 3d cursor that’s nothing but a wireframe that always appears in the new tile’s spot, and so shows where the new tile “will” be, highlighting with a wireframe the edge of the voxel you’re pointing at. You could even make this cursor only have a wireframe on one side, and use the normal of the raycast hit to rotate it, and thus magically highlight just the side in question, without ever really knowing what it is…

Thanks for your suggestion, it was a great help !!

That makes perfect sense, thank you so much for the clear explanation! I really appreciate your help

That’s a really helpful explanation, thank you! Multiplying and clamping the normal to get a precise adjacent tile makes a lot of sense. I’ll try implementing that along with a simple wireframe preview, like you mentioned. It sounds like a great way to visualise placement before confirming the block. Really appreciate the detailed insight!