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

How to move cube in trajectory in Unity3D

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

我使用了 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);;

        }


    }



}

它不起作用,它显示了中所示的点。

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

主要问题是使用 cam.ScreenToWorldPoint(Input.mousePosition); 透视相机总是 returns 相机的位置(这是一个很常见的错误),所以不是使用鼠标位置而是立方体,你正在使用相机与立方体。

考虑到立方体与相机的比较位置,您需要使用另一种方法来使用鼠标的位置。

获得所需行为的一种方法是通过垂直于相机方向的立方体创建一个平面 运行,然后查看鼠标射线与该平面相交的位置。此外,将 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);

然后,不是在与确定轨迹相同的 if 中检查 GetKeyUp(KeyCode.Mouse0),而是需要在它旁边检查是否找到轨迹:

        }
    } 
}

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 作为必要的。如果您自己找不到好的解决方案,最好在单独的问题中提出。