2017-12-02 160 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; 
}