# Minecraft style block placement

hello everybody, i am trying to make kind of a minecraft like block placment mecanic, i have the block placement half done, the main problem i have now is the fact that i have no idea on how to snap the block into a possition. if someone has any idea on ow to make this happen pls let me know. note that i am certainly not asking for code, simply an idea on how can this be done. thanks a lot for your help.

I found this tutorial really useful. It starts with a Minecraft like system, but takes it much further later on.

This is a simple way I came up with:

As you may have guessed, the idea is to cast a ray in the player camera’s forward direction, and we are interested in the point of collision of this ray.

Destroying a block is simple, we just identify the `Collider`’s `gameObject`, and destroy it, like this:

``````if (Input.GetKeyDown(KeyCode.Mouse0))  // left click --> destroy block
{
RaycastHit hitInfo;
if (Physics.Raycast(playerCam.transform.position, playerCam.transform.forward, out hitInfo, range, playerMask))
{
Destroy(hitInfo.collider.gameObject);
}
}
``````

That’s really all there is to it.

Now, to place a block, it’s slightly trickier, but not that bad: We have to find which face of the block the
player is aiming at. For that, We cast a ray, identify the collider’s
`gameObject`, specifically its position (we call P) in world space (the idea is that the block’s
reference frame will lie right in the center of the block). Position P will have components x, y and z.
The key here is that P lies on the face of the block (obviously), but this means one of the components
of P finishes with .5. because in my case, the block has side length 1 unit.
We look at the relative position between point P and the position of the center of the block. One of its comonents will be -0.5f or 0.5f, and we just need to check will one! We write a method like this:

``````Vector3 SnappedPosition(Vector3 pointToSnap, Vector3 blockCenterPosition)
{
Vector3 relativePosition = pointToSnap - blockCenterPosition;

if (relativePosition.x == 0.5f) return blockCenterPosition + Vector3.right;
else if (relativePosition.x == -0.5f) return blockCenterPosition + Vector3.left;
else if (relativePosition.y == 0.5f) return blockCenterPosition + Vector3.up;
else if (relativePosition.y == -0.5f) return blockCenterPosition + Vector3.down;
else if (relativePosition.z == 0.5f) return blockCenterPosition + Vector3.forward;
else if (relativePosition.z == -0.5f) return blockCenterPosition + Vector3.back;
else return Vector3.zero;  // error (should not occur)
}
``````

This will return the position the block’s center will lie at. Then we call this function after ray casting,
like so:

``````if (Input.GetKeyDown(KeyCode.Mouse1))  // right click --> place block
{
RaycastHit hitInfo;
if (Physics.Raycast(playerCam.transform.position, playerCam.transform.forward, out hitInfo, range))
{
Vector3 instantiatePosition = SnappedPosition(hitInfo.point, hitInfo.collider.transform.position);
Instantiate(editingInfo.currentGameObject, instantiatePosition, Quaternion.identity);
}
}
``````

The complete code (which should be attached to the player Game Onject) will look like this:

``````using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EditingTerrain : MonoBehaviour
{

public Camera playerCam;

public float range = 10f;

public EditingInfo editingInfo;  // to retrieve the currently selected block from another script

Vector3 SnappedPosition(Vector3 pointToSnap, Vector3 blockCenterPosition)
{
Vector3 relativePosition = pointToSnap - blockCenterPosition;

if (relativePosition.x == 0.5f) return blockCenterPosition + Vector3.right;
else if (relativePosition.x == -0.5f) return blockCenterPosition + Vector3.left;
else if (relativePosition.y == 0.5f) return blockCenterPosition + Vector3.up;
else if (relativePosition.y == -0.5f) return blockCenterPosition + Vector3.down;
else if (relativePosition.z == 0.5f) return blockCenterPosition + Vector3.forward;
else if (relativePosition.z == -0.5f) return blockCenterPosition + Vector3.back;
else return Vector3.zero;  // error (should not occur)
}

void Start()
{
// to avoid collision with player camera during raycast
}

// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse0))  // left click --> destroy block
{
RaycastHit hitInfo;
if (Physics.Raycast(playerCam.transform.position, playerCam.transform.forward, out hitInfo, range, playerMask))
{
Destroy(hitInfo.collider.gameObject);
}
}

if (Input.GetKeyDown(KeyCode.Mouse1))  // right click --> place block
{
RaycastHit hitInfo;
if (Physics.Raycast(playerCam.transform.position, playerCam.transform.forward, out hitInfo, range))
{
Vector3 instantiatePosition = SnappedPosition(hitInfo.point, hitInfo.collider.transform.position);
Instantiate(editingInfo.currentGameObject, instantiatePosition, Quaternion.identity);
}
}
}
}
``````

Hope that helps, even if I’m 6 years late.