Unity 3d 4.6 Raycast在精灵上忽略alpha

时间:2015-03-23 11:12:39

标签: c# unity3d

所以我有这个image我正在使用它来检测拖动事件,以便用户可以从屏幕一侧拉动滚动。问题是我有一个位于粘土密封上方的按钮,它被滚动图片的矩形阻挡。由于滚动移动我不能完全按下它的按钮。所以我问是否有办法忽略滚动上的alpha并让光线投射通过它。我已经有一个使用盒式对撞机的脚本并实现了ICanvasRaycastFilter,但由于某些原因它似乎不能使用统一滚动矩形。这是完整的脚本:

using UnityEngine;
using System.Collections;

public class RaycastFilter : MonoBehaviour, ICanvasRaycastFilter
{
    private RectTransform rectTransform;
    private new BoxCollider2D collider2D;

    public void Awake()
    {
        rectTransform = GetComponent<RectTransform>();
        collider2D = GetComponent<BoxCollider2D>();
    }

    public bool IsRaycastLocationValid(Vector2 screenPosition, Camera raycastEventCamera) //uGUI callback
    {
        // If we don't have a collider we will simply use the big button box. //TODO: make custom exception for this.
        if (collider2D == null)
            return true;

        Vector2 localPoint;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPosition, raycastEventCamera, out localPoint);

        Vector2 pivot = rectTransform.pivot - new Vector2(0.5f, 0.5f);

        Vector2 pivotScaled = Vector2.Scale(rectTransform.rect.size, pivot);

        Vector2 realPoint = localPoint + pivotScaled;

        Rect colliderRect = new Rect(
            collider2D.center.x - collider2D.size.x / 2,
            collider2D.center.y - collider2D.size.y / 2,
            collider2D.size.x,
            collider2D.size.y); // TODO: CACHE

        bool containsRect = colliderRect.Contains(realPoint);

        return containsRect;
    }
}

2 个答案:

答案 0 :(得分:1)

万一有人像我一样偶然发现这个问题,这是我在3D世界中通过alpha射线投射精灵的解决方案。

首先,使用逆变换将击中点转换为精灵的局部空间。然后,添加精灵的枢轴点。由于它以像素表示,因此将其除以每单位像素可得到正确的偏移量。 要获得该局部点的UV值,请将其除以Sprite边界大小。这将为您提供0到1之间的值。由于我们的坐标系是Y向上,纹理是Y向下,因此我们必须将Y值反转。 现在很容易读取正确的像素。将UV乘以纹理的宽度和高度。

    private GameObject Raycast(Vector2 screenPos)
    {
        Ray ray = new Ray(_camera.ScreenToWorldPoint(screenPos), _camera.transform.forward);

        var result = Physics.RaycastAll(ray, float.MaxValue).ToList().OrderByDescending(h => h.distance); //inverse raycast

        foreach (var hit in result)
        {
            var rend = hit.transform.GetComponent<SpriteRenderer>();
            if (rend == null)
                continue;

            Vector2 localPos = hit.transform.InverseTransformPoint(hit.point);
            localPos += rend.sprite.pivot / rend.sprite.pixelsPerUnit;

            Vector2 uv = localPos / rend.sprite.bounds.size;
            uv.y = 1f - uv.y;

            Texture2D tex = rend.sprite.texture as Texture2D;

            int x = (int)(uv.x * tex.width);
            int y = (int)(uv.y * tex.height);
            var pix = tex.GetPixel(x, y);

            if (pix.a > 0)
            {
                return hit.transform.gameObject;
            }
        }

        return null;
    }

答案 1 :(得分:-1)

您使用的是ScrollRect组件吗?如果没有,你会遇到很多问题,ScrollRect来自新的UI,你不需要编码输入触摸,它会自动为你提供完美的输入识别。

您也可以将滑块添加到ScrollRect。我建议您观看此视频。

将滑块组件添加到ScrollRect以及您可以自定义“不需要担心RayCast忽略”的滑块