如何在Unity3D中按轨迹移动立方体

时间:2019-05-14 18:27:08

标签: c# unity3d game-physics

当拖动鼠标以在鼠标的某个位置及其拖动能力移动时,我需要使用点或箭头型符号以轨迹运动方式移动立方体。

我使用了2D项目中使用的代码以轨迹运动方式移动了一个球,但是没有用。

这是我尝试的代码

void Start()
{
    cam = Camera.main;
    cubeClick = GameObject.Find("Cube Click Area");
    trajectoryDots = GameObject.Find("Trajectory Dots");
    rb = Player.GetComponent<Rigidbody>();
    trajectoryDots.transform.localScale = new Vector3(
        initialDotSize, 
        initialDotSize, 
        trajectoryDots.transform.localScale.z);
    for (int dotNumber = 0; dotNumber < 40; dotNumber++)
    {
        Dots[dotNumber] = GameObject.Find("Dot (" + dotNumber + ")");
        if (DotSprite !=null)
        {
            Dots[dotNumber].GetComponent<SpriteRenderer>().sprite = DotSprite;
        }
    }
    for (int dotNumber = NumberOfDots; dotNumber < 40; dotNumber++)
    {
        GameObject.Find("Dot (" + dotNumber + ")").SetActive(false);
    }
    trajectoryDots.SetActive(false);


}


void Update()
{
    Ray camRay = cam.ScreenPointToRay(Input.mousePosition);
    RaycastHit hit;
    //RaycastHit2D hit = Physics2D.Raycast(cam.(Input.mousePosition), Vector2.zero);
    if (Physics.Raycast(camRay, out hit, 100f) && !cubeisClicked2)
    {
        if (hit.collider.gameObject.name == Player.name)
        {
            cubeisClicked = true;
        }
        else
        {
            cubeisClicked = false;
        }
    }
    else
    {
        cubeisClicked = false;
    }

    if (cubeisClicked2)
    {
        cubeisClicked = true;
    }

    if ((rb.velocity.x * rb.velocity.x) + (rb.velocity.y * rb.velocity.y) <= 0.0085f)
    {
        rb.velocity = new Vector2(0f, 0f);
    }
    else
    {
        trajectoryDots.SetActive(false);
    }
    cubePosition = Player.transform.position;
    if ((Input.GetKey(KeyCode.Mouse0) && cubeisClicked) && ((rb.velocity.x == 0f && rb.velocity.y == 0f)))
    {
        cubeisClicked2 = true;
        fingerPosition = cam.ScreenToWorldPoint(Input.mousePosition);
        fingerPosition.z = 0f;
        cubeFingerDiff = cubePosition - fingerPosition;
        ShotForce = new Vector2(cubeFingerDiff.x * shootingPowerX , cubeFingerDiff.y * shootingPowerY);
        if (Mathf.Sqrt((cubeFingerDiff.x * cubeFingerDiff.x) + (cubeFingerDiff.y * cubeFingerDiff.y) )>0.4f)
        {
            trajectoryDots.SetActive(true);

        }
        else
        {
            trajectoryDots.SetActive(false);
        }

        for (int dotNumber = 0; dotNumber < NumberOfDots; dotNumber++)
        {
            x1 = cubePosition.x * ShotForce.x * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift);
            y1 = cubePosition.y * ShotForce.y * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift) - (-Physics.gravity.y / 2f * Time.fixedDeltaTime * Time.fixedDeltaTime * (DotSeparation * dotNumber + dotShift) * (DotSeparation * dotNumber + dotShift));
            Dots[dotNumber].transform.position = new Vector3(x1, -y1, 0);
        }

        if (Input.GetKeyUp(KeyCode.Mouse0))
        {
            cubeisClicked2 = false;
            trajectoryDots.SetActive(false);

            rb.velocity = new Vector2 (ShotForce.x, ShotForce.y);;

        }


    }



}

它不起作用,它按。所示显示点。

image

它应以用户拖动并指向要移动的位置的方式移动立方体。

1 个答案:

答案 0 :(得分:1)

主要问题是将cam.ScreenToWorldPoint(Input.mousePosition);与透视相机配合使用总是会返回相机的位置(这是一个非常常见的错误),因此您正在使用鼠标而不是立方体进行操作用相机和立方体。

您需要使用另一种方法来使用鼠标的位置,考虑到多维数据集与相机的位置。

获得所需行为的一种方法是创建一个垂直于相机方向贯穿立方体的平面,并查看鼠标光线与平面相交的位置。另外,将cubeisClicked2标志设置为false,仅在我们实际单击飞机时将其设置为true:

