1. 程式人生 > >unity複雜地形檢測角色是否在地面上(與地面碰撞)(著地)的方法

unity複雜地形檢測角色是否在地面上(與地面碰撞)(著地)的方法

補充:在膠囊碰撞體裡的物體都會被檢測到,因此當添加了諸如武器之類的碰撞盒時,應該將他們的layer設定為和角色本身一樣的Layer,否則將會導致碰撞數量大於一個,而且即使脫離了地面,OverLarpCapsule返回碰撞陣列也會>=1,導致浮空判斷為真.或者你可以重新寫關於陣列的判斷方法.

這個問題困擾了我幾天,在我找到解決方案之前,嘗試了以下方法

1.射線,在角色座標(一般是腳底),發射一根向下的射線,長度大約為0.2,這樣是的確可以檢測到玩家是否在地面的,但只適用於簡單地形,如果你配置好了下落動畫,那麼用這種方法在斜面上往下走的話就會導致著地狀態檢測為false,如果有動畫的話,就會播放浮空動畫..這是由於角色往前走了一步時,剛體還沒來得及讓玩家因重力而下降足夠的高度,導致射線不能射到斜面.因此判false,加長射線長度可以緩解問題,但又會導致跳躍動畫出現問題,(動畫會提前著地).而且在經過腳下有縫隙的情況而角色膠囊體半徑大於縫隙並不會掉下去的時也會導致著地狀態判false;

2.unity官方角色控制器,簡單的加上控制器並呼叫控制器指令碼查詢是否著地時無法達到想要的效果的,著地狀態返回false,折騰了半天發現控制器只能在呼叫simplemove時(和move等移動函式)判斷isGrounded(是否著地),而且播放一些動畫會導致判斷在true和false狀態來回切換.並且Skinwidth也會導致這種問題.再加上一些角色控制器的限制,邏輯上不是那麼自由.例如需要自己編寫重力,因此我放棄了這個方法.

如果你有能用角色控制器達到正確的效果的方法的話,希望能告訴我,謝謝

最終使用的方法是投射一個膠囊碰撞體來檢測地面

方法來自這個視訊,視訊作者並不是我:視訊連結

原理:投射一個和角色本身膠囊體碰撞器一樣大小的膠囊碰撞器,(也可以不一樣,知道原理後就會知道什麼樣的大小合適了)通過這個膠囊體能比較準確的檢測著地狀態,再不是特別陡的坡和不是特別快的速度下都能比較準確的檢測到.

API:

Physics.OverlapCapsule(pointBottom, pointTop, radius, LayerMask);

以pointBottom為底部半圓圓心,PointTop為頂部半圓圓心,radius為半徑,連線起來構成一個膠囊體


值得注意的是:LayerMask的設定方法,假設ground層為10,那麼這裡如果要只碰撞第10層Layer,那麼Layermask mask=1<<10;這是位運算.按這種格式寫就行了.

然而,投射的膠囊體也會檢測自己本身,而再遊戲中也希望基本上任何能碰撞物體都能夠用來站腳,所以實際上我們要做的應該是碰撞除了使用者本身Layer以外的所有層.假設Player層為8

寫出來的話就是:~(1<<8)

~可以理解為位運算的取反符號

實際的程式碼:

 private CapsuleCollider capsuleCollider;
    private Vector3 pointBottom, pointTop;
    private float radius; 

void Awake () {
       
        capsuleCollider = GetComponent<CapsuleCollider>();
        radius = capsuleCollider.radius;


    }
bool OnGround()
    {

        pointBottom = transform.position + transform.up * radius-transform.up*overLapCapsuleOffset;
        pointTop = transform.position + transform.up * capsuleCollider.height - transform.up * radius;
        LayerMask ignoreMask = ~(1 << 8);

        colliders = Physics.OverlapCapsule(pointBottom, pointTop, radius, ignoreMask);
        Debug.DrawLine(pointBottom, pointTop,Color.green);
        if (colliders.Length!=0)
        {
            isOnGround = true;
            return true;
        }
        else
        {
             isOnGround = false;
            return false;
        }
     
       
    }
另外: 為避免角色在下陡坡時直接浮空,應該增加一個時間變數來計算浮空時間,當達到一定時間後才播放浮空動畫.同時也能避免角色在經過一個小坡後離地面只有幾釐米時直接播放浮空動畫的不合理情況.