旋转视角

基础旋转

相机环绕角色旋转,使用RotateAround函数

视角水平旋转,以角色为圆心,以竖直向上的方向向量为旋转轴

视角上下旋转,从角色正面旋转到角色头顶,以角色为圆心,以相机左侧的方向向量为旋转轴,这种旋转之后,相机可能会倾斜,所以最后要使用LookAt函数修正,让相机正确地朝向角色

transform.RotateAround(focus.position, Vector3.up, anglex);
transform.RotateAround(focus.position, -transform.right, angley);
transform.LookAt(focus);      

限制转动视角

只需要限制视角的上下旋转。

设相机为C,角色为P,拿到一个待旋转角∠C'PC,计算  的夹角,也就是∠PCD,再间接计算出∠CPQ,最后再判断∠C'PC+∠CPQ是否超出限制的范围即可。

currentAngleY = 90 - Vector3.Angle(-RelativePosition, Vector3.down);            //计算两点连线与水平方向的夹角
if (currentAngleY - angley > MaximumDegree || currentAngleY - angley < MinimumDegree)angley = 0;

通过鼠标拖拽速度来旋转视角

思路

按下鼠标左键时,每一帧都获取鼠标的位置,通过两帧之间的鼠标位置之差除以两帧之间的时间,即可求得两帧之间的鼠标速度。

将鼠标速度作为视角旋转的依据,将鼠标速度转换为视角旋转的角度,转化比率可自己设定。

代码

    float mouseVelocityX;float mouseVelocityY;Vector3? point1;//旋转每度,在一帧中需要的速度int DragVelocityPerAngle = 170;void DragToRotateView_Velocity(){if (Input.GetMouseButton(0))                //按下鼠标左键的每一帧都执行{var point2 = Input.mousePosition;if (point1 != null){mouseVelocityX = -(point1.Value.x - point2.x) / Time.deltaTime;mouseVelocityY = -(point1.Value.y - point2.y) / Time.deltaTime;}point1 = point2;float anglex = mouseVelocityX / DragVelocityPerAngle;                   //将鼠标在屏幕上拖拽的速度转化为角度float angley = mouseVelocityY / DragVelocityPerAngle;currentAngleY = 90 - Vector3.Angle(-RelativePosition, Vector3.down);            //计算两点连线与水平方向的夹角if (currentAngleY - angley > MaximumDegree || currentAngleY - angley < MinimumDegree)angley = 0;transform.RotateAround(focus.position, Vector3.up, anglex);transform.RotateAround(focus.position, -transform.right, angley);transform.LookAt(focus);                    //如果没有这一句,摄像头转着转着就会歪RelativePosition = transform.position - focus.position;                 //更新相对位置}if(Input.GetMouseButtonUp(0))       //脱手瞬间{point1 = null;}}

基于速度的惯性旋转

实现方式

将惯性运动的初速度设定为鼠标左键松开时的鼠标移动速度,随后用协程实现

获取惯性运动的初速度

        if(Input.GetMouseButtonUp(0))       //脱手瞬间{point1 = null;inertialRotation = true;lastMouseVelocityX = mouseVelocityX;lastMouseVelocityY = mouseVelocityY;if (lastMouseVelocityX > maxlastMouseVelocityX) lastMouseVelocityX = maxlastMouseVelocityX;else if (lastMouseVelocityX < -maxlastMouseVelocityX) lastMouseVelocityX = -maxlastMouseVelocityX;if (lastMouseVelocityX > 0) isCounterClockwise = true;else if (lastMouseVelocityX < 0) isCounterClockwise = false;//print(lastMouseVelocityX);}if(inertialRotation==true)StartCoroutine("InertialRotation");     //通过协程来实现视角的惯性旋转,调用协程只有写在Update里并且在每一帧都被调用时才会继续执行

