Unity3d 用NGUI制作做新手引导的思路

一、先看下效果

 

Prefab结构

 

二、实现思路:

1、prefab上的Panel层级设置成较高

2、背景由5个UISprite拼接起来的,4个(L,R,U,D)当作遮罩,1个镂空(Hollow)当作点击触发(全部都有BoxCollider,并且都生效,有人会问这不就把后面的按钮也给拦截住了,后面会说为什么要这样)

3、4个遮罩的大小由Holow大小决定

4、Hollow绑定一个点击事件ClickCenter  (后面代码里有)

 

三、关键部分:

这里解释为什么上面要把Hollow也带上BoxCollider,目的是修正点击位置,只要是点Hollow上,就让NGUI只相应点击在Hollow中心点后面的第一个UIWidget,这样就可以避免因为点不准,拖拽的其他问题

如图,只要我点在篮筐里,就只响应红点下面的第一个控件

 

四、代码

其实就是NGUI的点击响应代码,位置传入的是Hollow的位置

using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;


public class NewbieGuide : MonoBehaviour
{

    public Transform Hollow;



    bool IsVisible(Vector3 worldPoint, GameObject go)
    {
        UIPanel panel = NGUITools.FindInParents<UIPanel>(go);

        while (panel != null)
        {
            if (!panel.IsVisible(worldPoint)) return false;
            panel = panel.parentPanel;
        }
        return true;
    }

    struct DepthEntry
    {
        public int depth;
        public RaycastHit hit;
        public Vector3 point;
        public GameObject go;
    }

#if UNITY_FLASH
    static bool IsVisible (DepthEntry de)
#else
    static bool IsVisible(ref DepthEntry de)
#endif
    {
        UIPanel panel = NGUITools.FindInParents<UIPanel>(de.go);

        while (panel != null)
        {
            if (!panel.IsVisible(de.point)) return false;
            panel = panel.parentPanel;
        }
        return true;
    }

    void Notify(GameObject go, string funcName, object obj)
    {
        if (NGUITools.GetActive(go))
        {
            go.SendMessage(funcName, obj, SendMessageOptions.DontRequireReceiver);
        }
    }

    public void ClickCenter()
    {
        DepthEntry mHit = new DepthEntry();
        BetterList<DepthEntry> mHits = new BetterList<DepthEntry>();

        UICamera cam = UICamera.current;

        UIEventTrigger.current = null;

        // Convert to view space
        var currentCamera = cam.cachedCamera;

        // Cast a ray into the screen
        var p = Hollow.transform.position;
        p.z = currentCamera.nearClipPlane;
        Ray ray = new Ray(p, Vector3.forward);

        // Raycast into the screen
        int mask = currentCamera.cullingMask & (int)cam.eventReceiverMask;
        float dist = (cam.rangeDistance > 0f) ? cam.rangeDistance : currentCamera.farClipPlane - currentCamera.nearClipPlane;

        RaycastHit[] hits = Physics.RaycastAll(ray, dist, mask);

        if (hits.Length > 1)
        {
            for (int b = 0; b < hits.Length; ++b)
            {
                GameObject go = hits[b].collider.gameObject;

                if (go == Hollow.gameObject)
                    continue;

                UIWidget w = go.GetComponent<UIWidget>();

                if (w != null)
                {
                    if (!w.isVisible) continue;
                    if (w.hitCheck != null && !w.hitCheck(hits[b].point)) continue;
                }
                else
                {
                    UIRect rect = NGUITools.FindInParents<UIRect>(go);
                    if (rect != null && rect.finalAlpha < 0.001f) continue;
                }

                mHit.depth = NGUITools.CalculateRaycastDepth(go);

                if (mHit.depth != int.MaxValue)
                {
                    mHit.hit = hits[b];
                    mHit.point = hits[b].point;
                    mHit.go = hits[b].collider.gameObject;
                    mHits.Add(mHit);
                }
            }

            mHits.Sort(delegate(DepthEntry r1, DepthEntry r2) { return r2.depth.CompareTo(r1.depth); });

            for (int b = 0; b < mHits.size; ++b)
            {
#if UNITY_FLASH
                        if (IsVisible(mHits.buffer[b]))
#else
                if (IsVisible(ref mHits.buffer[b]))
#endif
                {
                    Notify(mHits.buffer[b].go, "OnClick", null);
                    return;
                }
            }
            mHits.Clear();
        }
        else if (hits.Length == 1)
        {
            GameObject go = hits[0].collider.gameObject;

            if (go == Hollow.gameObject)
                return;

            UIWidget w = go.GetComponent<UIWidget>();

            if (w != null)
            {
                if (!w.isVisible) return;
                if (w.hitCheck != null && !w.hitCheck(hits[0].point)) return;
            }
            else
            {
                UIRect rect = NGUITools.FindInParents<UIRect>(go);
                if (rect != null && rect.finalAlpha < 0.001f) return;
            }

            if (IsVisible(hits[0].point, hits[0].collider.gameObject))
            {
                Notify(hits[0].collider.gameObject, "OnClick", null);
                return;
            }
        }

    }

}

 

posted @ 2016-04-18 17:15  MrBlue  阅读(2786)  评论(0编辑  收藏  举报