【UNITY 3D】第三人称相机的代码实现

一个游戏,少不了摄像机的参与。摄像机,总体来说分为了两大类别:上帝视角,也就是俗称的第三人称视角,以一种凌驾于游戏object的方式存在,玩家跟上帝一般俯瞰整个游戏;主角视角,第一人称视角,以主角的角度观看游戏的发展状态;观察视角,关注于某个物体的视角,这个视角在一些密室逃脱类游戏里经常有。
下面我们来实现一下第三人称相机,
因为不习惯Cinemachine插件,所以自己手写了一个。
eg:其实只是因为我菜不知道怎么用......

相机跟随角色

相机跟随很容易实现

只需将camera作为子物件放在player上即可。

相机随鼠标移动

让我们新建一个C#脚本,并将其加入到Camera中

public class CameraController : MonoBehaviour
{
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    private float mouseX, mouseY;
    public float mouseSensitivity;//鼠标灵敏度
    public Transform target;//父物体,即player,在脚本界面将player托人即可

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
        mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;

        float nowFlip = transform.localEulerAngles.x + mouseY * mouseSensitivity * Time.deltaTime;
        if (nowFlip < 60 || nowFlip > 300) //相机围绕角色上下旋转的角度限定
        {
            transform.RotateAround(target.transform.position, transform.right, mouseY * mouseSensitivity * Time.deltaTime);//上下旋转
        }
        transform.RotateAround(target.transform.position, Vector3.up, mouseX * mouseSensitivity * Time.deltaTime);//左右旋转
    }

}

角色朝向随镜头方向改变

接下来我们想让Player在移动时,w方向始终朝向镜头方向,且模型朝向随键盘输入的移动方向改变,
下面我们对C#脚本进行完善

//将其相应进行添加进行
    private float hMove;
    private float vMove;
    private Vector3 rot, myRot, myPos;

void LateUpdate() //角色跟随键盘操作转向,放到Lateupdate中防止了Player模型抖动
    {
        hMove = Input.GetAxis("Horizontal") ;
        vMove = Input.GetAxis("Vertical") ;
        myRot = transform.eulerAngles;
        myPos = transform.position;
        rot = target.eulerAngles;
        //根据Horizontal与Vertical来判断Player朝向
        if (vMove > 0)
            if (hMove == 0)
            {
                rot.y = transform.eulerAngles.y;
            }
            else
            {
                rot.y = transform.eulerAngles.y + Mathf.Atan2(hMove, vMove) * 180 / Mathf.PI;
                if (rot.y < 0)
                    rot.y += 360;
                else if (rot.y >= 360)
                    rot.y -= 360;
            }

        else if (vMove < 0)
            if (hMove == 0)
            {
                rot.y = transform.eulerAngles.y + 180;
                if (rot.y >= 360)
                    rot.y -= 360;
            }
            else
            {
                rot.y = transform.eulerAngles.y + Mathf.Atan2(hMove, vMove) * 180 / Mathf.PI;
                if (rot.y < 0)
                    rot.y += 360;
                else if (rot.y >= 360)
                    rot.y -= 360;
            }
        else
            if (hMove > 0)
        {
            rot.y = transform.eulerAngles.y + 90;
            if (rot.y >= 360)
                rot.y -= 360;
        }
        else if (hMove < 0)
        {
            rot.y = transform.eulerAngles.y - 90;
            if (rot.y < 0)
                rot.y += 360;
        }
        target.eulerAngles = rot;
        transform.eulerAngles = myRot;
        transform.position = myPos;
    }

接下来在你的控制角色移动的脚本中加入下面的代码

private Vector3 rot, myRot, myPos;
public Transform cam;//将相机拖入
void move()//检测移动操作后使角色朝向更改为相机朝向,并执行移动操作
           //使角色移动操作不会受到影响
{

    if (Input.GetAxis("Horizontal")!= 0 || Input.GetAxis("Vertical") != 0)
    {
        myRot = cam.eulerAngles;
        myPos = cam.position;
        rot = transform.eulerAngles;
        rot.y = transform.eulerAngles.y;
        transform.eulerAngles = rot;
        cam.eulerAngles = myRot;
        cam.position = myPos;
    }
    //
	//这里写你原本角色move操作的代码
    //
}

