为什么我的 3d 对象夹不能统一工作?

Why is my 3d object clamp not working in unity?

总结: 我正在统一尝试一些东西以更好地理解 it.I 创建了一个带有刚体的 3d 对象并冻结了 y 轴。我将相机放置在向下看 3d 对象的位置,对象可以使用 x 和 z 轴向左、向右、向上、向下移动。

问题:问题是播放器超出屏幕边界。

这是我的代码,基于我自己的理解(在统一手册中)和其他有同样问题的人的代码。

private Vector3 transformPos;

void LateUpdate () 
{
    //Defined the boundaries of the screen by using ViewPortToWorldPoint. I tried ViewportToWorldPoint as well and it did not work
    float left = Camera.main.WorldToViewportPoint(Vector3.zero).x;
    float right = Camera.main.WorldToViewportPoint(Vector3.one).x;
    float top = Camera.main.WorldToViewportPoint(Vector3.zero).y;
    float bottom = Camera.main.WorldToViewportPoint(Vector3.one).y;

    //Brought the player transform from World units to screen unit. Where x is x, z from the 3d object acts as y, and y is z.
    transformPos = Camera.main.WorldToViewportPoint (transform.position);
    //This debug was to check if z is y in the ViewportPoint and it was
    Debug.Log(transformPos);

    float x = transformPos.x;
    //Calling it z because I dont wanna confuse myself when I convert it back
    float z = transformPos.y;
    
    //This is where I start the clamping using if statements
    if(transformPos.x <= left)
    {
        x = Mathf.Clamp(transformPos.x, 0.1f,0.9f);
    }
    else if(transformPos.x >= right)
    {
        x = Mathf.Clamp(transformPos.x, 0.1f,0.9f);
    }

    if(transformPos.y <= top)
    {
        z = Mathf.Clamp(transformPos.y, 0.1f,0.9f);
    }
    else if( transformPos.y >= bottom)
    {
        z = Mathf.Clamp(transformPos.y, 0.1f,0.9f);
    }

    //And then finally I convert it back to world unit where the values is just placed in. x is x, y of the 3d object remains the same, and z 
    transform.position = Camera.main.ViewportToWorldPoint(new Vector3(x,transform.position.y,z));
    
}

下图是我从这段代码中得到的:

正如你从我右下方的主摄像头看到的那样,它完全在我的屏幕范围之外,我无法移动它。所以我的代码显然有问题,但我不明白我错在哪里。

编辑#1

图中的立方体就是我用的播放器

编辑#2

下面的代码是我附加在我的播放器上的播放器移动脚本以及上面的脚本。我不认为它与它冲突,但以防万一。移动也有一点问题(我正在尝试使用 phone 倾斜功能移动播放器),但我也在尝试修复它

  Rigidbody playerRigidbody;

public float speed = 10;
private Vector3 movement;
private Vector3 tilt ;


// Start is called before the first frame update
void Start()
{
    playerRigidbody = GetComponent<Rigidbody>();
}

// Update is called once per frame
void Update()
{
    tilt = Input.acceleration.normalized;
    tilt = Quaternion.Euler(90f, 0, 0) * tilt;
    //movement = new Vector3(Input.acceleration.normalized.x, 0.0f, 0.0f);
}

void FixedUpdate()
{

    //  horizontal movement code through device rotation
    //var movement = new Vector3(Input.acceleration.normalized.x, 0.0f, Input.acceleration.normalized.z);
    //playerRigidbody.velocity = movement * speed;
    MoveCharacter(tilt);

}

private void MoveCharacter(Vector3 direction)
{
    //playerRigidbody.velocity = movement * speed;
    playerRigidbody.MovePosition(transform.position + (direction * speed * Time.deltaTime));
}
private Vector3 transformPos;

void LateUpdate()
{
    //Defined the boundaries of the screen by using ViewPortToWorldPoint. I tried ViewportToWorldPoint as well and it did not work
    float LeftBottom = 1;
    float RightBottom = 0;
    float LeftTop = 1;
    float RightTop = 0;
    Debug.Log($"Left: {LeftBottom} \n Right: {RightBottom} \n Top: {LeftTop} \n Bottom: {RightTop}");
    //Brought the player transform from World units to screen unit. Where x is x, z from the 3d object acts as y, and y is z.
    transformPos = Camera.main.WorldToViewportPoint(transform.position);
    //This debug was to check if z is y in the ViewportPoint and it was
    Debug.Log(transformPos);

    float x = transformPos.x;
    //Calling it z because I dont wanna confuse myself when I convert it back
    float z = transformPos.y;

    //This is where I start the clamping using if statements
    if (transformPos.x <= LeftBottom)
    {
        x = Mathf.Clamp(transformPos.x, 0.1f, 0.9f);
        Debug.Log(x);
    }
    else if (transformPos.x >= RightBottom)
    {
        x = Mathf.Clamp(transformPos.x, 0.1f, 0.9f);
    }

    if (transformPos.y <= LeftTop)
    {
        z = Mathf.Clamp(transformPos.y, 0.1f, 0.9f);
    }
    else if (transformPos.y >= RightTop)
    {
        z = Mathf.Clamp(transformPos.y, 0.1f, 0.9f);
    }

    //And then finally I convert it back to world unit where the values is just placed in. x is x, y of the 3d object remains the same, and z 
    transform.position = Camera.main.ViewportToWorldPoint(new Vector3(x, z, 1));

}

以上代码有效。谢谢@Ubaldo Vitiello。我在这里添加我自己的答案的原因也是为了解释为什么玩家会在完全停止之前移动一点然后口吃。花了我一段时间,但我终于明白了原因。 这是因为“WorldToViewportPoint”与“rigidbody.MovePosition”不兼容。现在这只是我的理解,所以我可能是错的,但是 MovePosition 是玩家的刚体移动到您指定的位置的地方。该位置仅出现在世界space。 “WorldToViewportPoint” 将 world space 转换为视口 space。这就是为什么我的玩家在完成之前移动了一点,直到完全停止,因为我的第二个脚本附加到播放器正在将其转换为视口 space。现在我的播放器会口吃的原因是因为我当时正在将视口 space 转换回世界 space。这两个代码根本不兼容,仅此而已。 我如何解决它是使用 rigidbody.velocity