2017-12-02 108 views
1

我正在在Unity一個簡單的項目,其中有連接到SpringJoint2d component球上成角度的斜率,像下面的圖像中的球限制2D對象的運動向後:enter image description here僅在UNITY

我只是希望用戶能夠沿着斜坡的邊緣向後拖動球,換句話說,我不希望用戶能夠將球從斜坡上移開。

心中已經在嘗試幾種方法我認爲可以做的工作她與我試圖拖動的腳本: (這是更新版本)

public class ball : MonoBehaviour 
{ 
    public Rigidbody2D rb; 
    public Transform spring; 

    public Transform calcpoint; 
    private Vector3 start; 
    private Vector3 end; 
    private bool isPressed = false; 
    RaycastHit2D[] hits = new RaycastHit2D[2]; 
    RaycastHit2D[] hits2 = new RaycastHit2D[2]; 
    float factor = 0; 
    private void OnMouseDown() 
    { 
     if (!isPressed) 
     { 
      isPressed = true; 
      rb.isKinematic = true; 
     } 

    } 
    private void OnMouseUp() 
    { 

     isPressed = false; 
     rb.isKinematic = false; 
     StartCoroutine(release()); 
    } 
    /// <summary> 
    /// release the ball from the spring joint after a small amount of time 
    /// </summary> 
    /// <returns></returns> 
    IEnumerator release() 
    { 
     yield return new WaitForSeconds(0.1f); 
     rb.GetComponent<SpringJoint2D>().enabled = false; 

    } 
    // Update is called once per frame 
    void Update() 
    { 

     if (isPressed) 
     { 
      if (Vector3.Distance(spring.position, rb.position) > 3f || spring.position.x < (rb.position.x - 1)) return;//restrict the dragging of the ball to not go beyond the spring point and not too far back 
      float angle = 0; 
      if (checkGround() > 1)//if we hit the slope with the ray cast downward from the mouse/Tap position 
      { 

       angle = Mathf.Abs(Mathf.Atan2(hits[1].normal.x, hits[1].normal.y) * Mathf.Rad2Deg); //get angle 
       factor = (float)(((45 - angle) * 0.02) + 1) * (angle/45);//an inaccurate formula to offset the ball to be on top of the slope that works just fine with some glitches 
       rb.position = hits[1].point + new Vector2(0, factor * 1f);//position the ball at the point were the ray cast downward from the mouse hit 
                     //(that puts the ball center on the line of the slope) so I offset it usinf the formula above 

      } 
     } 
    } 
    private int checkGround() 
    { 
     int h = Physics2D.RaycastNonAlloc(Camera.main.ScreenToWorldPoint(Input.mousePosition), -Vector2.up, hits); //cast downwards 
     return h; 
    } 

} 

這裏有球的設置:

enter image description here

和傾斜設置:

enter image description here

球的拖動工作正常,有一點玩家可以將它拖到空中或進入斜坡,我設法用新代碼修復它,所以現在玩家只能將它拖到邊緣上,儘管我的計算仍然有點缺陷,當斜坡角度發生變化時,球會在斜坡內部傾斜一點,並在釋放時導致一些問題。

用來解決問題的方法很簡單,當玩家開始拖動球時,我會向下投射一個光線,並在與斜坡碰撞的點上擊球,抵消它以坐在頂部它的問題是,抵消部分不夠準確。

我希望我解釋自己好一點這一次謝謝:)

+0

你能發佈與安裝於滾珠和斜率分量的圖像?當你將球向不同的方向拉時,現在發生了什麼?它是否完全移動,也許它會通過斜坡本身? – Hristo

+0

用更多信息和我目前的進度更新了這個問題。 –

+1

您是否嘗試過設置** Rigidbody插值模式**進行外插?此外,如果問題只發生在球快速移動時,您應該將**碰撞檢測模式**更改爲**連續動態模式** – Hristo

回答

0

經過大量的試驗和錯誤我還是設法拿出一個完美的解決了問題,所以我想我也可以分享答案也許它會幫助別人。

這裏更新的代碼我改變了我的完全限制了運動的方法,現在我用簡單的直線方程如下圖所示:

private void OnMouseDown() 
{ 
    if (!isPressed) 
    { 
     //cast a ray on the slope 
     if (checkGround() > 1) 
     { 
      angle = Mathf.Abs(Mathf.Atan2(hits[1].normal.x, hits[1].normal.y) * Mathf.Rad2Deg); //get angle 
      slope = Mathf.Tan(angle * Mathf.Deg2Rad);//get the slope steepiness 
     } 
     isPressed = true; 
     rb.isKinematic = true; 
    } 

} 
private void OnMouseUp() 
{ 

     isPressed = false; 
    rb.isKinematic = false; 

    StartCoroutine(release()); 
} 
void Update() { 

    if (isPressed) 
    { 
     xMove = Camera.main.ScreenToWorldPoint(Input.mousePosition).x - spring.position.x;//get how much the mouse moved backward or forward 
     if (xMove < -3f) xMove = -3f; //restrict the drag range to 3 backward 
     if (xMove > 0.3f) xMove = 0.3f;//restrict the drag range to 0.3 forward 
     xpos = spring.position.x+xMove;//since the ball and the spring start at exactly the same position the new ball's x position would be the spring x + the x movement we calculated above 
     ypos = (xMove * slope)- spring.position.y; //the y posistion would be y=mx+b so the the x movement * the slop steepiness - the starting y position 
     rb.position = new Vector2(xpos, -ypos);//set the new position of the ball 

    } 
} 
private int checkGround() 
{ 
    int h = Physics2D.RaycastNonAlloc(Camera.main.ScreenToWorldPoint(Input.mousePosition), -Vector2.up, hits); //cast downwards 
    return h; 
}