制作大型MMO项目中的相机视角操作

发表于2017-09-30
评论0 1.5k浏览

今天闲下来给大家实现个大型MMORPG项目中都会用到的功能

1.相机跟随玩家

2.左右滑动屏幕 旋转相机

3.上下滑动屏幕或使用鼠标滚轮 缩放相机及调整相机视野

上效果图:

角色移动脚本:

using UnityEngine;
using System.Collections;
public class MoveController : MonoBehaviour {
    Transform camera;
    Animator ani;
    NavMeshAgent nav;
    float h, v;
    Vector3 moveVec;
    // Use this for initialization
    void Start () {
        camera = Camera.main.transform;
        ani = GetComponent();
        nav = GetComponent();
    }
	// Update is called once per frame
	void Update () {
        h = Input.GetAxis("Horizontal");
        v = Input.GetAxis("Vertical");
        moveVec = new Vector3(h, 0, v);
        if (h != 0 || v != 0)
        {
            ani.SetBool("Run", true);
            // 根据摄像机方向 进行移动
            moveVec = Quaternion.Euler(0, camera.eulerAngles.y, 0) * moveVec;
            nav.Move(moveVec * Time.deltaTime * 5);
            RotatePlayer();
        }
        else
        {
            ani.SetBool("Run", false);
        }
	}
    private void RotatePlayer()
    {
        Vector3 vec = Quaternion.Euler(0, 0, 0) * moveVec;
        Quaternion qua = Quaternion.LookRotation(vec);
        transform.rotation = Quaternion.Lerp(transform.rotation, qua, Time.deltaTime * 100);
    }
}

相机控制脚本:

using UnityEngine;
public class ThirdCamera : MonoBehaviour
{
    public Transform target = null;     // 目标玩家
    [SerializeField]
    [Range(0, 360)]
    float horizontalAngle = 270f;      // 水平角度
    [SerializeField]
    [Range(0, 20)]
    float initialHeight = 2f;    // 人物在视野内屏幕中的位置设置
    [SerializeField]
    [Range(10, 90)]
    float initialAngle = 40f;   // 初始俯视角度
    [SerializeField]
    [Range(10, 90)]
    float maxAngle = 50f;     // 最高俯视角度
    [SerializeField]
    [Range(10, 90)]
    float minAngle = 35f;     // 最低俯视角度
    float initialDistance;    // 初始化相机与玩家的距离 根据角度计算
    [SerializeField]
    [Range(1, 100)]
    float maxDistance = 20f;        // 相机距离玩家最大距离
    [SerializeField]
    [Range(1, 100)]
    float minDistance = 5f;        // 相机距离玩家最小距离
    [SerializeField]
    [Range(1, 100)]
    float zoomSpeed = 50;       // 缩放速度
    [SerializeField]
    [Range(1f, 200)]
    float swipeSpeed = 50;      // 左右滑动速度
    float scrollWheel;        // 记录滚轮数值
    float tempAngle;          // 临时存储摄像机的初始角度
    Vector3 tempVector = new Vector3();
    void Start()
    {
        InitCamera();
    }
    void Update()
    {
        ZoomCamera();
        SwipeScreen();
    }    
    void LateUpdate()
    {
        FollowPlayer();
        RotateCamera();
    }
    /// 
    /// 初始化 相机与玩家距离
    /// 
    void InitCamera()
    {
        tempAngle = initialAngle;
        initialDistance = Mathf.Sqrt((initialAngle - minAngle) / Calculate())   minDistance;
        initialDistance = Mathf.Clamp(initialDistance, minDistance, maxDistance);
    }
    /// 
    /// 相机跟随玩家
    /// 
    void FollowPlayer()
    {
        float upRidus = Mathf.Deg2Rad * initialAngle;
        float flatRidus = Mathf.Deg2Rad * horizontalAngle;
        float x = initialDistance * Mathf.Cos(upRidus) * Mathf.Cos(flatRidus);
        float z = initialDistance * Mathf.Cos(upRidus) * Mathf.Sin(flatRidus);
        float y = initialDistance * Mathf.Sin(upRidus);
        transform.position = Vector3.zero;
        tempVector.Set(x, y, z);
        tempVector = tempVector   target.position;
        transform.position = tempVector;
        tempVector.Set(target.position.x, target.position.y   initialHeight, target.position.z);
        transform.LookAt(tempVector);
    }
    /// 
    /// 缩放相机与玩家距离
    /// 
    void ZoomCamera()
    {
        scrollWheel = GetZoomValue();
        if (scrollWheel != 0)
        {
            tempAngle = initialAngle - scrollWheel * 2 * (maxAngle - minAngle);
            tempAngle = Mathf.Clamp(tempAngle, minAngle, maxAngle);
        }
        if (tempAngle != initialAngle)
        {
            initialAngle = Mathf.Lerp(initialAngle, tempAngle, Time.deltaTime * 10);
            initialDistance = Mathf.Sqrt((initialAngle - minAngle) / Calculate())   minDistance;
            initialDistance = Mathf.Clamp(initialDistance, minDistance, maxDistance);
        }
    }
    float Calculate()
    {
        float dis = maxDistance - minDistance;
        float ang = maxAngle - minAngle;
        float line = ang / (dis * dis);
        return line;
    }
    bool isMousePress = false;
    Vector2 oldMousePos;
    Vector2 newMousePos;
    Vector2 mousePosOffset;
    /// 
    /// 滑动屏幕 旋转相机和缩放视野
    /// 
    public void SwipeScreen()
    {
        if (Input.GetMouseButtonDown(0))
        {
            oldMousePos = Vector2.zero;
            isMousePress = true;
        }
        else if(Input.GetMouseButtonUp(0))
        {
            mousePosOffset = Vector2.zero;
            isMousePress = false;
        }
        if (!isMousePress)
            return;
        newMousePos = Input.mousePosition;
        if(oldMousePos != Vector2.zero)
        {
            mousePosOffset = newMousePos - oldMousePos;
        }
        oldMousePos = newMousePos;
    }
    /// 
    /// 获取缩放视野数值  1.鼠标滚轮 2.屏幕上下滑动
    /// 
    /// 
    float GetZoomValue()
    {
        float zoomValue = 0;
        // 使用鼠标滚轮
        if (Input.GetAxis("Mouse ScrollWheel") != 0)
        {
            zoomValue = Input.GetAxis("Mouse ScrollWheel");
        }
        else if (mousePosOffset != Vector2.zero)
        {
            zoomValue = mousePosOffset.y * Time.deltaTime * zoomSpeed * 0.01f;
        }
        return zoomValue;
    }
    float xVelocity = 0;
    /// 
    /// 旋转相机
    /// 
    void RotateCamera()
    {
        horizontalAngle = Mathf.SmoothDamp(horizontalAngle, horizontalAngle   mousePosOffset.x * Time.deltaTime * swipeSpeed, ref xVelocity, 0.1f);
    }
}

相机参数已测试参考值:

项目使用版本:Unity5.3.4 GitHub下载地址:

https://github.com/654306663/CameraOperate

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: