CylinderProximityField.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. using UnityEngine;
  2. using UnityEngine.Assertions;
  3. namespace Rokid.UXR.Interaction {
  4. public class CylinderProximityField : MonoBehaviour,
  5. IProximityField, ICurvedPlane
  6. {
  7. [SerializeField]
  8. private Cylinder _cylinder;
  9. [SerializeField]
  10. private float _rotation = 0f;
  11. [SerializeField, Range(0f, 360f)]
  12. private float _arcDegrees = 360;
  13. [SerializeField]
  14. private float _bottom = -1f;
  15. [SerializeField]
  16. private float _top = 1f;
  17. /// <summary>
  18. /// 提供一个ICurvePlane复写本地的属性
  19. /// </summary>
  20. [Tooltip("Providing an ICurvedPlane here will " +
  21. "override all other local properties")]
  22. [SerializeField, Optional, Interface(typeof(ICurvedPlane))]
  23. private MonoBehaviour _curvedPlane;
  24. private ICurvedPlane CurvedPlane;
  25. public Cylinder Cylinder => _cylinder;
  26. public float ArcDegrees
  27. {
  28. get => _arcDegrees;
  29. set => _arcDegrees = value;
  30. }
  31. public float Rotation
  32. {
  33. get => _rotation;
  34. set => _rotation = value;
  35. }
  36. public float Bottom
  37. {
  38. get => _bottom;
  39. set => _bottom = value;
  40. }
  41. public float Top
  42. {
  43. get => _top;
  44. set => _top = value;
  45. }
  46. protected virtual void Awake()
  47. {
  48. CurvedPlane = _curvedPlane != null ?
  49. _curvedPlane as ICurvedPlane :
  50. this;
  51. }
  52. protected virtual void Start()
  53. {
  54. Assert.IsNotNull(CurvedPlane);
  55. Assert.IsNotNull(CurvedPlane.Cylinder);
  56. }
  57. public Vector3 ComputeClosestPoint(Vector3 point)
  58. {
  59. return ComputeClosestPoint(CurvedPlane, point);
  60. }
  61. /// <summary>
  62. /// 最近点的计算
  63. /// </summary>
  64. /// <param name="curvedPlane"></param>
  65. /// <param name="point"></param>
  66. /// <returns></returns>
  67. private static Vector3 ComputeClosestPoint(ICurvedPlane curvedPlane, Vector3 point)
  68. {
  69. RKLog.Debug($"CylinderProximityField ComputeClosestPoint");
  70. Vector3 localPoint = curvedPlane.Cylinder.transform.InverseTransformPoint(point);
  71. if (curvedPlane.Top > curvedPlane.Bottom)
  72. {
  73. localPoint.y = Mathf.Clamp(localPoint.y, curvedPlane.Bottom, curvedPlane.Top);
  74. }
  75. if (curvedPlane.ArcDegrees < 360)
  76. {
  77. float angle = Mathf.Atan2(localPoint.x, localPoint.z) * Mathf.Rad2Deg % 360;
  78. float rotation = curvedPlane.Rotation % 360;
  79. if (angle > rotation + 180)
  80. {
  81. angle -= 360;
  82. }
  83. else if (angle < rotation - 180)
  84. {
  85. angle += 360;
  86. }
  87. angle = Mathf.Clamp(angle, rotation - curvedPlane.ArcDegrees / 2f,
  88. rotation + curvedPlane.ArcDegrees / 2f);
  89. localPoint.x = Mathf.Sin(angle * Mathf.Deg2Rad) * curvedPlane.Cylinder.Radius;
  90. localPoint.z = Mathf.Cos(angle * Mathf.Deg2Rad) * curvedPlane.Cylinder.Radius;
  91. }
  92. else
  93. {
  94. Vector3 nearestPointOnCenterAxis = new Vector3(0f, localPoint.y, 0f);
  95. float distanceFromCenterAxis = Vector3.Distance(localPoint,
  96. nearestPointOnCenterAxis);
  97. localPoint = Vector3.MoveTowards(localPoint,
  98. nearestPointOnCenterAxis,
  99. distanceFromCenterAxis - curvedPlane.Cylinder.Radius);
  100. }
  101. return curvedPlane.Cylinder.transform.TransformPoint(localPoint);
  102. }
  103. }
  104. }