IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity 第三人称自由视角 环绕相机脚本 -> 正文阅读

[游戏开发]Unity 第三人称自由视角 环绕相机脚本

说明

按下鼠标左键并拖拽,可以让相机在上下和左右方向以角色为轴心旋转

鼠标滚轮可以调节视角的大小

实现方式

相机不绑定在角色身上

需要在角色的中心位置放置一个空对象作为视角中心

需要在面板指定视角中心

效果?

环绕相机控制脚本

挂载在相机上

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

public class SurroundCamera : MonoBehaviour
{
    //视角中心
    public Transform CentreOfView;

    //相对距离
    public Vector3 Distance;

    //鼠标滚轮灵敏度
    public float mouseWheelSensitivity = 30;

    void Start()
    {
        Distance = CentreOfView.position - transform.position;
    }

    void Update()
    {
        Follow();
        DragToRotateView();
        ScrollToScaleDistance();
    }

    void Follow()
    {
        transform.position = CentreOfView.position - Distance;
    }

    private Vector3 startPoint;
    private Vector3 endPoint;
    //旋转每度需要拖拽的距离
    public int DragDistancePerAngle = 5;

    //两点连线与水平方向的夹角
    public float currentAngleY;
    //最小水平夹角
    public float MinimumDegree = 10;
    //最大水平夹角
    public float MaximumDegree = 35;

    void DragToRotateView()
    {
        if (Input.GetMouseButtonDown(0))
        {
            startPoint = Input.mousePosition;
        }

        if (Input.GetMouseButton(0))
        {
            endPoint = Input.mousePosition;
            float dx = endPoint.x - startPoint.x;
            float dy = endPoint.y - startPoint.y;

            //将鼠标在屏幕上拖拽的距离转化为角度
            float anglex = dx / DragDistancePerAngle;
            float angley = dy / DragDistancePerAngle;

            //计算两点连线与水平方向的夹角
            currentAngleY = 90 - Vector3.Angle(CentreOfView.position - transform.position, Vector3.down);

            if (currentAngleY - angley > MaximumDegree || currentAngleY - angley < MinimumDegree)
                angley = 0;

            Vector3 linkVector = CentreOfView.position - transform.position;
            Vector3 verticalRotateAxis = Vector3.Cross(linkVector, Vector3.up).normalized;

            transform.RotateAround(CentreOfView.position, Vector3.up, anglex);
            transform.RotateAround(CentreOfView.position, verticalRotateAxis, angley);

            //如果没有这一句,摄像头转着转着就会歪
            transform.LookAt(CentreOfView);

            //更新距离
            Distance = CentreOfView.position - transform.position;

            startPoint = endPoint;
            endPoint = Vector3.zero;
        }
    }

    //调节视角

    //方案一
    public float MinFieldOfView = 20f;
    public float MaxFieldOfView = 100f;

    void ScrollToScaleView()
    {
        if (Input.GetAxis("Mouse ScrollWheel") == 0) return;

        GetComponent<Camera>().fieldOfView = GetComponent<Camera>().fieldOfView - Input.GetAxis("Mouse ScrollWheel") * mouseWheelSensitivity;
        GetComponent<Camera>().fieldOfView = Mathf.Clamp(GetComponent<Camera>().fieldOfView, MinFieldOfView, MaxFieldOfView);
    }

    //方案二
    public float MinViewDistance = 1;
    public float MaxViewDistance = 10;

    void ScrollToScaleDistance()
    {
        transform.position = CentreOfView.transform.position - Distance;

        if (Input.GetAxis("Mouse ScrollWheel") > 0)
        {
            if (Distance.magnitude <= MinViewDistance) return;

            transform.Translate(Distance / mouseWheelSensitivity *10, Space.World);
            Distance = CentreOfView.transform.position - transform.position;
        }
        else if (Input.GetAxis("Mouse ScrollWheel") < 0)
        {
            if (Distance.magnitude >= MaxViewDistance) return;

            transform.Translate(-Distance / mouseWheelSensitivity *10, Space.World);
            Distance = CentreOfView.transform.position - transform.position;
        }
    }    
}

原理解释

跟随:

相机不绑定在角色身上,而是作为一个单独的对象时刻跟随着角色

拖拽以旋转:

通过记录鼠标点击的前一位置与后一位置,用其长度控制旋转的角度

环绕:

使用transform.RotateAround函数,让相机围绕着视角中心旋转

水平环绕:

以竖直向上的单位向量为轴环绕

面向角色竖直环绕:

以 角色与相机的连线 与 竖直向上的单位向量 所在的平面法向量为轴环绕

限定视角参数的范围:

使用Mathf.Clamp函数

角色控制脚本

挂载在角色上

WS 前进后退 AD 左右旋转 空格跳跃

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

public class PlayerControl : MonoBehaviour
{
    //速度:每秒移动4个单位长度
    public float moveSpeed = 4;

    //角速度:每秒旋转60度
    private float angularSpeed = 60;

    //角色水平旋转灵敏度
    public float horizontalRotateSensitivity = 2;

    //跳跃参数
    public float jumpForce = 200f;

    //角色的刚体
    private Rigidbody rigidbody;

    //动画控制器
    Animator anim;

    //二段跳限制
    private int jumpLimit = 2;

    void Start()
    {
        rigidbody = GetComponent<Rigidbody>();
        anim = GetComponent<Animator>();
    }

    void FixedUpdate()
    {
        Move();
        Jump();
    }

    void Move()
    {
        //通过键盘获取竖直、水平轴的值,范围在-1到1
        float v = Input.GetAxis("Vertical");
        float h = Input.GetAxis("Horizontal");

        //按下左边Shift键行走
        if (Input.GetKey(KeyCode.LeftShift))
        {
            v *= 0.5f;
        }

        //传入动画所需要的参数
        //SpeedX代表水平轴,SpeedY代表竖直轴
        anim.SetFloat("SpeedX", h);
        anim.SetFloat("SpeedY", v);

        //前进后退
        transform.Translate(Vector3.forward * v * Time.deltaTime * moveSpeed);

        //水平旋转
        transform.Rotate(Vector3.up * h * Time.deltaTime * angularSpeed * horizontalRotateSensitivity);
    }

    // 通过射线检测角色是在地面或者物体上(注意,角色的零点需要设置在脚底处)
    bool IsGrounded()
    {
        return Physics.Raycast(transform.position, -Vector3.up, 0.1f);
    }

    void Jump()
    {
        //如果接触地面,则恢复可跳跃次数
        if (IsGrounded())
        {
            jumpLimit = 2;
            anim.SetBool("Jump", false);
        }

        if (Input.GetKeyDown(KeyCode.Space))
        {
            //限制最多二段跳
            if (jumpLimit > 0)
            {
                rigidbody.AddForce(Vector3.up * jumpForce);
                anim.SetBool("Jump", true);
                jumpLimit--;
            }
        }
    }
}

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-03-04 15:56:00  更:2022-03-04 15:56:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 16:37:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码