В моей игре есть механика сборки, и мне было интересно, как сделать так, чтобы всякий раз, когда я помещал объект вниз, он привязывался к сетке. Всякий раз, когда я нажимаю 0, он перемещает объект к моей мыши, а всякий раз, когда я нажимаю, он кладет объект вниз. Я хочу, чтобы при размещении он привязывался к сетке, чтобы объекты не сталкивались.
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");
}
}
}




Вы можете привязаться к сетке в коде, просто округлив каждую ось transform.position:
var currentPosition = transform.position;
transform.position = new Vector3(Mathf.Round(currentPosition.x),
Mathf.Round(currentPosition.y),
Mathf.Round(currentPosition.z));
Более математический подход, для которого вы можете легко установить размер сетки (кроме ответа Льюса Терина), будет заключаться в следующем:
positionmodyourGridSize (скажем, размер вашей сетки 64 и позиция 144. тогда: 144 mod 64 = 16)mod и вычтите из позиции: 144 - 16 = 128.yourGridSize: 128/64 = 2.Теперь вы знаете, что ваша позиция — 2 блоков в сетке. Примените эту операцию для трех осей:
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);
Запутанный? Может быть. Эффективно? Черт, да!
@fhc, где бы я разместил это в сценарии, над методом обновления не работает, поскольку он говорит, что не распознает переменные положения
Я верю в ваш метод MoveCurrentObjectToMouse() при назначении на currentPlaceableObject.transform.position.
@fhcimolin Это не сработает, во-первых, объект помещается примерно на 100 единиц вправо от меня, а во-вторых, он остается только в этом месте, и всякий раз, когда я пытаюсь переместить его с помощью мыши, он дрожит и возвращается. Подождите, неважно, я только что изменил размер сетки, и теперь все работает нормально, спасибо.
Не забудьте не разделить, если вы хотите, чтобы координаты проложили объект в, чтобы расположить его в сетке.