cubePosition = Player.transform.position;
if ((Input.GetKey(KeyCode.Mouse0) && cubeisClicked) && ((rb.velocity.x == 0f && rb.velocity.y == 0f)))
{
    cubeisClicked2 = false;

    Plane cubePlane = new Plane(cam.transform.position - cubePosition, cubePosition);

    // reusing camRay

    // Determine if we are even hitting the plane
    float enter = 0.0f;

    if (cubePlane.Raycast(camRay, out enter))
    {
        cubeisClicked2 = true;
        fingerPosition  = camRay.GetPoint(enter);

此外,您需要在力和轨迹计算中包括z分量。您可能只是将ShootingPowerX用作z组件的功能。我在评论中提到的轨迹计算也需要进行更改:

        cubeFingerDiff = cubePosition - fingerPosition;
        ShotForce = new Vector3(cubeFingerDiff.x * shootingPowerX , cubeFingerDiff.y * shootingPowerY, cubeFingerDiff.z * shootingPowerX );
        if (cubeFingerDiff.magnitude>0.4f)
        {
            trajectoryDots.SetActive(true);

        }
        else
        {
            trajectoryDots.SetActive(false);
        }

        for (int dotNumber = 0; dotNumber < NumberOfDots; dotNumber++)
        {
            x1 = cubePosition.x + ShotForce.x * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift);
            y1 = cubePosition.y + ShotForce.y * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift) + (Physics.gravity.y / 2f * Time.fixedDeltaTime * Time.fixedDeltaTime * (DotSeparation * dotNumber + dotShift) * (DotSeparation * dotNumber + dotShift));
            z1 = cubePosition.z + ShotForce.z * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift);
            Dots[dotNumber].transform.position = new Vector3(x1, y1, z1);

然后,与其在确定轨迹的同一GetKeyUp(KeyCode.Mouse0)中检查if,不如在确定轨迹的同时检查它是否存在:

        }
    } 
}

if (Input.GetKeyUp(KeyCode.Mouse0) && cubeisClicked2)
{
    cubeisClicked2 = false;
    trajectoryDots.SetActive(false);

    rb.velocity = new Vector3 (ShotForce.x, ShotForce.y, ShotForce.z);;

}

总共看起来可能像这样:

cubePosition = Player.transform.position;
if ((Input.GetKey(KeyCode.Mouse0) && cubeisClicked) && ((rb.velocity.x == 0f && rb.velocity.y == 0f)))
{
    cubeisClicked2 = false;
    Plane cubePlane = new Plane(cam.transform.position - cubePosition, cubePosition);

    // reusing camRay

    // Determine if we are even hitting the plane
    float enter = 0.0f;
    if (cubePlane.Raycast(camRay, out enter))
    {
        cubeisClicked2 = true;
        fingerPosition  = camRay.GetPoint(enter);

        cubeFingerDiff = cubePosition - fingerPosition;
        ShotForce = new Vector3(cubeFingerDiff.x * shootingPowerX , cubeFingerDiff.y * shootingPowerY, cubeFingerDiff.z * shootingPowerX );
        if (cubeFingerDiff.magnitude>0.4f)
        {
            trajectoryDots.SetActive(true);

        }
        else
        {
            trajectoryDots.SetActive(false);
        }

        for (int dotNumber = 0; dotNumber < NumberOfDots; dotNumber++)
        {
            x1 = cubePosition.x + ShotForce.x * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift);
            y1 = cubePosition.y + ShotForce.y * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift) + (Physics.gravity.y / 2f * Time.fixedDeltaTime * Time.fixedDeltaTime * (DotSeparation * dotNumber + dotShift) * (DotSeparation * dotNumber + dotShift));
            z1 = cubePosition.z + ShotForce.z * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift);
            Dots[dotNumber].transform.position = new Vector3(x1, y1, z1);
        }
    }         
}

if (Input.GetKeyUp(KeyCode.Mouse0) && cubeisClicked2)
{
    cubeisClicked2 = false;
    trajectoryDots.SetActive(false);

    rb.velocity = new Vector3 (ShotForce.x, ShotForce.y, ShotForce.z);;

}

因为这会计算出您指向的cubePlane上的镜头的力量,所以当相机距离更远时,您将能够进行更强劲的拍摄。

这可能不是您想要的行为,但是如果摄像机始终与立方体保持相同的距离,那应该不是问题。

如果这不是可接受的限制,则可以按照将ShotForce除以立方体与相机之间的距离,并根据需要增加shootingPowerXshootingPowerY的方式来做一些事情。如果您自己找不到一个好的解决方案,则最好在单独的问题中提出。