在UI Canvas的Render Mode模式是Screen Space-Camera模式极其容易3D坐标值转UI坐标出错。
**具体原因是:**Canvas的Rect Transform锁定,其Scale的倍数值不是1,所以导致从3D的坐标数值转换成UI坐标时就会出现问题。
正确做法:
1、 声明变量: 3D物体、 UI的RectTransform、 Canvas的RectTransform、 Canvas所使用的Camera
2、将物体的世界坐标转换为Canvas内的局部坐标
3、设置UI元素的位置为Canvas内的局部坐标
代码:文章来源:https://www.toymoban.com/news/detail-617693.html
public class TitileMove : MonoBehaviour
{
// 3D物体
public Transform object3D;
// UI Image的RectTransform
public RectTransform uiImageRectTransform;
// Canvas的RectTransform
public RectTransform canvasRectTransform;
// Canvas所使用的Camera
public Camera canvasCamera;
public GameObject lastSelectedObject;
private bool isDragging = false;
private bool isRotating = false;
private Vector3 lastMousePosition;
private void OnBecameInvisible()
{
// 当物体不可见时,隐藏UI元素
uiImageRectTransform.gameObject.SetActive(false);
}
void Update()
{
// 如果鼠标左键按下
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
// 射线检测是否点击到物体
if (Physics.Raycast(ray, out hit))
{
GameObject selectedObject = hit.collider.gameObject;
// 判断是否点击到了我们想要拖拽的物体
if (selectedObject.transform.name == "3")
{
uiImageRectTransform.gameObject.SetActive(true);
// 开始拖拽
// 将物体的世界坐标转换为Canvas内的局部坐标
Vector2 localPos;
RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTransform, Camera.main.WorldToScreenPoint(selectedObject.transform.position), canvasCamera, out localPos);
// 设置UI元素的位置为Canvas内的局部坐标
localPos = new Vector2(localPos.x - 249, localPos.y + 70);
uiImageRectTransform.localPosition = localPos;
lastSelectedObject = selectedObject;
Vector3 objectPosition = selectedObject.transform.position;
lastMousePosition = Input.mousePosition;
}
else
{
// 隐藏UI元素
uiImageRectTransform.gameObject.SetActive(false);
}
}
isRotating = true;
// 检测物体是否不可见并隐藏UI元素
if (lastSelectedObject != null && IsObjectInvisible(lastSelectedObject))
{
uiImageRectTransform.gameObject.SetActive(false);
}
}
if (isRotating && object3D != null)
{
// 获取当前鼠标位置和上一帧鼠标位置之间的差值
Vector3 deltaMouse = Input.mousePosition - lastMousePosition;
// 根据差值来计算旋转角度
float rotationSpeed = 0.25f; // 调整旋转速度
float rotationY = deltaMouse.x * rotationSpeed;
// 应用旋转
object3D.transform.Rotate(Vector3.up, -rotationY, Space.World);
// 更新上一帧鼠标位置
lastMousePosition = Input.mousePosition;
if (uiImageRectTransform != null)
{
// uiImageRectTransform.GetComponent<RectTransform>().anchoredPosition = new Vector2(uiImageRectTransform.GetComponent<RectTransform>().anchoredPosition.x + deltaMouse.x, uiImageRectTransform.GetComponent<RectTransform>().anchoredPosition.y);
// 将物体的世界坐标转换为屏幕坐标
Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(null, uiImageRectTransform.position);
// 将屏幕坐标转换为Canvas内的局部坐标
RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTransform, screenPos, null, out Vector2 localPos);
localPos = new Vector2(localPos.x + deltaMouse.x, localPos.y);
// 设置物体的局部坐标
uiImageRectTransform.anchoredPosition = localPos;
}
}
// 如果鼠标左键释放
if (Input.GetMouseButtonUp(0))
{
isRotating = false;
}
}
// 检测物体是否不可见
private bool IsObjectInvisible(GameObject obj)
{
// 获取物体的包围盒
Bounds bounds = obj.GetComponent<Renderer>().bounds;
// 获取摄像机的视锥体平面
Plane[] frustumPlanes = GeometryUtility.CalculateFrustumPlanes(Camera.main);
// 检查包围盒是否与视锥体相交
return !GeometryUtility.TestPlanesAABB(frustumPlanes, bounds);
}
// 检测物体是否被遮挡
private bool IsObjectOccluded(GameObject obj)
{
// 获取摄像机到物体的方向
Vector3 directionToTarget = obj.transform.position - Camera.main.transform.position;
// 发射射线
Ray ray = new Ray(Camera.main.transform.position, directionToTarget);
RaycastHit hit;
// 射线检测是否有其他碰撞器位于射线路径上
if (Physics.Raycast(ray, out hit, directionToTarget.magnitude))
{
// 如果射线击中的物体不是目标物体,则表示目标物体被遮挡
if (hit.collider.gameObject != obj)
{
return true;
}
}
return false;
}
}
重点文章来源地址https://www.toymoban.com/news/detail-617693.html
// 将物体的世界坐标转换为Canvas内的局部坐标
Vector2 localPos;
RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTransform, Camera.main.WorldToScreenPoint(selectedObject.transform.position), canvasCamera, out localPos);
// 设置UI元素的位置为Canvas内的局部坐标
localPos = new Vector2(localPos.x - 249, localPos.y + 70);
uiImageRectTransform.localPosition = localPos;
到了这里,关于Unity3D坐标与UI坐标转化差别过大的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!