Unity笔记-29-ARPG游戏项目-01-第三人称相机

相机观测实现

核心思路

通过YawPitch轴控制相机旋转

    private Vector3 myDafaultDir;//默认方向[SerializeField]public Vector3 myCurrentDir;//当前方向private Transform myPlayerTransform;//玩家Transformprivate Vector3 myRotateValue;//控制器存储旋转值private Vector3 myPitchRotateAxis;//俯仰方向旋转轴private Vector3 myYawRotateAxis;//左右横向方向旋转轴[Header("相机观测距离")]public float distance = 4f;//相机观测距离[Header("相机观测距离限制")]public Vector2 distanceLimit = new Vector2(1f, 4f);[Header("相机旋转速度")]public float moveSpeed = 120f;//相机旋转速度[Header("观测目标偏移量")]public Vector3 offset = new Vector3(0f,1.5f,0f);//观测目标偏移量[Header("视距调整速度")][Range(0,1)]public float stadiaAdjustmentSpeed;[Header("pitch反转")]public bool invertPitch=true;//反转pitch方向相机滑动[Header("pitch角度限制")]public Vector2 pitchLimit = new Vector2(-40f, 70f);//pitch方向角度约束
    private void OnEnable(){myCurrentDir = myDafaultDir;myCurrentDistance = distance;//世界坐标系:y轴方向Vector3 upAxis = -Physics.gravity.normalized;//找到玩家TransformmyPlayerTransform = GameObject.FindGameObjectWithTag(GameConst.PLAYER).transform;//通过摄像机与玩家的方向向量投影在地面上的单位向量-获得初始方向//地面使用地面的法向量myDafaultDir = Vector3.ProjectOnPlane((transform.position-myPlayerTransform.position),upAxis).normalized;//横向旋转轴myYawRotateAxis = upAxis;//俯仰旋转轴,使用摄像机朝向与世界y轴方向的叉积得到myPitchRotateAxis = Vector3.Cross(upAxis, Vector3.ProjectOnPlane(transform.forward, upAxis));}

初始化操作

upAxis:通过物理重力轴获得世界y轴朝向,作为世界地面的法向量,后续用于投影;

myPlayerTransform:通过标签获得观测对象Transform

myDafaultDir:默认方向,通过由角色指向摄像机方向向量于地面上的投影的单位向量表示

Yas&Pitch:前者为世界y轴,后者为摄像机朝向与地面上的投影向量和世界y轴的叉积向量,相机观测仅需要这两个自由度,无需Roll

myRotateValue:作为旋转量的临时存储容器

Update实现

通过虚拟轴输入

Vector2 inputDelta = new Vector2(Input.GetAxis(GameConst.MOUSEX_AXIS),Input.GetAxis(GameConst.MOUSEY_AXIS));

更新旋转值

            //更新横向旋转值myRotateValue.x += inputDelta.x * moveSpeed * Time.smoothDeltaTime;myRotateValue.x = AngleCorrection(myRotateValue.x);//更新纵向旋转值#region 俯仰角度约束myRotateValue.y += inputDelta.y * moveSpeed * (invertPitch ? -1 : 1) * Time.smoothDeltaTime;myRotateValue.y = AngleCorrection(myRotateValue.y);myRotateValue.y = Mathf.Clamp(myRotateValue.y, pitchLimit.x, pitchLimit.y);#endregion

存储临时旋转值——>欧拉角修正——>俯仰角限制

不断叠加输入的旋转值到旋转值临时存储容器里,通过欧拉角修正,把角度控制在0-360度

叠加四元数旋转

//构建角轴四元数,通过四元数方法:AngleAxis(角度,旋转轴)获得角轴旋转Quaternion horizontalQuat = Quaternion.AngleAxis(myRotateValue.x, myYawRotateAxis);//横向Quaternion verticalQuat = Quaternion.AngleAxis(myRotateValue.y, myPitchRotateAxis);//俯仰//注:第三人称控制只需要两个自由度,不需要RollVector3 finalDir = horizontalQuat * verticalQuat * myDafaultDir;//叠加四元数旋转获得最终方向myCurrentDir = finalDir;

将旋转容器里的旋转值通过四元数角轴获得对应轴体四元数(旋转),将旋转叠加给默认方向,即可获得当前方向

            //Vector3 from = myPlayerTransform.TransformPoint(offset);//获得偏移后的伪相机位置Vector3 from = myPlayerTransform.localToWorldMatrix.MultiplyPoint3x4(offset);//获得偏移后的伪相机位置Vector3 to = from + finalDir * distance;//添加观测距离后的相机最终位置

通过角色局部坐标转化,获得偏移的伪相机坐标,将伪相机坐标叠加观测距离后即可后的相机的最终坐标,

叠加观测距离:把相机从伪相机坐标朝着最终方向位移观测距离即伪相机的最终位置

transform.LookAt(from);

最终调整摄像机朝向,让摄像机看向伪相机坐标,也就是角色偏移的观测位置;

相机与墙体

穿模修正

    private Vector3 ObstacleProcess(Vector3 from,Vector3 to){//获得从伪相机位置到相机最终位置的方向向量Vector3 dir = (to - from).normalized;//检查最初位置是否会检测到障碍物,若检测到则报错//if (Physics.CheckSphere(from, obstacleSphereRadius, obstacleLayerMask))//    Debug.Log("错误!障碍物检测球体半径应小于角色胶囊");RaycastHit hit = default;//使用圆形检测是否有障碍物,如果有则将射线检测位置的负方向圆形半径位置赋值if(Physics.SphereCast(new Ray(from,dir),obstacleSphereRadius,out hit, distance, obstacleLayerMask)){return hit.point + (-dir * obstacleSphereRadius);}return to;}

核心思想

获取伪相机位置from,以及相机本来的最终位置to

计算由from射向to的单位方向向量dir,从from发射朝向dir的球体射线检测是否存在物体,如果检测到物体,那么则返回检测点加上负dir方向乘以球体半径的位置,作为真正的最终位置,

相机位置插值恢复

在因为碰撞体导致摄像机距离被拉近后,当视角拉到无碰撞体的位置,相机位置会恢复,但是不能立刻恢复,否则感觉十分突兀,需要通过插值平滑过渡

   private void CameraMoveDelay(Vector3 from, Vector3 to){//临时位置存储Vector3 exceptTo = ObstacleProcess(from, to);//获取移动距离float expectDistance = Vector3.Distance(exceptTo, from);if (expectDistance < myCurrentDistance)//如果拉近,则重置延迟{//拉近瞬时拉近myCurrentDistance = expectDistance;myDistanceRecoveryDelayCounter = distanceRecoveryDelay;}else//如果为拉远,延迟一段时间逐渐拉远{if (myDistanceRecoveryDelayCounter > 0)myDistanceRecoveryDelayCounter -= Time.deltaTime;elsemyCurrentDistance = Mathf.Lerp(myCurrentDistance, expectDistance, Time.smoothDeltaTime * distanceRecoverySpeed);}}

相机延迟恢复,首先使用穿模修正获得真正的相机位置,然后计算真正位置与伪相机位置的距离,判断当前十分需要拉近操作,如果小于当前距离,那么则将距离存储给当前距离,并重置拉远延迟计数器;否则,即为拉远距离,通过计数器延迟拉远,并通过插值平滑拉远速度

Update实现补充

            //省略前部分代码Vector3 finalDir = horizontalQuat * verticalQuat * myDafaultDir;//叠加四元数旋转获得最终方向myCurrentDir = finalDir;//Vector3 from = myPlayerTransform.TransformPoint(offset);//获得偏移后的伪相机位置Vector3 from = myPlayerTransform.localToWorldMatrix.MultiplyPoint3x4(offset);//获得偏移后的伪相机位置Vector3 to = from + finalDir * distance;//添加观测距离后的相机最终位置
//在此处添加插值恢复检测即可CameraMoveDelay(from, to);transform.position = from + finalDir * myCurrentDistance;transform.LookAt(from);#endregion

欧拉角修正

    private float AngleCorrection(float value){float angle = value - 180;if (angle > 0){return angle - 180;}if (value == 0) return 0;return value;}

Unity笔记-29-ARPG游戏项目-01-第三人称相机相关推荐

  1. 使用three.js实现跟随模型的第一人称、第三人称相机控制

    最近在我原有的"室内场景demo"的基础上做了一个跟随模型的第三人称相机控制,以键盘wasd控制模型的行走,以鼠标控制模型的朝向. 在线预览地址​​​​​​​ CSDN下载地址ht ...

  2. Unity2020.3.19f1 简单的第三人称相机跟随

    参考书籍:Unity3D动作游戏开发实战 常规第三人称相机是指相机在玩家身后以一定距离看向玩家,相机位置可受到鼠标移动或者手柄摇杆操作的控制而左右上下旋转. using System.Collecti ...

  3. Unity学习笔记(一):第三人称镜头和人物移动

    凭借一腔热情,想着大学做点什么事,就想着做个游戏出来.之前没有接触过unity等各类引擎,学习了一段时间发现有许多地方挺复杂的,开个专栏记录一下学到的东西. 基本目标是做一个RPG式的游戏,涉及的东西 ...

  4. [Unity] GameFramework 学习记录 4:第三人称控制器

    我想知道 UEntity 数据表中的编号跟每个实体表自己的编号之间是否需要统一,现在看来好像不需要统一,但是我也不知道是不是因为我还没看到这两个表有交互的时候 哦我才注意到,这个实体表是用来定义资源的 ...

  5. 虚幻引擎图文笔记:官方模板中第三人称角色(ThirdPersonCharacter)的构成图解

    本文图解一下官方第三人称游戏模板中角色控制器的构成,以方便学习和扩展. 文章目录 蓝图类 EventGraph 组件构成 Mesh:USkeletalMesh组件 ThirdPerson_AnimBP ...

  6. webgl 第三人称相机

    发现自己越来越懒了...基础的我不写了,有很多博客都写了,连w3c都有,瞬间没有心思写下去了,并且也很忙:每天都在研究:别骂我...真心没心思:我会考虑写一些难度大点的,这样有动力点:代码如下: 看下 ...

  7. Unity 3D第三人称视角、用途广泛限定角度(视角不能360度翻转)

    Unity第三人称相机视角控制 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人! (拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心 ...

  8. Unity第三人称控制实现方式

    第三人称移动,主要两个部分,一是人物,二是相机. 先说人物,unity其实提供了一个CharacteController组件可以方便地用于控制人物移动,但是这个组件会与刚体冲突.如果使用Charact ...

  9. Unity制作第三人称射击游戏-成为创新游戏开发者学习教程

    用Unity游戏引擎学习和制作第三人称射击游戏-成为创新游戏开发者- TPS战地克隆 你会学到什么 Unity 3D游戏开发 如何打造TPP第三人称射击游戏 第三人控制者 第三人称动画 第三人运动控制 ...

  10. Unity第三人称射击游戏的相机控制

    (关于其他几种角色移动的控制在我之前的博客有写到) 首先我们需要先理解一下第三人称相机控制的原理: 我们要实现的效果就是:获取鼠标的移动输入,转化成角色以及相机的旋转,通过鼠标输入Input.GetA ...

最新文章

  1. C#机房重构-总结(三)
  2. python十七:高阶函数
  3. 策略模式与简单工厂模式区别(转)
  4. 顺利通过2018年下工信部的软件设计师考试,在此感悟一下
  5. mysql json函数_Mysql里的JSON系列操作函数
  6. Nginx编译./configure翻译
  7. linux中求当前时间gettime,linux – 你如何在shell中获得clock_gettime(2)时钟?
  8. Matlab无约束优化
  9. 17款现代风格的免费英文字体,分享给设计师们
  10. 电脑android模拟器哪个好用,安卓模拟器哪个好用
  11. 四川金弘同创:拼多多产品要怎么上新
  12. background,background-size背景图片和盒子模型
  13. 手机投屏到电脑的实用工具
  14. 文献阅读笔记(2022.11.14)
  15. DDoS防御的8种方针详解
  16. GPIO之推挽输出和开漏输出
  17. 富芮坤FR8008A II2C驱动之AW9523B
  18. terraform笔记
  19. java 发票打印_Java发票打印CommPortIdentifier与无符号字节的问题
  20. 前端使用CryptoJS的AES解密,Java后端加密实现

热门文章

  1. 【Matlab】变分法求控制器(无约束)
  2. VisionMobile:Apple和三星利润的秘诀
  3. 内外网隔离--网络准入控制系统有什么功能
  4. c/c++游戏编程之Easyx图形库基础
  5. java+poodle漏洞修复_如何修复 POODLE SSLv3 安全漏洞 (CVE-2014-3566)
  6. numpy中如何判断一个值是否为masked
  7. 人工智能研究中心快递柜——代码分析十三
  8. !HDU 4311 最小曼哈顿距离-思维卡时间-(横纵坐标分开算,排序)
  9. 用Python3在牛客网acm模式刷题怎么输入输出
  10. office修复找不到msi_Microsoft Office安装程序找不到ProPlus.WW\ProPlusWW.msi