1、需要射線檢測的物體先加個collider組件,方便射線檢測到
2、第一種方式通過獲取點擊UI界面的UI座標A,將A轉換爲RawImage的相對座標B,再將B轉爲映射相機的視口(Viewport)座標C,然後在映射相機發射射線對穿過的物體進行檢測
代碼如下:
using UnityEngine;
using UnityEngine.UI;
public class TestRenderTexture : MonoBehaviour
{
// 點擊RawImage時,相對RawImage自身的座標
private Vector2 ClickPosInRawImg;
// 畫布
public Canvas Canvas;
// 預覽映射相機
public Camera PreviewCamera;
public RawImage PreviewImage;
public Camera UiCamera;
private Vector3 MousePos;
void Start(){}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
MousePos = Input.mousePosition;
}
if (MousePos != null)
{
CheckDrawRayLine(Canvas, Input.mousePosition, PreviewImage, PreviewCamera);
}
}
/// <summary>
/// 射線投射
/// </summary>
/// <param name="canvas">畫布</param>
/// <param name="mousePosition">當前Canvas下點擊的鼠標位置</param>
/// <param name="previewImage">預覽圖</param>
/// <param name="previewCamera">預覽映射圖的攝像機</param>
void CheckDrawRayLine(Canvas canvas, Vector3 mousePosition, RawImage previewImage, Camera previewCamera)
{
// 將UI相機下點擊的UI座標轉爲相對RawImage的座標
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, mousePosition, UiCamera, out ClickPosInRawImg))
{
// Lylibs.MessageUtil.Show("座標:x=" + ClickPosInRawImg.x + ",y=" + ClickPosInRawImg.y);
//獲取預覽圖的長寬
float imageWidth = previewImage.rectTransform.rect.width;
float imageHeight = previewImage.rectTransform.rect.height;
//獲取預覽圖的座標,此處RawImage的Pivot需爲(0,0),不然自己再換算下
float localPositionX = previewImage.rectTransform.localPosition.x;
float localPositionY = previewImage.rectTransform.localPosition.y;
//獲取在預覽映射相機viewport內的座標(座標比例)
float p_x = (ClickPosInRawImg.x - localPositionX) / imageWidth;
float p_y = (ClickPosInRawImg.y - localPositionY) / imageHeight;
//從視口座標發射線
Ray p_ray = previewCamera.ViewportPointToRay(new Vector2(p_x, p_y));
RaycastHit p_hitInfo;
if (Physics.Raycast(p_ray, out p_hitInfo))
{
//顯示射線,只有在scene視圖中才能看到
Debug.DrawLine(p_ray.origin, p_hitInfo.point);
// Debug.Log(p_hitInfo.transform.name);
}
}
}
}
3、第二種方式直接寫個繼承RawImage的類A,在A裏直接通過監聽RawImage的點擊事件獲取相對RawImage的點擊座標B,將A轉換爲RawImage的相對座標B,再將B轉爲映射相機的視口(Viewport)座標C,然後在映射相機發射射線對穿過的物體進行檢測,感覺比第一種方便些
代碼如下:
using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace Lylibs
{
public class LyRawImage : RawImage, IPointerClickHandler
{
// 點擊RawImage時,相對RawImage自身的座標
private Vector2 ClickPosInRawImg;
// 預覽映射相機
private Camera PreviewCamera;
private XLua.LuaTable ObjTable;
private Action<XLua.LuaTable, Vector2, Transform> CallFun = null;
void Start()
{
// 初始獲取預覽映射相機
if (PreviewCamera == null)
{
PreviewCamera = GameObject.Find("[CAMERAs]").transform.Find("[RENDER_TEXTURE_CAMERA]").GetComponent<Camera>();
}
}
void Update()
{
#if UNITY_EDITOR
CheckDrawRayLine(false);
#endif
}
void IPointerClickHandler.OnPointerClick(PointerEventData eventData)
{
// 獲取相對RawImage的點擊座標
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out ClickPosInRawImg))
{
// Lylibs.MessageUtil.Show("座標:x=" + ClickPosInRawImg.x + ",y=" + ClickPosInRawImg.y);
CheckDrawRayLine(true);
}
}
// 檢查是否需要繪製射線
void CheckDrawRayLine(bool isCallBack)
{
if (PreviewCamera != null && ClickPosInRawImg != null)
{
//獲取預覽圖的長寬
float p_imageWidth = rectTransform.rect.width;
float p_imageHeight = rectTransform.rect.height;
//獲取預覽圖的座標
float p_localPositionX = rectTransform.localPosition.x;
float p_localPositionY = rectTransform.localPosition.y;
//獲取在預覽映射相機viewport內的座標(座標比例)
float p_x = ClickPosInRawImg.x / p_imageWidth;
float p_y = ClickPosInRawImg.y / p_imageHeight;
//從預覽映射相機視口座標發射線
Ray ray = PreviewCamera.ViewportPointToRay(new Vector2(p_x, p_y));
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo))
{
//顯示射線,只有在scene視圖中才能看到
Debug.DrawLine(ray.origin, hitInfo.point);
// Debug.Log(hitInfo.transform.name);
if (isCallBack == true && ObjTable != null && CallFun != null)
{
CallFun(ObjTable, ClickPosInRawImg, hitInfo.transform);
}
}
}
}
public void SetEventCall(XLua.LuaTable table, Action<XLua.LuaTable, Vector2, Transform> call)
{
ObjTable = table;
CallFun = call;
}
}
}
4、此種實現諸如如下的效果方便: