I have a build mechanic in my game and I was wondering how I could make it so whenever I was placing the object down it would snap to a grid. Whenever I press 0 it moves the object to my mouse and whenever I click it places the object down. I want to make it snap to a grid when placing so objects dont collide.
using UnityEngine;
using UnityEngine.AI;
public class GroundPlacementController : MonoBehaviour
{
[SerializeField]
private GameObject placeableObjectPrefab;
public NavMeshObstacle nav;
[SerializeField]
private KeyCode newObjectHotkey = KeyCode.A;
private GameObject currentPlaceableObject;
private float mouseWheelRotation;
private void Update()
{
HandleNewObjectHotkey();
nav = GetComponent<NavMeshObstacle>();
if (currentPlaceableObject != null)
{
MoveCurrentObjectToMouse();
RotateFromMouseWheel();
ReleaseIfClicked();
}
}
private void HandleNewObjectHotkey()
{
if (Input.GetKeyDown(newObjectHotkey))
{
if (currentPlaceableObject != null)
{
Destroy(currentPlaceableObject);
}
else
{
currentPlaceableObject = Instantiate(placeableObjectPrefab);
}
}
}
private void MoveCurrentObjectToMouse()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo))
{
currentPlaceableObject.transform.position = hitInfo.point;
currentPlaceableObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal);
currentPlaceableObject.GetComponent<NavMeshObstacle>().enabled = false;
}
}
private void RotateFromMouseWheel()
{
Debug.Log(Input.mouseScrollDelta);
mouseWheelRotation += Input.mouseScrollDelta.y;
currentPlaceableObject.transform.Rotate(Vector3.up, mouseWheelRotation * 90f);
}
private void ReleaseIfClicked()
{
if (Input.GetMouseButtonDown(0))
{
currentPlaceableObject.GetComponent<NavMeshObstacle>().enabled = true;
print("disabled");
currentPlaceableObject = null;
print("removed prefab");
}
}
}
You can snap to grid in code by simply rounding each axis of the transform.position:
var currentPosition = transform.position;
transform.position = new Vector3(Mathf.Round(currentPosition.x),
Mathf.Round(currentPosition.y),
Mathf.Round(currentPosition.z));
A more mathematical approach, and one that you can easily set the grid size for (other than Lews Therin's answer) would be to:
position mod yourGridSize (say, your grid size is 64 and the position is 144. then: 144 mod 64 = 16)mod result and subtract from position: 144 - 16 = 128yourGridSize: 128 / 64 = 2Now you know your position is 2 blocks into the grid. Apply this operation for the three axis:
var yourGridSize = 64;
var currentPosition = currentPlaceableObject.transform.position;
currentPlaceableObject.transform.position = new Vector3(((currentPosition.x - (currentPosition.x % yourGridSize)) / yourGridSize) * yourGridSize,
((currentPosition.y - (currentPosition.y % yourGridSize)) / yourGridSize) * yourGridSize,
((currentPosition.z - (currentPosition.z % yourGridSize)) / yourGridSize) * yourGridSize);
Convoluted? Maybe. Effective? Heck yes!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With