通过协程实现视角的惯性旋转

    bool inertialRotation = false;      //是否需要视角的惯性旋转float lastMouseVelocityX;           //脱手瞬间鼠标速度float lastMouseVelocityY;float maxlastMouseVelocityX = 3000; bool isCounterClockwise;            //旋转方向IEnumerator InertialRotation()      //在旋转末尾补上一个逐渐减缓的惯性旋转{yield return null;float anglex = lastMouseVelocityX / DragVelocityPerAngle;                   //将鼠标在屏幕上拖拽的速度转化为角度float angley = lastMouseVelocityY / DragVelocityPerAngle;currentAngleY = 90 - Vector3.Angle(-RelativePosition, Vector3.down);            //计算两点连线与水平方向的夹角if (currentAngleY - angley > MaximumDegree || currentAngleY - angley < MinimumDegree + 10)angley = 0;lastMouseVelocityX -= lastMouseVelocityX * 0.08f;lastMouseVelocityY -= lastMouseVelocityY * 0.08f;if ((isCounterClockwise && (anglex < 1))||!isCounterClockwise && (anglex > -1)){StopCoroutine("InertialRotation");inertialRotation = false;}    transform.RotateAround(focus.position, Vector3.up, anglex/3);transform.RotateAround(focus.position, -transform.right, Mathf.Abs(angley/25));transform.LookAt(focus);RelativePosition = transform.position - focus.position;}

通过鼠标拖拽距离来旋转视角

思路

按下鼠标左键时,每一帧都获取鼠标的位置。

将两帧之间的鼠标拖拽距离作为视角旋转的依据,将距离转换为视角旋转的角度,转化比率可自己设定。

代码

    Vector3 Point1;Vector3 Point2;//旋转每度,在一帧中需要拖拽的距离int DragDistancePerAngle = 20;void DragToRotateView_Distance(){if (Input.GetMouseButton(0))                //按下鼠标左键的每一帧都执行{Point2 = Input.mousePosition;float dx = Point2.x - Point1.x;float dy = Point2.y - Point1.y;float anglex = dx / DragDistancePerAngle;                   //将鼠标在屏幕上拖拽的距离转化为角度float angley = dy / DragDistancePerAngle;currentAngleY = 90 - Vector3.Angle(-RelativePosition, Vector3.down);                    //计算两点连线与水平方向的夹角if (currentAngleY - angley > MaximumDegree || currentAngleY - angley < MinimumDegree)angley = 0;transform.RotateAround(focus.position, Vector3.up, anglex);transform.RotateAround(focus.position, -transform.right, angley);transform.LookAt(focus);                    //如果没有这一句,摄像头转着转着就会歪RelativePosition = transform.position - focus.position;                 //更新相对位置Point1 = Point2;Point2 = Vector3.zero;}}

基于鼠标拖拽距离的惯性旋转

按下鼠标瞬间记录拖拽起点,松开鼠标瞬间记录拖拽终点

获取两帧之间的拖拽距离

        if (Input.GetMouseButtonDown(0))                //按下鼠标左键的瞬间,记录起始位置{Point1 = Input.mousePosition;StartPoint = Point1;}if(Input.GetMouseButtonUp(0)){EndPoint = Input.mousePosition;if (Point1!=EndPoint)                       //鼠标无速度则不进行惯性旋转inertialRotation = true;dragX = EndPoint.x - StartPoint.x;dragY = EndPoint.y - StartPoint.y;if (dragX > maxdragX) dragX = maxdragX;else if (dragX < -maxdragX) dragX = -maxdragX;if (dragX > 0) isCounterClockwise = true;else if (dragX < 0) isCounterClockwise = false;print(dragX);}if (inertialRotation == true)StartCoroutine("InertialRotation2");

通过协程实现视角的惯性旋转

Vector3 StartPoint;     //拖拽起点Vector3 EndPoint;       //拖拽终点float dragX;        //水平拖拽距离float dragY;        //垂直拖拽距离float maxdragX = 3000;float sactor = 10;  //惯性系数IEnumerator InertialRotation2()      //在旋转末尾补上一个逐渐减缓的惯性旋转{yield return null;float anglex = dragX / DragDistancePerAngle / sactor;                   //将鼠标在屏幕上拖拽的距离转化为角度float angley = dragY / DragDistancePerAngle / sactor;                   currentAngleY = 90 - Vector3.Angle(-RelativePosition, Vector3.down);            //计算两点连线与水平方向的夹角if (currentAngleY - angley > MaximumDegree || currentAngleY - angley < MinimumDegree + 10)angley = 0;dragX -= dragX * 0.05f;dragY -= dragY * 0.05f;print(dragX);if ((isCounterClockwise && (anglex < 1)) || !isCounterClockwise && (anglex > -1)){StopCoroutine("InertialRotation2");inertialRotation = false;}transform.RotateAround(focus.position, Vector3.up, anglex / 4);transform.RotateAround(focus.position, -transform.right, Mathf.Abs(angley/4));transform.LookAt(focus);RelativePosition = transform.position - focus.position;}

