Quantcast
Channel: かずきのBlog@hatena
Viewing all articles
Browse latest Browse all 1387

Unity の UIWidgets で背景が透明なところは裏側の 3D の世界にイベントを飛ばしてほしい

$
0
0

デフォルトだと UIWidgets が全てかっさらってしまって、例えば Cube に EventTrigger をしかけて、UIWidgets に全面透明な画面とかを置いてもクリックが反応しないみたいです。 解決策として、以下の Issue にコードが載ってます。

github.com

一応念のためコードだけここにも複製。

using Unity.UIWidgets.engine;
using UnityEngine;
using UnityEngine.UI;

[DisallowMultipleComponent]
[RequireComponent(typeof(UIWidgetsPanel))]
publicclass UIWidgetsRaycastFilter : MonoBehaviour, ICanvasRaycastFilter
{
    publicbool reversed;

    private UIWidgetsPanel rawImage;

    void OnEnable()
    {
        rawImage = GetComponent<UIWidgetsPanel>();
    }


    publicstatic Texture2D toTexture2D(RenderTexture rTex)
    {
        Texture2D tex = new Texture2D(rTex.width, rTex.height, TextureFormat.RGBA32, false);
        RenderTexture.active = rTex;
        tex.ReadPixels(new Rect(0, 0, rTex.width, rTex.height), 0, 0);
        tex.Apply();
        return tex;
    }

    publicbool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
    {
        if (!enabled)
            returntrue;

        Texture2D texture = null;
        var w = rawImage.texture;
        texture = toTexture2D(w as RenderTexture);
        if (texture == null)
            returntrue;

        Vector2 local;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(rawImage.rectTransform, screenPoint, eventCamera, out local);

        Rect rect = rawImage.rectTransform.rect;

        // Convert to have lower left corner as reference point.
        local.x += rawImage.rectTransform.pivot.x * rect.width;
        local.y += rawImage.rectTransform.pivot.y * rect.height;

        Rect uvRect = rawImage.uvRect;
        float u = local.x / rect.width * uvRect.width + uvRect.x;
        float v = local.y / rect.height * uvRect.height + uvRect.y;

        Debug.Log("alpha = " + texture.GetPixelBilinear(u, v).a);

        try
        {
            if (!reversed)
                return texture.GetPixelBilinear(u, v).a != 0;
            elsereturn texture.GetPixelBilinear(u, v).a == 0;
        }
        catch (UnityException e)
        {
            Debug.LogException(e);
        }

        returntrue;
    }
}

このコードを使うと透明な部分は Raycast が裏まで届くようになるらしい。原理は…知らない。 上記のスクリプトを Panel に追加して、以下のような画面を表示します。

class TransparentState : State<ThreeDementionInteractionWidget>
{
    publicoverride Widget build(BuildContext context)
    {
        returnnew Scaffold(
            backgroundColor: Colors.transparent,
            appBar:new AppBar(title: new Text("Transparent page"))
        );
    }
}

そうすると、こんな感じに動きます。

f:id:okazuki:20191219182512g:plain

一応、Android の実機にもデプロイして試してみたら同じように動きました。


Viewing all articles
Browse latest Browse all 1387

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>