相机旋转后滚动

scrolling after camera rotation

我正在使用 C# 在 Unity 中编写一种 RTS CameraController。我已经设法实现了基本功能,但现在我面临一个棘手的问题。我设法旋转了相机,然后向正确的方向移动,但是旋转后我的滚动边界不再起作用(当然因为我只是在水平滚动时检查 x,但旋转后我需要检查 y ).对于边界,我的意思是限制滚动直到到达某个位置 (x < 0)。

我对如何轻松解决我的问题有点困惑。一种方法似乎是使用条件并在检查边界之前检查旋转,但这对我来说似乎不是一个好方法,只是解决了问题,但并没有真正解决问题。现在我的问题是:是否有更简单或更好的方法来实现我正在做的事情?我是不是完全错过了什么?

这就是我希望相机在所有 4 个旋转中移动的方式。矩形是我的世界,箭头定义了我的边界。相机应该总是在向后方向超调并在向前方向边界之前停止。:

这是我的更新方法(vertDist 和 horDist 只是定义鼠标滚动应该从什么时候开始):

    void LateUpdate() {
    //LEFT
    if((Input.mousePosition.x < horDist || Input.GetAxis("Horizontal") < 0)
       && transform.position.x > 0)
        transform.Translate(-speed, 0, 0);
    //RIGHT
    if((Input.mousePosition.x > Screen.width - horDist || Input.GetAxis("Horizontal") > 0)
       && transform.position.x < world.worldX)
        transform.Translate(speed, 0, 0);
    //UP
    if((Input.mousePosition.y > Screen.height - vertDist || Input.GetAxis("Vertical") > 0)
       && transform.position.z < world.worldZ - 30) {
        Vector3 temp = transform.eulerAngles;
        transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, transform.eulerAngles.z);
        transform.Translate(0, 0, speed);
        transform.eulerAngles = temp;
    }
    //DOWN
    if((Input.mousePosition.y < vertDist || Input.GetAxis("Vertical") < 0)
       && transform.position.z > -10) {
        Vector3 temp = transform.eulerAngles;
        transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, transform.eulerAngles.z);
        transform.Translate(0, 0, -speed);
        transform.eulerAngles = temp;
    }

    //ZOOM
    //camera.fieldOfView -= Input.GetAxis("Mouse ScrollWheel");

    //ROTATE
    if(Input.GetButtonDown("Rotate")){
        Vector3 targetPosition = transform.position;
        targetPosition += transform.forward * 27;
        //transform.Rotate(new Vector3(0, Mathf.Sign(Input.GetAxis("Rotate")) * 90, 0), Space.World);
        transform.RotateAround(targetPosition, Vector3.up, Mathf.Sign(Input.GetAxis("Rotate")) * 90);
    }
}

使用

transform.Translate(0, 0, -speed, Space.Self); // For all the Translate, use Space.Self

它只会根据它的本地位置而不是世界位置移动。但你会得到你想要的。 希望对你有帮助。

终于找到解决办法了!我决定根据当前旋转定义一个 Rect,然后检查相机位置是否在 Rect 内。因此我不得不弄乱这些位置,因为我不知道为什么 Rect.Contains() 只采用位置的 x 和 y 坐标。我的相机只是沿着 x 轴和 z 轴移动,所以我在那里做了这个奇怪的坐标交换:

    void LateUpdate() {
    Rect bounds = DefineBounds();
    Vector3 pos = transform.position;

    //LEFT
    if((/*Input.mousePosition.x < horDist ||*/ Input.GetAxis("Horizontal") < 0)) {
        pos += transform.TransformDirection(-speed * Time.deltaTime, 0, 0);
        //reset pos if out of bounds
        if(!bounds.Contains(new Vector2(pos.x, pos.z)))
            pos -= transform.TransformDirection(-speed * Time.deltaTime, 0, 0);
    }
    //RIGHT
    if((/*Input.mousePosition.x > Screen.width - horDist ||*/ Input.GetAxis("Horizontal") > 0)) {
        pos += transform.TransformDirection(speed * Time.deltaTime, 0, 0);
        //reset pos if out of bounds
        if(!bounds.Contains(new Vector2(pos.x, pos.z)))
            pos -= transform.TransformDirection(speed * Time.deltaTime, 0, 0);
    }
    //UP
    if((/*Input.mousePosition.y > Screen.height - vertDist ||*/ Input.GetAxis("Vertical") > 0)) {
        //Set camera x-angle to 0
        Vector3 temp = transform.eulerAngles;
        transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, transform.eulerAngles.z);

        pos += transform.TransformDirection(0, 0, speed * Time.deltaTime);
        //reset pos if out of bounds
        if(!bounds.Contains(new Vector2(pos.x, pos.z)))
            pos -= transform.TransformDirection(0, 0, speed * Time.deltaTime);

        //Reset camera x-angle
        transform.eulerAngles = temp;
    }
    //DOWN
    if((/*Input.mousePosition.y < vertDist ||*/ Input.GetAxis("Vertical") < 0)) {
        //Set camera x-angle to 0
        Vector3 temp = transform.eulerAngles;
        transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, transform.eulerAngles.z);

        pos += transform.TransformDirection(0, 0, -speed * Time.deltaTime);
        //reset pos if out of bounds
        if(!bounds.Contains(new Vector2(pos.x, pos.z)))
            pos -= transform.TransformDirection(0, 0, -speed * Time.deltaTime);

        //Reset camera x-angle
        transform.eulerAngles = temp;
    }

    transform.position = pos;

    //ZOOM
    //camera.fieldOfView -= Input.GetAxis("Mouse ScrollWheel");
    transform.position = new Vector3(pos.x, pos.y - Input.GetAxis("Mouse ScrollWheel"), pos.z);

    //ROTATE
    if(Input.GetButtonDown("Rotate")){
        Vector3 targetPosition = transform.position;
        Vector2 posXZ;

        targetPosition += transform.forward * 27;
        transform.RotateAround(targetPosition, Vector3.up, Mathf.Sign(Input.GetAxis("Rotate")) * 90);
        bounds = DefineBounds();

        pos = transform.position;
        posXZ = new Vector2(pos.x, pos.z);

        while(!bounds.Contains(posXZ)) {
            posXZ = Vector2.MoveTowards(posXZ, bounds.center, 1);

            pos.x = posXZ.x;
            pos.z = posXZ.y;
        }
        transform.position = pos;
    }
}