效果

完整代码

    /*-----------------调整视角------------------*///相机旋转方案public CameraRotateBy cameraRotateBy = CameraRotateBy.MouseVelocity;public enum CameraRotateBy{MouseVelocity,Distance,}//最小水平夹角public float MinimumDegree = 0;//最大水平夹角public float MaximumDegree = 60;//两点连线与水平方向的夹角float currentAngleY;/*方案一以两帧之间的鼠标移动速度为依据进行旋转*/float mouseVelocityX;float mouseVelocityY;Vector3? point1;//旋转每度,在一帧中需要的速度int DragVelocityPerAngle = 170;//脱手瞬间鼠标速度float lastMouseVelocityX;float lastMouseVelocityY;void DragToRotateView_Velocity(){if (Input.GetMouseButton(0))                //按下鼠标左键的每一帧都执行{var point2 = Input.mousePosition;if (point1 != null){mouseVelocityX = -(point1.Value.x - point2.x) / Time.deltaTime;mouseVelocityY = -(point1.Value.y - point2.y) / Time.deltaTime;}point1 = point2;float anglex = mouseVelocityX / DragVelocityPerAngle;                   //将鼠标在屏幕上拖拽的速度转化为角度float angley = mouseVelocityY / DragVelocityPerAngle;currentAngleY = 90 - Vector3.Angle(-RelativePosition, Vector3.down);            //计算两点连线与水平方向的夹角if (currentAngleY - angley > MaximumDegree || currentAngleY - angley < MinimumDegree)angley = 0;transform.RotateAround(focus.position, Vector3.up, anglex);transform.RotateAround(focus.position, -transform.right, angley);transform.LookAt(focus);                    //如果没有这一句,摄像头转着转着就会歪RelativePosition = transform.position - focus.position;                 //更新相对位置}if(Input.GetMouseButtonUp(0))       //脱手瞬间{point1 = null;inertialRotation = true;lastMouseVelocityX = mouseVelocityX;lastMouseVelocityY = mouseVelocityY;if (lastMouseVelocityX > maxlastMouseVelocityX) lastMouseVelocityX = maxlastMouseVelocityX;else if (lastMouseVelocityX < -maxlastMouseVelocityX) lastMouseVelocityX = -maxlastMouseVelocityX;if (lastMouseVelocityX > 0) isCounterClockwise = true;else if (lastMouseVelocityX < 0) isCounterClockwise = false;//print(lastMouseVelocityX);}if(inertialRotation==true)StartCoroutine("InertialRotation");     //通过协程来实现视角的惯性旋转,调用协程只有写在Update里并且在每一帧都被调用时才会继续执行}bool inertialRotation = false;      //是否需要视角的惯性旋转float maxlastMouseVelocityX = 3000; bool isCounterClockwise;            //旋转方向IEnumerator InertialRotation()      //在旋转末尾补上一个逐渐减缓的惯性旋转{yield return null;float anglex = lastMouseVelocityX / DragVelocityPerAngle;                   //将鼠标在屏幕上拖拽的速度转化为角度float angley = lastMouseVelocityY / DragVelocityPerAngle;currentAngleY = 90 - Vector3.Angle(-RelativePosition, Vector3.down);            //计算两点连线与水平方向的夹角if (currentAngleY - angley > MaximumDegree || currentAngleY - angley < MinimumDegree + 10)angley = 0;lastMouseVelocityX -= lastMouseVelocityX * 0.08f;lastMouseVelocityY -= lastMouseVelocityY * 0.08f;//print(lastMouseVelocityX);if ((isCounterClockwise && (anglex < 1))||!isCounterClockwise && (anglex > -1)){StopCoroutine("InertialRotation");inertialRotation = false;}    transform.RotateAround(focus.position, Vector3.up, anglex/3);transform.RotateAround(focus.position, -transform.right, Mathf.Abs(angley/25));transform.LookAt(focus);RelativePosition = transform.position - focus.position;}/*方案二以两帧之间的鼠标移动距离为依据进行旋转*/Vector3 Point1;Vector3 Point2;//旋转每度,在一帧中需要拖拽的距离int DragDistancePerAngle = 20;void DragToRotateView_Distance(){float v = Input.GetAxis("Vertical");float h = Input.GetAxis("Horizontal");if (!(h==0&&v==0))                  //不运动时的旋转灵敏度{DragDistancePerAngle = 17;      //松手前拖拽灵敏度sactor = 10;                    //松手后拖拽灵敏度}else                                //运动时的旋转灵敏度{DragDistancePerAngle = 8;sactor = 4;}if (Input.GetMouseButtonDown(0))                //按下鼠标左键的瞬间,记录起始位置{Point1 = Input.mousePosition;StartPoint = Point1;}if (Input.GetMouseButton(0))                //按下鼠标左键的每一帧都执行{Point2 = Input.mousePosition;float dx = Point2.x - Point1.x;float dy = Point2.y - Point1.y;float anglex = dx / DragDistancePerAngle;                   //将鼠标在屏幕上拖拽的距离转化为角度float angley = dy / DragDistancePerAngle;currentAngleY = 90 - Vector3.Angle(-RelativePosition, Vector3.down);                    //计算两点连线与水平方向的夹角if (currentAngleY - angley > MaximumDegree || currentAngleY - angley < MinimumDegree)angley = 0;transform.RotateAround(focus.position, Vector3.up, anglex);transform.RotateAround(focus.position, -transform.right, angley);transform.LookAt(focus);                    //如果没有这一句,摄像头转着转着就会歪RelativePosition = transform.position - focus.position;                 //更新相对位置Point1 = Point2;Point2 = Vector3.zero;}if(Input.GetMouseButtonUp(0)){EndPoint = Input.mousePosition;if (Point1!=EndPoint)                       //鼠标无速度则不进行惯性旋转inertialRotation = true;dragX = EndPoint.x - StartPoint.x;dragY = EndPoint.y - StartPoint.y;if (dragX > maxdragX) dragX = maxdragX;else if (dragX < -maxdragX) dragX = -maxdragX;if (dragX > 0) isCounterClockwise = true;else if (dragX < 0) isCounterClockwise = false;print(dragX);}if (inertialRotation == true)StartCoroutine("InertialRotation2");}Vector3 StartPoint;     //拖拽起点Vector3 EndPoint;       //拖拽终点float dragX;        //水平拖拽距离float dragY;        //垂直拖拽距离float maxdragX = 3000;float sactor = 10;  //惯性系数IEnumerator InertialRotation2()      //在旋转末尾补上一个逐渐减缓的惯性旋转{yield return null;float anglex = dragX / DragDistancePerAngle / sactor;                   //将鼠标在屏幕上拖拽的距离转化为角度float angley = dragY / DragDistancePerAngle / sactor;                   currentAngleY = 90 - Vector3.Angle(-RelativePosition, Vector3.down);            //计算两点连线与水平方向的夹角if (currentAngleY - angley > MaximumDegree || currentAngleY - angley < MinimumDegree + 10)angley = 0;dragX -= dragX * 0.05f;dragY -= dragY * 0.05f;print(dragX);if ((isCounterClockwise && (anglex < 1)) || !isCounterClockwise && (anglex > -1)){StopCoroutine("InertialRotation2");inertialRotation = false;}transform.RotateAround(focus.position, Vector3.up, anglex / 4);transform.RotateAround(focus.position, -transform.right, Mathf.Abs(angley/4));transform.LookAt(focus);RelativePosition = transform.position - focus.position;}

