Unity开发技巧之摄像机跟随

前言

游戏开发中,不可避免地会涉及摄像机的跟随和控制,摄像机的位置以及角度朝向都需要在不断的调试中,以确认出对玩家比较友好的方案。本篇中将讨论几种在Unity3D中摄像机跟随的方案。

方案一:作为目标的子物体跟随目标的进行空间坐标变换

如字面意思,将摄像机作为需要跟随的目标的子物体,在操纵目标进行移动旋转时,摄像机也会跟随父物体进行移动旋转。

    

优点:简单直观,不需要写代码。

不足:由于是跟随父物体一起运动,会随着父物体的旋转而旋转,当父物体的旋转不当时,摄像机的角度无法进行调整。

方案二:利用三角函数关系求得摄像机位置,并时刻跟随目标

这里有几个参数需要介绍一下

水平偏移角度:摄像机在x轴和z轴平面中,与目标位置形成的角度

垂直偏移角度:摄像机在x轴和y轴平面中,与目标位置形成的角度

距离:摄像机与目标之间的距离

Unity开发技巧之摄像机跟随_第1张图片

现在我们分别从水平平面和垂直平面中求得摄像机的x、y、z坐标。

垂直平面

Unity开发技巧之摄像机跟随_第2张图片

height = distance * Mathf.Sin(roll)

temp= distance * Mathf.Cos(roll)

在垂直平面中,我们求得摄像机距目标的相对高度,即摄像机的y坐标,和求x、z坐标的一个中间值

水平平面

Unity开发技巧之摄像机跟随_第3张图片

cameraPos.x = targetPos.x + temp * Mathf.Cos(rot);
cameraPos.z = targetPos.z + temp * Mathf.Sin(rot);

通过中间值temp,我们便可以求得摄像机的x、z坐标

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

public class CameraFollow : MonoBehaviour {
    //距离
    public float distance = 8;
    //横向角度
    public float rot = 0;
    //纵向角度
    private float roll = 30f * Mathf.PI * 2 / 360;
    //目标物体
    private GameObject target;
    //横向旋转速度
    public float rotSpeed = 0.2f;
    //纵向角度范围
    private float maxRoll = 70f * Mathf.PI * 2 / 360;
    private float minRoll = -10f * Mathf.PI * 2 / 360;
    //纵向旋转速度
    private float rollSpeed = 0.2f;
    //距离范围
    public float maxDistance = 22f;
    public float minDistance = 5f;
    //距离变化速度
    public float zoomSpeed = 0.2f;

    void Start() {
        //找到坦克
        //SetTarget(GameObject.Find("tank"));
    }

    void LateUpdate() {
        //一些判断
        if (target == null)
            return;
        if (Camera.main == null)
            return;
        //目标的坐标
        Vector3 targetPos = target.transform.position;
        //用三角函数计算相机位置
        Vector3 cameraPos;
        float d = distance * Mathf.Cos(roll);
        float height = distance * Mathf.Sin(roll);
        cameraPos.x = targetPos.x + d * Mathf.Cos(rot);
        cameraPos.z = targetPos.z + d * Mathf.Sin(rot);
        cameraPos.y = targetPos.y + height;
        Camera.main.transform.position = cameraPos;
        //对准目标
        Camera.main.transform.LookAt(target.transform);
        //横向旋转
        Rotate();
        //纵向旋转
        Roll();
        //调整距离
        Zoom();
    }

    //设置目标
    public void SetTarget(GameObject target) {
        if (target.transform.Find("cameraPoint") != null)
            this.target = target.transform.Find("cameraPoint").gameObject;
        else
            this.target = target;
    }

    //横向旋转
    void Rotate() {
        float w = Input.GetAxis("Mouse X") * rotSpeed;
        rot -= w;
    }

    //纵向旋转
    void Roll() {
        float w = Input.GetAxis("Mouse Y") * rollSpeed * 0.5f;

        roll -= w;
        if (roll > maxRoll)
            roll = maxRoll;
        if (roll < minRoll)
            roll = minRoll;
    }

    //调整距离
    void Zoom() {
        if (Input.GetAxis("Mouse ScrollWheel") > 0) {
            if (distance > minDistance)
                distance -= zoomSpeed;
        } else if (Input.GetAxis("Mouse ScrollWheel") < 0) {
            if (distance < maxDistance)
                distance += zoomSpeed;
        }
    }
}

 优点:比较严谨摄像机跟随方案,可进行进一步的摄像机控制,例如视角的操控

缺点:实现过程稍麻烦,需要理解摄像机与跟随目标的三角函数关系

方案三:利用向量的插值运算与四元数

Unity开发技巧之摄像机跟随_第4张图片

  • 先计算出摄像机与目标的相对位置

Vector3 TargetPos = new Vector3(0, 3f, -3f);
transform.position = Vector3.Lerp(transform.position, playerTransform.position + TargetPos, speed * Time.deltaTime);

使用Lerp函数是为了摄像机移动的更平滑些。

  • 然后通过四元素进行视角的注视

Quaternion TargetRotation = Quaternion.LookRotation(playerTransform.position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, TargetRotation, speed * Time.deltaTime);

使用Slerp函数与使用Lerp函数同理

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

public class FollowPlayer : MonoBehaviour
{
    public float speed = 2f;

    private Transform playerTransform;
	
	void Start ()
    {
        playerTransform = GameObject.FindGameObjectWithTag("Player").transform;
	}
	
	
	void Update ()
    {
        if (playerTransform == null)
            return;
        Vector3 TargetPos = new Vector3(0, 3f, -3f);
        transform.position = Vector3.Lerp(transform.position, playerTransform.position + TargetPos, speed * Time.deltaTime);

        Quaternion TargetRotation = Quaternion.LookRotation(playerTransform.position - transform.position);
        transform.rotation = Quaternion.Slerp(transform.rotation, TargetRotation, speed * Time.deltaTime);

    }
}

优点:代码实现简单,可以做出不错的摄像机跟随效果。

不足:不便于进行视角的操控

总结

由于博主能力有限,在学习过程中,总结了这三种摄像机跟随的实现方案,实现是比较简单的,而且能满足基本的需求。

你可能感兴趣的:(Unity3D开发小技巧)