限制仅在UNITY

时间:2017-12-02 17:21:46

标签: unity3d vector

我在Unity制作了一个简单的项目,其中有一个Ball附加到SpringJoint2d component,球位于倾斜的斜坡上,如下图所示:enter image description here

我只是希望用户能够仅沿着斜坡的边缘向后拖动球,换句话说,我不希望用户能够将球从斜坡移开或进入斜坡。 / p>

我一直在尝试几种方式,我认为可以完成这项工作,而我用我所尝试的拖拽脚本: (这是更新版本)

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

球的拖动效果很好,玩家可以将它拖到空中或斜坡上,我设法用新代码修复它,所以现在玩家只能将它拖到边缘,尽管我的计算仍然有点瑕疵,当斜坡角度改变时,球会在斜坡内倾斜一点,这会在释放时产生一些问题。

用于尝试解决问题的方法很简单,当玩家开始拖动球时,我从鼠标向下投射一条射线并将球撞到与斜坡撞击的点上,将其偏移到坐在顶部它,问题在于偏移部分不够准确。

我希望这次我自己解释得更好谢谢:)

1 个答案:

答案 0 :(得分: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;
}