Unity 自由视角的惯性旋转相关推荐

  1. Unity 第三人称自由视角

    环绕相机控制脚本 该脚本需要挂载在环绕相机上,而环绕相机不绑定在角色身上,而是作为一个单独的存在 此外,由于一般来说,角色的原点都在脚底,所以需要特别在角色的中心位置放置一个空对象作为视野中心,并在面 ...

  2. Unity SKFramework框架(十七)、FreeCameraController 上帝视角/自由视角相机控制脚本

    目录 一.简介 二.功能 1.键盘控制平移 2.鼠标控制平移 3.视角拉近拉远 4.绕视角中心旋转 5.视角聚焦 6.活动区域限制 7.闲置时绕视角中心旋转 三.核心变量 一.简介 FreeCamer ...

  3. Unity3D 自由视角代码之解析

    效果:实现对物体的自由视角观察 本代码是<Unity3D游戏开发>一书中,7-11的例子,其中有几处注释是我个人的分析 using UnityEngine; using System.Co ...

  4. 优酷播放黑科技 | 自由视角技术的全链路策略与落地实践

    ​ 作者:李晓阳(苏铭) 在<优酷播放黑科技 | 自由视角技术体验优化实践>中我们提出对自由视角观影体验做了很多优化,为何需要做如此多的体验优化,下面将一一解答. 随着5G时代的到来,视频 ...

  5. 【Unity3D游戏开发学习笔记】(七)上帝之眼—第三人称摄像机的简单实现(跟随视角,自由视角)

    陆陆续续又开始更新自己的博客,看来自我驱动能力还是不够啊= =,废话不多说了,之前的内容大概说了一下Unity的一些基础知识,接下来我们将要对一些基本功能做一些学习.大家都知道,一个游戏,少不了摄像机 ...

  6. Unity物体围绕中中心旋转加角度

    Unity物体围绕中中心旋转加角度 ```csharp using System.Collections; using System.Collections.Generic; using UnityE ...

  7. 《这就是街舞》自由视角沉浸式体验黑科技

    <这!就是街舞>第四季大家看了吗?不知道有没有小伙伴跟笔者一样,"DNA"都要跟着舞动了起来.除了炸裂的舞台,堪比跨次元的真实观影体验,让用户在自由视角视频体验效果下身 ...

  8. 优酷播放黑科技 | 自由视角技术体验优化实践

    作者:邓小龙(白展) "本文为<优酷播放黑科技>系列文章第一篇<自由视角技术体验优化实践>,之后我们会陆续上线<基于WebRTC实现的直播"云多视角& ...

  9. 为ARVR黑科技:以“自由视角”360度尽展舞台唯美

    摘要:看华为的黑科技,如何用"自由视角"让观众感受舞台"风暴"的魅力所在. "风暴"降临 2021年1月9日晚上,我坐在电视机前,等待湖南卫 ...

  10. 64机位的自由视角体验,爱奇艺这次让你当“导播”

    左右滑动,想看哪个角度就看哪个角度--在第七期<爆裂舞台>中,THE9-陆柯燃的舞台中上演"爆裂时刻"自由视角.爱奇艺自由视角除了能把互动能力交给观众,让观众仿佛置身拍 ...

最新文章

  1. Jetty 基本使用样例
  2. java plugin 安装_eclipse maven plugin 插件 安装 和 配置
  3. file的open()和read()
  4. BLE 数据包格式解析
  5. python无法启动此程序因为计算机中丢失_python报错:无法启动此程序,因为计算机中丢失...
  6. nodejs在服务器上运行
  7. 依赖注入及AOP简述(六)——字符串请求模式 .
  8. 升级nginx,查看已经安装的模块,并隐藏或者修改版本号
  9. JeecgBoot 连接达梦数据库
  10. 试着开发chrome插件
  11. jQuery EasyUI 使用笔记
  12. axis wsdl2java_AXIS1.4 客户端 wsdl2java 使用方法
  13. 夜神模拟器使用过程遇到的问题
  14. 计算机两个活动分区,硬盘无法设置活动分区,硬盘只能有一个活动分区吗
  15. clip_gradient_norms()
  16. 解决阿里云端口不通 配置安全组无效
  17. 机器学习从入门到创业手记-2.算法与导师
  18. 带有en的单词有哪些_en押韵的词语
  19. rtems总体设计思路
  20. 雪花飘落代码java_JS实现的雪花飘落特效示例

热门文章

  1. 激荡三十年阅读笔记》
  2. swf播放器air android 版,网极SWF播放器(com.webgenie.swf.play) - 1.6.3 - 应用 - 酷安
  3. IMAGE_IMPORT_DESCRIPTOR
  4. java技术英文名词读音_Java开发,Java development,音标,读音,翻译,英文例句,英语词典...
  5. spring boot(五) 用户注册功能
  6. eclipse豆沙绿设置(一些其他的编辑器也变成豆沙绿)
  7. JAVAWEB-NOTE03
  8. 联通手机卡网速的修改
  9. 计算机学院陈冠华,生命科学学院2020年研究生学业奖学金(老生)获奖名单公示...
  10. 打开程序员心理B面,这些黑红话题他们亲自回应丨1024特辑