一:射線
Ray射線
定義:射線是一條從原點出發,沿某一方向運動的無限直線。
//創建一條初始位置爲startPos,方向爲dir的一條射線
Ray ray = new Ray (startPos, dir);
//創建一條從攝像機通過屏幕點的光線。
//得到的光線在世界空間中,從相機的近平面開始,經過屏幕上的(x,y)像素座標(位置)。z是忽略。
Ray camerRay = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit : 用於存儲發射射線後產生的碰撞信息。
常用的成員變量如下:
- collider 與射線發生碰撞的碰撞器
- distance 從射線起點到射線與碰撞器的交點的距離
- normal 射線射入平面的法向量
- point 世界空間中射線與碰撞體的交點的座標(Vector3對象)
具體的可以參考官方文檔
二:線性投射
1.Raycast :
從起點開始,向最大距離的方向發射一條射線,進行碰撞檢測,但是僅能檢測到第一個被射線碰撞的物體。
可以選擇提供一個 LayerMask 來過濾掉不需要的碰撞,結合RaycastHit可以獲取到碰撞信息。
定義:
public static bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance, int layerMask);
有多個重載方法,具體參考官方文檔
示例代碼:
Ray ray = new Ray (startPos, dir);
RaycastHit hit;
Physics.Raycast(ray,out hit,distance);
//或者
Physics.Raycast(startPos,dir,out hit,distance);
Physics.Raycast(ray,out hit,distance,LayerMask.GetMask("ball"));
如圖:
ps: 對於射線的調試可以用 Debug.DrawRay() 或者 Gizmos 來繪製射線,方便調試。
如:Debug.DrawRay(startPos,dir,Color.red);
2.RaycastAll :
用法和Raycast差不多,區別在於可檢測射線路徑上的所有物體,返回一個RaycastHit[ ]。
示例代碼:
//檢測所有
RaycastHit[] hits = Physics.RaycastAll(ray,distance);
RaycastHit[] hits = Physics.RaycastAll(ray,distance,LayerMask.GetMask("ball"));
3.Linecast:
如果有任何碰撞器與start和end之間的直線相交,返回true,否則false
示例代碼:
//兩點檢測: 如果有任何碰撞器與start和end之間的直線相交,返回true,否則false
bool isCrash = Physics.Linecast(startPos,endPos);
bool isCrash = Physics.Linecast(startPos,endPos,LayerMask.GetMask("ball"));
三:體型投射
1.BoxCast 立方體投射:
將方框沿射線投射,進行立方體範圍碰撞檢測,返回一個bool值。
和Raycast 一樣只能檢測第一個。(ps : BoxCastAll 檢測所有, 用法和BoxCast類似)
定義:以center爲中心創建一個大小爲halfExtents的立方體線框,向direction方向發射,最大距離爲maxDistance,根據layerMask過濾碰撞體,並且通過queryTriggerInteraction指定此查詢是否應觸發觸發器,hitInfo接收碰撞信息
//以center爲中心創建一個半徑大小爲halfExtents的立方體線框,向direction方向發射,最大距離爲maxDistance,根據layerMask過濾碰撞體,並且通過queryTriggerInteraction指定此查詢是否應觸發觸發器,hitInfo接收碰撞信息
public static bool BoxCast(Vector3 center, Vector3 halfExtents, Vector3 direction, out RaycastHit hitInfo, [Internal.DefaultValue("Quaternion.identity")] Quaternion orientation, [Internal.DefaultValue("Mathf.Infinity")] float maxDistance, [Internal.DefaultValue("DefaultRaycastLayers")] int layerMask, [Internal.DefaultValue("QueryTriggerInteraction.UseGlobal")] QueryTriggerInteraction queryTriggerInteraction);
示例代碼:
Ray ray = new Ray (startPos, dir);
RaycastHit hit;
bool isCrash = Physics.BoxCast(startPos,transform.localScale/2,dir,out hit);
bool isCrash = Physics.BoxCast(startPos,transform.localScale/2,dir,out hit,transform.rotation,distance,LayerMask.GetMask("ball"));
如圖:
2.SphereCast 球體投射:
和立方體投射類似,範圍爲球體,返回一個bool值,單一檢查。(SphereCastAll:檢測所有,返回RaycastHit[])
定義:以origin爲中心創建一個半徑爲radius的球體線框,向direction方向發射,最大距離爲maxDistance,根據layerMask過濾碰撞體,並且通過queryTriggerInteraction指定此查詢是否應觸發觸發器。
public static bool SphereCast(Vector3 origin, float radius, Vector3 direction, out RaycastHit hitInfo, [Internal.DefaultValue("Mathf.Infinity")] float maxDistance, [Internal.DefaultValue("DefaultRaycastLayers")] int layerMask, [Internal.DefaultValue("QueryTriggerInteraction.UseGlobal")] QueryTriggerInteraction queryTriggerInteraction);
示例代碼:
Ray ray = new Ray (startPos, dir);
RaycastHit hit;
bool isHit = Physics.SphereCast (startPos, transform.localScale.x/2, dir, out hit, m_MaxDistance);
演示:
3.CapsuleCast 膠囊體投射:
和上面兩種類似,檢測範圍爲膠囊體,返回一個bool值,單一檢查。(CapsuleCastAll:檢測所有,返回RaycastHit[])
定義:point1膠囊體頂端的球體中心,point2膠囊體末端的球體中心,半徑爲radius,向direction方向發射,最大距離爲maxDistance,根據layerMask過濾碰撞體,並且通過queryTriggerInteraction指定此查詢是否應觸發觸發器。
public static bool CapsuleCast(Vector3 point1, Vector3 point2, float radius, Vector3 direction, out RaycastHit hitInfo, [Internal.DefaultValue("Mathf.Infinity")] float maxDistance, [Internal.DefaultValue("DefaultRaycastLayers")] int layerMask, [Internal.DefaultValue("QueryTriggerInteraction.UseGlobal")] QueryTriggerInteraction queryTriggerInteraction);
示例代碼:
RaycastHit hit;
bool isHit = Physics.CapsuleCast(point1, point2,radius, direction, out hit, maxDistance, layerMask, queryTriggerInteraction);
四:相交檢測
注意:"相交檢測” 每個方法都有對應的 “無內存分配” 方法,每次調用該方法時都是讀取緩存,不會重新分配內存,也就是說不會產生過多的內存垃圾。實際應用中也儘量採用“無內存分配”方法,可以提高一定性能。
比如:
OverlapBox 對應的 “無內存分配” 方法:OverlapBoxNonAlloc
OverlapSphere 對應的 “無內存分配” 方法:OverlapSphereNonAlloc
OverlapCapsule 對應的 “無內存分配” 方法:OverlapCapsuleNonAlloc
這些用法區別不大,詳情可以查看官網
1.OverlapBox 相交立方體:
用於檢測與立方體碰撞的所有collider信息。
**定義:以center爲中心創建一個半徑爲halfExtents的正立方體,通過layerMask過濾不需要的collider。返回一個collider集合 Collider[] **
public static Collider[] OverlapBox(Vector3 center, Vector3 halfExtents, Quaternion orientation, int layerMask);
演示:
2.OverlapSphere 相交球:
用於檢測與球體碰撞的所有collider信息。
**定義:以center爲中心創建一個半徑爲radius的球體,通過layerMask過濾不需要的collider。返回一個collider集合 Collider[] **
public static Collider[] OverlapSphere(Vector3 position, float radius, [Internal.DefaultValue("AllLayers")] int layerMask, [Internal.DefaultValue("QueryTriggerInteraction.UseGlobal")] QueryTriggerInteraction queryTriggerInteraction);
3.OverlapCapsule 相交膠囊體:
用於檢測與膠囊體碰撞的所有collider信息。
和以上類似
定義:
public static int OverlapCapsuleNonAlloc(Vector3 point0, Vector3 point1, float radius, Collider[] results, [Internal.DefaultValue("AllLayers")] int layerMask, [Internal.DefaultValue("QueryTriggerInteraction.UseGlobal")] QueryTriggerInteraction queryTriggerInteraction);
五:校驗檢測
和相交檢測類似,區別在於該類型方法 校驗是否發生了碰撞 ,返回的是bool值,而不是碰撞體信息集合,相對於性能較好。(ps:也會校驗自身的collider)
1.CheckBox 校驗立方體:
校驗該立方體是否與其他collider重疊。返回bool值
定義:
public static bool CheckBox(Vector3 center, Vector3 halfExtents, Quaternion orientation = Quaternion.identity, int layermask = DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal);
2.CheckSphere 校驗球:
校驗該球是否與其他collider重疊。返回bool值
定義:
public static bool CheckSphere(Vector3 position, float radius, int layerMask = DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal);
3.CheckCapsule 校驗膠囊體:
校驗該立方體是否與其他collider重疊。返回bool值
定義:
public static bool CheckCapsule(Vector3 start, Vector3 end, float radius, int layerMask = DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal);
IgnoreCollision 忽略碰撞:
使碰撞檢測系統忽略collider1和collider2之間的所有碰撞。
這對於防止投射物與發射它們的物體發生碰撞是很有用的。
public static void IgnoreCollision(Collider collider1, Collider collider2, bool ignore = true);
六:調試技巧:
一般有兩種方法:
1.Debug.DrawRay:繪製一條射線。
示例:
//start:起點,dir:射線的方向和長度, red:顏色
Debug.DrawRay(start,dir,Color.red);
2. Gizmos:用於在場景視圖中提供可視化調試或設置幫助。(以上的演示動態圖就是通過該方法繪製的)
示例:
void OnDrawGizmos () {
//設置顏色
Gizmos.color = Color.red;
//繪製射線
Gizmos.DrawRay (transform.position, transform.forward * distance);
//繪製立方體線框
Gizmos.DrawWireCube (transform.position + transform.forward * distance, transform.localScale);
}
最後
引用網友HONT的性能測試總結:
射線和線段的開銷非常小,可以忽略。
性能消耗順序:
從投射物來看: Box < Sphere < Capsule
從投射方法來看: CheckXXX < OverlapXXX < XXXCast