白泽图

  • 文章
    • Unity渲染
    • Unity项目开发
    • 工具
    • 数学
    • 算法
    • 网站搭建
    • 网络&操作系统
蒋程个人博客
互联网技术经验总结&分享
  1. 首页
  2. Unity项目开发
  3. 正文

NGUI中的射线检测核心代码

2021-05-26 1569点热度 0人点赞 0条评论
[LuaInterface.NoToLua]static  public bool Raycast (Vector3 inPos)
{
	for (int i = 0; i < list.size; ++i)
	{
		UICamera cam = list.buffer[i];
		
		// Skip inactive scripts
		if (!cam.enabled || !NGUITools.GetActive(cam.gameObject)) continue;

		// Convert to view space
		currentCamera = cam.cachedCamera;
#if !UNITY_4_7 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2
		if (currentCamera.targetDisplay != 0) continue;
#endif
		Vector3 pos = currentCamera.ScreenToViewportPoint(inPos);
		if (float.IsNaN(pos.x) || float.IsNaN(pos.y)) continue;

		// If it's outside the camera's viewport, do nothing
		if (pos.x < 0f || pos.x > 1f || pos.y < 0f || pos.y > 1f) continue;

		// Cast a ray into the screen
		Ray ray = currentCamera.ScreenPointToRay(inPos);

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

		if (cam.eventType == EventType.World_3D)
		{
			lastWorldRay = ray;

#if UNITY_4_7
			if (Physics.Raycast(ray, out lastHit, dist, mask))
#else
			if (Physics.Raycast(ray, out lastHit, dist, mask, QueryTriggerInteraction.Ignore))
#endif
			{
				lastWorldPosition = lastHit.point;
				mRayHitObject = lastHit.collider.gameObject;

				if (!cam.eventsGoToColliders)
				{
					var rb = mRayHitObject.gameObject.GetComponentInParent<Rigidbody>();
					if (rb != null) mRayHitObject = rb.gameObject;
				}
				return true;
			}
			continue;
		}
		else if (cam.eventType == EventType.UI_3D)
		{
#if UNITY_4_7
			RaycastHit[] mRayHits = Physics.RaycastAll(ray, dist, mask);
			var hitCount = mRayHits.Length;
#else
			if (mRayHits == null) mRayHits = new RaycastHit[50];
			var hitCount = Physics.RaycastNonAlloc(ray, mRayHits, dist, mask, QueryTriggerInteraction.Collide);
#endif
			if (hitCount > 1)
			{
				for (int b = 0; b < hitCount; ++b)
				{
					GameObject go = mRayHits[b].collider.gameObject;
#if UNITY_5_5_OR_NEWER
					UnityEngine.Profiling.Profiler.BeginSample("Editor-only GC allocation (GetComponent)");
					UIWidget w = go.GetComponent<UIWidget>();
					UnityEngine.Profiling.Profiler.EndSample();
#else
					Profiler.BeginSample("Editor-only GC allocation (GetComponent)");
					UIWidget w = go.GetComponent<UIWidget>();
					Profiler.EndSample();
#endif

					if (w != null)
					{
						if (!w.isVisible) continue;
						if (w.hitCheck != null && !w.hitCheck(mRayHits[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 = mRayHits[b];
						mHit.point = mRayHits[b].point;
						mHit.go = mRayHits[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
					{
						lastHit = mHits[b].hit;
						mRayHitObject = mHits[b].go;
						lastWorldRay = ray;
						lastWorldPosition = mHits[b].point;
						mHits.Clear();
						return true;
					}
				}
				mHits.Clear();
			}
			else if (hitCount == 1)
			{
				GameObject go = mRayHits[0].collider.gameObject;
#if UNITY_5_5_OR_NEWER
				UnityEngine.Profiling.Profiler.BeginSample("Editor-only GC allocation (GetComponent)");
				UIWidget w = go.GetComponent<UIWidget>();
				UnityEngine.Profiling.Profiler.EndSample();
#else
				Profiler.BeginSample("Editor-only GC allocation (GetComponent)");
				UIWidget w = go.GetComponent<UIWidget>();
				Profiler.EndSample();
#endif

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

				if (IsVisible(mRayHits[0].point, mRayHits[0].collider.gameObject))
				{
					lastHit = mRayHits[0];
					lastWorldRay = ray;
					lastWorldPosition = mRayHits[0].point;
					mRayHitObject = lastHit.collider.gameObject;
					return true;
				}
			}
			continue;
		}
		else if (cam.eventType == EventType.World_2D)
		{
			if (m2DPlane.Raycast(ray, out dist))
			{
				var point = ray.GetPoint(dist);
				var c2d = Physics2D.OverlapPoint(point, mask);

				if (c2d)
				{
					lastWorldPosition = point;
					mRayHitObject = c2d.gameObject;

					if (!cam.eventsGoToColliders)
					{
						Rigidbody2D rb = FindRootRigidbody2D(mRayHitObject.transform);
						if (rb != null) mRayHitObject = rb.gameObject;
					}
					return true;
				}
			}
			continue;
		}
		else if (cam.eventType == EventType.UI_2D)
		{
			if (m2DPlane.Raycast(ray, out dist))
			{
				lastWorldPosition = ray.GetPoint(dist);
#if UNITY_4_7
				Collider2D[] mOverlap = Physics2D.OverlapPointAll(lastWorldPosition, mask);
				var hitCount = mOverlap.Length;
#else
				if (mOverlap == null) mOverlap = new Collider2D[50];
				var hitCount = Physics2D.OverlapPointNonAlloc(lastWorldPosition, mOverlap, mask);
#endif
				if (hitCount > 1)
				{
					for (int b = 0; b < hitCount; ++b)
					{
						GameObject go = mOverlap[b].gameObject;
#if UNITY_5_5_OR_NEWER
						UnityEngine.Profiling.Profiler.BeginSample("Editor-only GC allocation (GetComponent)");
						UIWidget w = go.GetComponent<UIWidget>();
						UnityEngine.Profiling.Profiler.EndSample();
#else
						Profiler.BeginSample("Editor-only GC allocation (GetComponent)");
						UIWidget w = go.GetComponent<UIWidget>();
						Profiler.EndSample();
#endif

						if (w != null)
						{
							if (!w.isVisible) continue;
							if (w.hitCheck != null && !w.hitCheck(lastWorldPosition)) 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.go = go;
							mHit.point = lastWorldPosition;
							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
						{
							mRayHitObject = mHits[b].go;
							mHits.Clear();
							return true;
						}
					}
					mHits.Clear();
				}
				else if (hitCount == 1)
				{
					var go = mOverlap[0].gameObject;
#if UNITY_5_5_OR_NEWER
					UnityEngine.Profiling.Profiler.BeginSample("Editor-only GC allocation (GetComponent)");
					var w = go.GetComponent<UIWidget>();
					UnityEngine.Profiling.Profiler.EndSample();
#else
					Profiler.BeginSample("Editor-only GC allocation (GetComponent)");
					var w = go.GetComponent<UIWidget>();
					Profiler.EndSample();
#endif

					if (w != null)
					{
						if (!w.isVisible) continue;
						if (w.hitCheck != null && !w.hitCheck(lastWorldPosition)) continue;
					}
					else
					{
						var rect = NGUITools.FindInParents<UIRect>(go);
						if (rect != null && rect.finalAlpha < 0.001f) continue;
					}

					if (IsVisible(lastWorldPosition, go))
					{
						mRayHitObject = go;
						return true;
					}
				}
			}
			continue;
		}
	}
	return false;
}

调用参数 inPos 为屏幕坐标

标签: 暂无
最后更新:2021-05-26

蒋程

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论

COPYRIGHT © 2023 白泽图. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

登录
注册|忘记密码?