Search Unity

the fastest way to get Capsule's point 0 & 1, per frame.

Discussion in 'Physics' started by canis, Nov 4, 2019.

  1. canis

    canis

    Joined:
    Oct 25, 2013
    Posts:
    79
    I was wonder is there the way to get capsule's apex points without calculate each frame.
    since I need to platform `Physics.CapsuleCast` every fixedUpdate.

    here is the code I'm using to achieve the calculate.
    the major method was `UpdateReference()` within the following class.


    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. namespace Kit.Physic
    4. {
    5.     public enum eCapsuleDirection
    6.     {
    7.         XAxis = 0,
    8.         YAxis = 1,
    9.         ZAxis = 2,
    10.     }
    11.  
    12.     /// <summary>A middle class to represent the Capsule in pure data format.
    13.     /// respect Unity's Capsule Collider behaviour.</summary>
    14.     public struct CapsuleData
    15.     {
    16.         public static readonly CapsuleData Zero = default(CapsuleData);
    17.         public Vector3 center { get { return m_Center; } set { m_Center = value; m_Dirty = true; } }
    18.         public float radius { get { return m_Radius; } set { m_Radius = value; m_Dirty = true; } }
    19.         public float height { get { return m_Height; } set { m_Height = value; m_Dirty = true; } }
    20.         public int direction { get { return m_Direction; } set { m_Direction = value; m_Dirty = true; } }
    21.         private Vector3 m_Center;
    22.         private float m_Radius;
    23.         private float m_Height;
    24.         private int m_Direction;
    25.         private bool m_Dirty;
    26.  
    27.         public Vector3 position { get { return m_Matrix.GetColumn(3); } set { m_Matrix.SetTRS(value, rotation, Vector3.one); m_Dirty = true; } }
    28.         public Quaternion rotation
    29.         {
    30.             get
    31.             {
    32.                 Vector4
    33.                 lhs = m_Matrix.GetColumn(2),
    34.                 rhs = m_Matrix.GetColumn(1);
    35.                 if (lhs == Vector4.zero && rhs == Vector4.zero)
    36.                     return Quaternion.identity;
    37.                 else
    38.                     return Quaternion.LookRotation(lhs, rhs);
    39.             }
    40.             set { m_Matrix.SetTRS(position, value, Vector3.one); m_Dirty = true; }
    41.         }
    42.         private Matrix4x4 m_Matrix;
    43.  
    44.         public CapsuleData(CapsuleCollider colliderRef)
    45.             : this(colliderRef.transform, colliderRef.center, colliderRef.radius, colliderRef.height, (eCapsuleDirection)colliderRef.direction)
    46.         {
    47.             if (colliderRef == null)
    48.                 throw new System.NullReferenceException();
    49.         }
    50.  
    51.         public CapsuleData(Transform _transform, Vector3 center, float radius, float height, eCapsuleDirection direction = eCapsuleDirection.YAxis)
    52.             : this(_transform.position, _transform.rotation, center, radius, height, direction)
    53.         {
    54.             if (_transform == null)
    55.                 throw new System.NullReferenceException();
    56.         }
    57.  
    58.         public CapsuleData(Vector3 _pos, Quaternion _rot, Vector3 center,
    59.             float radius, float height, eCapsuleDirection direction = eCapsuleDirection.YAxis)
    60.         {
    61.             m_Center = center;
    62.             m_Radius = radius;
    63.             m_Height = height;
    64.             m_Direction = (int)direction; // 0,1,2
    65.             m_Dirty = true;
    66.  
    67.             m_Matrix = Matrix4x4.TRS(_pos, _rot, Vector3.one);
    68.             m_P0 = m_P1 = Vector3.zero;
    69.         }
    70.  
    71.         private Vector3 m_P0, m_P1;
    72.         public Vector3 p0
    73.         {
    74.             get
    75.             {
    76.                 if (m_Dirty)
    77.                     UpdateReference();
    78.                 return m_P0;
    79.             }
    80.         }
    81.         public Vector3 p1
    82.         {
    83.             get
    84.             {
    85.                 if (m_Dirty)
    86.                     UpdateReference();
    87.                 return m_P1;
    88.             }
    89.         }
    90.  
    91.         private void UpdateReference()
    92.         {
    93.             if (m_Dirty)
    94.             {
    95.                 // invalid setting :
    96.                 // matching Unity's Capsule Collider behaviour,
    97.                 if (height < radius * 2f)
    98.                 {
    99.                     m_P0 = m_P1 = m_Matrix.MultiplyPoint3x4(center);
    100.                 }
    101.                 else
    102.                 {
    103.                     float half = Mathf.Clamp((height / 2f) - radius, 0f, float.PositiveInfinity);
    104.                     switch (direction)
    105.                     {
    106.                         case 0: // X-axis
    107.                             m_P0 = center + new Vector3(-half, 0f, 0f);
    108.                             m_P1 = center + new Vector3(half, 0f, 0f);
    109.                             break;
    110.                         case 1: // Y-axis
    111.                             m_P0 = center + new Vector3(0f, half, 0f);
    112.                             m_P1 = center + new Vector3(0f, -half, 0f);
    113.                             break;
    114.                         case 2: // Z-axis
    115.                             m_P0 = center + new Vector3(0f, 0f, half);
    116.                             m_P1 = center + new Vector3(0f, 0f, -half);
    117.                             break;
    118.                         default:
    119.                             throw new System.NotImplementedException();
    120.                     }
    121.                     m_P0 = m_Matrix.MultiplyPoint3x4(m_P0);
    122.                     m_P1 = m_Matrix.MultiplyPoint3x4(m_P1);
    123.                 }
    124.             }
    125.             m_Dirty = false;
    126.         }
    127.  
    128.         public static explicit operator CapsuleData (CapsuleCollider collider)
    129.         {
    130.             return new CapsuleData(collider);
    131.         }
    132.     }
    133. }