您的位置:首页 > 移动开发 > Unity3D

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

2016-04-18 17:15 741 查看
一、先看下效果



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;
}
}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: