Unity上帝视角摄像机的实现

 适用于2.5D模拟经营、战旗策略类游戏摄像机脚本,需要获取主摄像机Main Camera对象和地形terrain对象,摄像机初始位置基于地图的尺寸设定在地图上空中心位置,并且x轴旋转45度俯瞰地图。

 

 实现了缩放摄像机(拉远、拉近)方法、WASD移动摄像机方法、按住鼠标右键旋转摄像机方法和限制摄像机移动范围方法。其中限制摄像机移动范围方法并不准确,需要获得摄像机视口范围即视野和地图相交的坐标信息,因为高度增加摄像机视野会变大,不同高度的摄像机被限制的范围应和高度建立联系,解决这一问题涉及了较深数学知识,先按下不表,使用简单的范围限制。

 

 完成这一脚本对扩充了我的以下知识点:

 

 1.Mathf.Sin等三角函数参数为弧度,需要把角度进行转换后传入

 

 2. 地形尺寸获取即获取地形的碰撞器的尺寸

 

 3.摄像机位置只能对position进行赋值、加减等操作,不能单独对position的x、y、z变量操作,因此需要声明一个Vector3变量,对此变量进行操作,再传给摄像机坐标

 

 4.Input.GetAxis("Vertical")、Input.GetAxis("Horizontal")返回的是1或-1,使用该封装可以简化按键事件,但如果提供修改键位功能还是需要老老实实写wasd等按键的事件

 

 5.旋转摄像机后再移动摄像机并不会按照摄像机方向移动,仍然会按照世界坐标系移动,因此移动摄像机算法中,不能使用对摄像机坐标的x、y、z直接加减,要使用摄像机坐标直接加减Vector3变量,该变量需要乘以transform.forward或transform.right方向向量,考虑到摄像机的x轴旋转了一定角度,需要把forward、right赋值为另一个Vector3变量,将其y变量赋为0,就使摄像机按照朝向的水平方向移动了

 

 6.由于摄像机是自由移动的,没有target作为目标点,缩放就不能使用修改distance的方法,在试过很多错误道路后,我发现缩放的实现和移动唯一的不同就是把将y变量赋为0这一步取消

 

脚本内容如下:

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraControl : MonoBehaviour {
    public GameObject mainCamera;//获取摄像机
    public GameObject terrain;//获取地图
    public float rollAngle=45;//摄像机倾斜角度
    public float height=40f;//摄像机和地图的高度差
    public float moveSpeed = 1.5f;//摄像机移动速度系数
    public float maxRangeX;//摄像机x坐标变化范围
    public float minRangeX;
    public float maxRangeZ;//摄像机z坐标变化范围
    public float minRangeZ;
    public float maxRangeY = 75f;//缩放最大高度
    public float minRangeY = 30f;//缩放最小高度
    public float zoomSpeed = 5f;//缩放速度系数
    public float rotateAngle = 0;
    public float rotateSpeed=100f;//旋转速度系数
    Vector3 cameraPos;//摄像机临时坐标
    public float sizeX;//地图尺寸x
    public float sizeZ;//地图尺寸z
    void Start () {
        //获取地图尺寸
        sizeX = terrain.GetComponent<TerrainCollider>().bounds.size.x;
        sizeZ = terrain.GetComponent<TerrainCollider>().bounds.size.z;
        maxRangeX = terrain.transform.position.x + 0.75f * sizeX;
        minRangeX = terrain.transform.position.x + 0.25f * sizeX;
        maxRangeZ = terrain.transform.position.z + 0.75f * sizeZ;
        minRangeZ = terrain.transform.position.z + 0.25f * sizeZ;
        //设置摄像机位置
        cameraPos.x = terrain.transform.position.x +  sizeX/ 2 ;
        cameraPos.y = terrain.transform.position.y + height;
        cameraPos.z = terrain.transform.position.z +  sizeZ/ 2 ;
        mainCamera.transform.position = cameraPos;
        mainCamera.transform.eulerAngles = new Vector3(rollAngle, 0, 0);
        Debug.Log("地图尺寸为:" + sizeX + "X" + sizeZ);
    }
	void Update () {
        //更新摄像机坐标
        MoveCamera();
        RotateCamera();
        ZoomCamera();
        LimitRange();
        mainCamera.transform.position = cameraPos;
    }
    void MoveCamera() {
        //第一种方法按下WS、AD,Input.GetAxis()会返回1或-1
        float moveZ = Input.GetAxis("Vertical");
        Vector3 moveDirectionZ = transform.forward;
        moveDirectionZ.y = 0;
        cameraPos += moveDirectionZ * moveZ * moveSpeed;
        float moveX = Input.GetAxis("Horizontal");
        Vector3 moveDirectionX = transform.right;
        moveDirectionZ.y = 0;
        cameraPos += moveDirectionX * moveX * moveSpeed;
        //按下shift加速移动摄像机
        if (Input.GetKey(KeyCode.LeftShift))
            moveSpeed = 2.5f;
        if (Input.GetKeyUp(KeyCode.LeftShift))
            moveSpeed = 1.5f;
    }
    void ZoomCamera() {
        //滚动鼠标滑轮缩放摄像机
        if (Input.GetAxis("Mouse ScrollWheel") > 0) {
            if (cameraPos.y < minRangeY)
                return;
            Vector3 moveDirectionZ = transform.forward;
            cameraPos += moveDirectionZ * zoomSpeed;
        }
        if (Input.GetAxis("Mouse ScrollWheel") <0) {
            if (cameraPos.y > maxRangeY)
                return;
            Vector3 moveDirectionZ = -transform.forward;
            cameraPos += moveDirectionZ * zoomSpeed;
        }
    }
    void RotateCamera() {
        //按下鼠标右键旋转摄像机
        if (Input.GetMouseButton(1)) {
            rotateAngle = Input.GetAxis("Mouse X")*rotateSpeed*Time.deltaTime;
            mainCamera.transform.Rotate(0,rotateAngle,0,Space.World);
        }
    }
    void LimitRange() {
        //摄像机移动范围限制
        if (cameraPos.x > maxRangeX)
            cameraPos.x = maxRangeX;
        if (cameraPos.x < minRangeX)
            cameraPos.x = minRangeX;
        if (cameraPos.z > maxRangeZ)
            cameraPos.z = maxRangeZ;
        if (cameraPos.z < minRangeZ)
            cameraPos.z = minRangeZ;
    }
}

 

 

 

 

 

 

 

没有更多推荐了,返回首页