鼠标滚轮实现场景缩放

让我们在camera脚本中继续添加如下代码

    public float m_sSpeed;//滚轮灵敏度
    public float m_maxDistance, m_minDistance;//最大,最小视野距离

    void Update()
    {
        if (Input.GetAxis("Mouse ScrollWheel") != 0)
        {
            float m_distance = Input.GetAxis("Mouse ScrollWheel") * m_sSpeed;
            Vector3 oldPos = transform.localPosition;
            Vector3 newPos = transform.position + transform.forward * m_distance;
            transform.position = newPos;
            if (transform.localPosition.magnitude >= m_maxDistance || transform.localPosition.magnitude <= m_minDistance)
                transform.localPosition = oldPos;
        }
    }

完整代码

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

public class CameraController : MonoBehaviour
{
    private float mouseX, mouseY;
    public float mouseSensitivity;
    public Transform target;
    public float m_sSpeed;
    public float m_maxDistance, m_minDistance;

    private float hMove;
    private float vMove;
    private Vector3 rot, myRot, myPos;

    void LateUpdate()
    {
        hMove = Input.GetAxis("Horizontal");
        vMove = Input.GetAxis("Vertical");
        myRot = transform.eulerAngles;
        myPos = transform.position;
        rot = target.eulerAngles;
        if (vMove > 0)
            if (hMove == 0)
            {
                rot.y = transform.eulerAngles.y;
            }
            else
            {
                rot.y = transform.eulerAngles.y + Mathf.Atan2(hMove, vMove) * 180 / Mathf.PI;
                if (rot.y < 0)
                    rot.y += 360;
                else if (rot.y >= 360)
                    rot.y -= 360;
            }

        else if (vMove < 0)
            if (hMove == 0)
            {
                rot.y = transform.eulerAngles.y + 180;
                if (rot.y >= 360)
                    rot.y -= 360;
            }
            else
            {
                rot.y = transform.eulerAngles.y + Mathf.Atan2(hMove, vMove) * 180 / Mathf.PI;
                if (rot.y < 0)
                    rot.y += 360;
                else if (rot.y >= 360)
                    rot.y -= 360;
            }
        else
            if (hMove > 0)
        {
            rot.y = transform.eulerAngles.y + 90;
            if (rot.y >= 360)
                rot.y -= 360;
        }
        else if (hMove < 0)
        {
            rot.y = transform.eulerAngles.y - 90;
            if (rot.y < 0)
                rot.y += 360;
        }
        target.eulerAngles = rot;
        transform.eulerAngles = myRot;
        transform.position = myPos;
    }

    // Update is called once per frame
    void Update()
    {
        mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
        mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
        float nowFlip = transform.localEulerAngles.x + mouseY * mouseSensitivity * Time.deltaTime;
        if (nowFlip < 60 || nowFlip > 300)
        {
            transform.RotateAround(target.transform.position, transform.right, mouseY * mouseSensitivity * Time.deltaTime);
        }
        transform.RotateAround(target.transform.position, Vector3.up, mouseX * mouseSensitivity * Time.deltaTime);

        //鼠标滚轮场景缩放;
        if (Input.GetAxis("Mouse ScrollWheel") != 0)
        {
            float m_distance = Input.GetAxis("Mouse ScrollWheel") * m_sSpeed;
            Vector3 oldPos = transform.localPosition;
            Vector3 newPos = transform.position + transform.forward * m_distance;
            transform.position = newPos;
            if (transform.localPosition.magnitude >= m_maxDistance || transform.localPosition.magnitude <= m_minDistance)
                transform.localPosition = oldPos;

        }

    }
}

注意不要忘记修改你的人物操作代码!!!!!代码在角色朝向随镜头方向改变中!!!

最终效果

avatar
看起来还是很不错的、emmmmm

posted @ 2021-03-12 12:33  ReyHan  阅读(2079)  评论(0)    收藏  举报