Unity点击RawImage获取RenderTexture的映射物体

43 篇文章 1 订阅
26 篇文章 3 订阅

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、此种实现诸如如下的效果方便:

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
Unity中通过点击RawImage获取RenderTexture的映射物体需要编写一些脚本逻辑。首先,在场景中创建一个RawImage和一个空物体,并将RawImage设为UI元素。接下来,我们需要在脚本中实现点击RawImage的功能。 首先,在需要实现点击事件的脚本中添加以下代码段: ```csharp using UnityEngine; using UnityEngine.EventSystems; public class ClickRawImage : MonoBehaviour, IPointerClickHandler { public GameObject mappedObject; // 映射物体 public RenderTexture renderTexture; // 渲染纹理 public void OnPointerClick(PointerEventData eventData) { // 获取点击的位置 Vector2 localCursor; RectTransformUtility.ScreenPointToLocalPointInRectangle(GetComponent<RectTransform>(), eventData.position, null, out localCursor); // 将点击的位置转换为纹理坐标 Vector2 textureCoordinates = new Vector2(localCursor.x / GetComponent<RectTransform>().rect.width + 0.5f, localCursor.y / GetComponent<RectTransform>().rect.height + 0.5f); // 根据纹理坐标获取映射的位置 Ray ray = Camera.main.ViewportPointToRay(textureCoordinates); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { // 获取点击位置的映射物体 mappedObject = hit.transform.gameObject; } } } ``` 在脚本中,我们需要实现接口`IPointerClickHandler`来响应RawImage点击事件。在点击事件回调函数`OnPointerClick`中,首先计算出点击的位置`localCursor`,然后将其转换为纹理坐标`textureCoordinates`。接着,根据纹理坐标通过Raycast来获取点击位置的映射物体,并将其赋值给`mappedObject`。 最后,将该脚本挂载到RawImage上,并将相应的RenderTexture赋值给脚本中的`renderTexture`变量。这样,当点击RawImage时,就可以通过点击位置获取映射物体了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值