Одна проблема состоит в том, что ваша разница между столкновением луча с поверхностью здания и землей, и вы добавляете его к земле, чтобы получить источник преобразования.
Вместо этого установите смещение в зависимости от того, где луч игрока падает на землю:
private void TestObjectSelection()
{
Ray ray = _cam.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray.origin, ray.direction, out RaycastHit hitInfo, 200f, _objectsLayerMask, QueryTriggerInteraction.Ignore))
{
if (hitInfo.transform.gameObject == _movableObject)
{
Plane groundPlane = new Plane(Vector3.up, Vector3.zero);
float groundDistance;
groundPlane.Raycast(ray, out groundDistance);
Vector3 groundPoint = ray.GetPoint(groundDistance);
// groundPoint is guaranteed y=0, so _objectSelectionOffset y=0;
_objectSelectionOffset = _movableObject.transform.position - groundPoint;
_objectIsSelected = true;
}
}
}
Если ваша земля не плоскость, вы можете использовать другую Physics.Raycast
, чтобы получить groundPoint
:
private void TestObjectSelection()
{
Ray ray = _cam.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray.origin, ray.direction, out RaycastHit hitInfo, 200f, _objectsLayerMask, QueryTriggerInteraction.Ignore))
{
if (hitInfo.transform.gameObject == _movableObject)
{
if (Physics.Raycast(ray.origin, ray.direction, out RaycastHit hitInfo, 200f, _groundLayerMask, QueryTriggerInteraction.Ignore))
{
_objectSelectionOffset = _movableObject.transform.position - hitInfo.point;
_objectIsSelected = true;
}
}
}
}
В любом случае, вы можете установить положение на основе смещения:
private Vector3 GetNewPosition()
{
if (_movableObject != null)
{
Ray ray = _cam.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray.origin, ray.direction, out RaycastHit hitInfo, 200f, _groundLayerMask, QueryTriggerInteraction.Ignore))
{
return hitInfo.point + _objectSelectionOffset;
}
}
return _movableObject.transform.position;
}