UIPanelBase.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. using System;
  2. using System.Reflection;
  3. using UnityEngine;
  4. using UnityEngine.EventSystems;
  5. using UnityEngine.UI;
  6. namespace Rokid.MRC
  7. {
  8. public class UIPanelBase : MonoBehaviour
  9. {
  10. private RectTransform rectTransform;
  11. public bool FollowCam;
  12. public float CamDistance = 1.3f;
  13. #if UMR
  14. public bool UseForUMR;
  15. #endif
  16. public bool is3DPanel;
  17. void Update()
  18. {
  19. OnUpdate();
  20. }
  21. public virtual void OnInit()
  22. {
  23. rectTransform = GetComponent<RectTransform>();
  24. //GraphicRaycaster设置
  25. #if UMR
  26. //因为Package中没办法获取UXR的类(非Package,并在主工程中),此处暂时用反射的方式添加
  27. if(UseForUMR)
  28. {
  29. BaseRaycaster curRayCaster = GetComponent<GraphicRaycaster>();
  30. Type tp = curRayCaster.GetType();
  31. //Type rkType = Type.GetType("Rokid.UXR.RKGraphicRaycaster");
  32. Assembly assembly = Assembly.GetEntryAssembly();
  33. assembly = Assembly.GetExecutingAssembly();
  34. assembly = Assembly.GetCallingAssembly();
  35. assembly = Assembly.GetAssembly(tp);
  36. assembly = GetAssembly("Rokid.Unity.XR");
  37. Type rkType = assembly.GetType("Rokid.UXR.RKGraphicRaycaster");
  38. if(rkType == null)
  39. {
  40. Debug.LogError("No RKGraphicRaycaster In Project");
  41. }
  42. else
  43. {
  44. if(tp != rkType)
  45. {
  46. Destroy(curRayCaster);
  47. gameObject.AddComponent(rkType);
  48. }
  49. }
  50. }
  51. #endif
  52. //界面类型
  53. Canvas canvas = GetComponent<Canvas>();
  54. if(is3DPanel)
  55. {
  56. canvas.renderMode = RenderMode.WorldSpace;
  57. }
  58. else
  59. {
  60. canvas.renderMode = RenderMode.ScreenSpaceOverlay;
  61. }
  62. }
  63. private Assembly GetAssembly(string name)
  64. {
  65. Assembly[] allAssb = AppDomain.CurrentDomain.GetAssemblies();
  66. for(int i = 0;i < allAssb.Length;i++)
  67. {
  68. if(allAssb[i].FullName.Contains(name))
  69. {
  70. return allAssb[i];
  71. }
  72. }
  73. return null;
  74. }
  75. public virtual void OnOpen()
  76. {
  77. }
  78. public virtual void OnClose()
  79. {
  80. }
  81. public virtual void OnUpdate()
  82. {
  83. if(FollowCam)
  84. {
  85. UpdatePanelPose();
  86. }
  87. }
  88. private void UpdatePanelPose()
  89. {
  90. if(Camera.main == null)
  91. {
  92. return;
  93. }
  94. //相机前方多远距离
  95. Vector3 disPos = Camera.main.transform.forward * CamDistance;
  96. Vector3 temp = Camera.main.transform.position + disPos;
  97. //UI界面朝向相机
  98. transform.rotation = Quaternion.LookRotation(Camera.main.transform.forward);
  99. //获取整个UI界面4个角的位置
  100. Vector3[] corners = new Vector3[4];
  101. rectTransform.GetWorldCorners(corners);
  102. //判断4个点是否在屏幕内
  103. if(!IsVisible(corners))
  104. {
  105. //不在屏幕内,则缓动到屏幕中
  106. TweenPosition.Begin(gameObject, transform.position, temp, 0.3f);
  107. }
  108. else
  109. {
  110. //在屏幕内,则计算UI界面与相机的距离,保持在固定距离
  111. float dist = Vector3.Distance(transform.position, Camera.main.transform.position);
  112. if(dist > CamDistance + 0.2f && dist > CamDistance - 0.2f)
  113. {
  114. transform.position = new Vector3(transform.position.x, transform.position.y, temp.z);
  115. }
  116. }
  117. }
  118. private bool IsVisible(Vector3[] worldPositions)
  119. {
  120. int index = 0;
  121. for(int i = 0;i < worldPositions.Length;i++)
  122. {
  123. if(IsGameObjectInCameraView(worldPositions[i]))
  124. index++;
  125. }
  126. return index >= 3;
  127. }
  128. public static bool IsGameObjectInCameraView(Vector3 pos, Camera camera = null)
  129. {
  130. if(camera == null)
  131. camera = Camera.main;
  132. if(camera == null)
  133. return false;
  134. Vector3 targetObjViewportCoord = camera.WorldToViewportPoint(pos);
  135. if(targetObjViewportCoord.x > 0 && targetObjViewportCoord.x < 1 && targetObjViewportCoord.y > 0f && targetObjViewportCoord.y < 1 && targetObjViewportCoord.z > camera.nearClipPlane && targetObjViewportCoord.z < camera.farClipPlane)
  136. return true;
  137. return false;
  138. }
  139. }
  140. }