ScreenPointToLocalPointInRectangle
public static bool ScreenPointToLocalPointInRectangle(RectTransform rect, Vector2 screenPoint, Camera cam, out Vector2 localPoint);
- rect: 对应的 RectTransform 的引用
- screenPoint: 位置,基于屏幕坐标系
- cam: 相机的引用,如果Canvas的Render Mode 为 Screen Space - Camera 模式,则需要填入 Render Camera 对应的引用
- localPoint: rect 本地坐标系下的坐标(原点(0,0)位置受Anchor的影响)
应用1:判断鼠标或者触摸点击位置在UI范围之外,则执行某个动作,比如关闭
using UnityEngine;
using UnityEngine.EventSystems;
using System;
using System.Collections.Generic;
public class UI_ClickOutsideHide : MonoBehaviour
{
private Rect m_rect;
private Camera m_uguiCamera;
private Transform m_canvas;
private bool m_canCheck = false;
private float width = 0;
private float height = 0;
private RectTransform rectTrans;
private List<RectTransform> lstExtraRectTransform = new List<RectTransform>();
private List<Rect> lstExtraRect = new List<Rect>();
private void Awake()
{
this.rectTrans = this.GetComponent<RectTransform>();
}
Transform UICanvas
{
get
{
if (m_canvas == null)
{
m_canvas = UIManager.Instance.GetCanvas().transform;
}
return m_canvas;
}
}
Camera UGUICamera
{
get
{
if (m_uguiCamera == null)
{
m_uguiCamera = UIManager.Instance.GetCamera();
}
return m_uguiCamera;
}
}
void OnEnable()
{
m_canCheck = true;
}
void OnDisable()
{
m_canCheck = false;
}
private void OnResize()
{
Vector3[] corners = new Vector3[4];
this.rectTrans.GetWorldCorners(corners);
float width = Math.Abs(Vector2.Distance(corners[0], corners[3]));
float height = Math.Abs(Vector2.Distance(corners[0], corners[1]));
m_rect = new Rect(corners[0].x, corners[0].y, width, height);
for (var index = 0; index < lstExtraRectTransform.Count; index++)
{
var rectTransform = lstExtraRectTransform[index];
lstExtraRect[index] = GetRect(rectTransform);
}
}
private Rect GetRect(RectTransform targetRect)
{
var corners = new Vector3[4];
targetRect.GetWorldCorners(corners);
var width = Math.Abs(Vector2.Distance(corners[0], corners[3]));
var height = Math.Abs(Vector2.Distance(corners[0], corners[1]));
return new Rect(corners[0].x, corners[0].y, width, height);
}
// Update is called once per frame
void Update()
{
if (!m_canCheck)
{
return;
}
if (this.width != this.rectTrans.rect.width && this.height != this.rectTrans.rect.height)
{
this.OnResize();
this.width = this.rectTrans.rect.width;
this.height = this.rectTrans.rect.height;
}
if (Input.GetMouseButtonDown(0) || (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began))
{
if (Application.platform == RuntimePlatform.WindowsPlayer ||
Application.platform == RuntimePlatform.WindowsEditor ||
Application.platform == RuntimePlatform.WindowsWebPlayer)
{
if (EventSystem.current.IsPointerOverGameObject())
{
Vector3 curPos = TransToWorldPos(Input.mousePosition);
if (m_rect.Contains(curPos))
{
return;
}
for (var index = 0; index < lstExtraRect.Count; index++)
{
var rect = lstExtraRect[index];
if (rect.Contains(curPos))
{
return;
}
}
gameObject.SetActive(false);
}
}
else if (Application.platform == RuntimePlatform.IPhonePlayer ||
Application.platform == RuntimePlatform.Android)
{
if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
{
Vector3 curPos = TransToWorldPos(Input.mousePosition);
if (m_rect.Contains(curPos))
{
return;
}
for (var index = 0; index < lstExtraRect.Count; index++)
{
var rect = lstExtraRect[index];
if (rect.Contains(curPos))
{
return;
}
}
gameObject.SetActive(false);
}
}
}
}
private Vector2 TransToWorldPos(Vector3 mousePosition)
{
Vector3 worldPosition;
RectTransformUtility.ScreenPointToWorldPointInRectangle(UICanvas.GetComponent<RectTransform>(), mousePosition,
UGUICamera, out worldPosition);
return worldPosition;
}
public void AddExtraOutSide(RectTransform rectTransform)
{
if (lstExtraRectTransform.Contains(rectTransform))
{
return;
}
lstExtraRectTransform.Add(rectTransform);
lstExtraRect.Add(GetRect(rectTransform));
}
}
应用2:在Canvas不同的渲染模式(RenderMode)下实现UI跟随3D物体
- 当Canvas.RenderMode为Screen Space-Overlay时
利用WorldToScreenPoint(worldPos)将物体的世界坐标转换成屏幕坐标,实时更新UI的坐标:
using UnityEngine;
using System.Collections;
public class FollowWorldObj : MonoBehaviour {
[SerializeField]
GameObject worldPos;//3D物体(人物)
[SerializeField]
RectTransform rectTrans;//UI元素(如:血条等)
public Vector2 offset;//偏移量
// Update is called once per frame
void Update () {
Vector2 screenPos=Camera.main.WorldToScreenPoint(worldPos.transform.position);
rectTrans.position = screenPos + offset;
}
}
- 当Canvas.RenderMode为Screen Space-Camera时
利用RectTransformUtility.ScreenPointToLocalPointInRectangle换算出UI元素在Canvas的2D坐标:
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
public class UI_FollowObj : MonoBehaviour {
[SerializeField]
Camera UI_Camera;//UI相机
[SerializeField]
RectTransform image;//UI元素
[SerializeField]
GameObject obj;//3D物体
[SerializeField]
Canvas ui_Canvas;
// Update is called once per frame
void Update () {
UpdateNamePosition();
}
/// <summary>
/// 更新image位置
/// </summary>
void UpdateNamePosition()
{
Vector2 mouseDown = Camera.main.WorldToScreenPoint(obj.transform.position);
Vector2 mouseUGUIPos = new Vector2();
bool isRect = RectTransformUtility.ScreenPointToLocalPointInRectangle(ui_Canvas.transform as RectTransform, mouseDown, UI_Camera, out mouseUGUIPos);
if (isRect)
{
image.anchoredPosition = mouseUGUIPos;
}
}
}
网友评论