在实际的项目开发中,一般需要程序抽象出一些在几何意义上有明确意义的参数,这样方便策划或美术在自己的机器上进行调试。

  下面是一个可变参的地下城摄像机的简单实现:

// 第三人称摄像机,平移和旋转会同时进行平滑
public class ThirdPersonalCamera : MonoBehaviour
{/// Camera Control Paramspublic GameObject Target = null;public float Distance = 10f;public float RotateX = 0f;                                  // pitch 俯仰public float RotateY = 0f;                                  // yaw 偏航public float SmoothTime = 0.01f;                            // 平滑时间,默认为1spublic float ScrollWheelSpeed = 1000f;                      // 中轴调整速度public Vector3 TargetOffset = Vector3.zero;                 // 目标偏移量private Vector3 Velocity = Vector3.zero;                    // 平滑初速度private Vector3 Offset = Vector3.zero;                      // 根据上面三个变量计算出private const float MinDistance = 5f;                       // 镜头最近距离private const float MaxDistance = 100f;                     // 镜头最远距离void Start(){if (Target == null) return;}public void Shake(){StartCoroutine("ShakeCoroutine");}void LateUpdate(){if (Target == null) return;UpdateDistance();float radX = Mathf.Deg2Rad * RotateX;float radY = Mathf.Deg2Rad * RotateY;Offset.x = Distance * Mathf.Cos(radX) * Mathf.Cos(radY);Offset.z = Distance * Mathf.Cos(radX) * Mathf.Sin(radY);Offset.y = Distance * Mathf.Sin(radX);Vector3 targetPos = Target.transform.position + Offset + TargetOffset;transform.position = Vector3.SmoothDamp(transform.position, targetPos, ref Velocity, SmoothTime);transform.LookAt(Target.transform.position + TargetOffset);}private void UpdateDistance(){float horizontal = Input.GetAxis("Mouse ScrollWheel") * ScrollWheelSpeed * Time.deltaTime;Distance -= horizontal;}}

  可以看到抽象出的控制参数主要包括:摄像机分别绕X轴和Y轴的旋转、摄像机距离角色的距离、以及用来控制平滑时间的参数。

  注意,上面这段代码的实现中,position和rotation是同时进行平滑的,下面来看另外一种实现:

using UnityEngine;
using System.Collections;[ExecuteInEditMode]
public class MyDungeonCamera : MonoBehaviour
{/// [摄像机控制参数]public GameObject Target = null;public float RotateX = 0f;                                  // pitch 俯仰public float RotateY = 0f;                                  // yaw 偏航public float Distance = 10f;                                // 摄像机远近public float MoveSmoothTime = 0.3f;                         // 位置平滑时间,默认为1spublic float RotateSmoothTime = 0.3f;                       // 旋转平滑时间public float ScrollWheelSpeed = 1000f;                      // 中轴调整速度public Vector3 TargetOffset = Vector3.zero;                 // 目标偏移量private Vector3 Velocity = Vector3.zero;                    // 平滑初速度private Vector3 Offset = Vector3.zero;                      // 根据上面三个变量计算出private const float MinDistance = 5f;                       // 镜头最近距离private const float MaxDistance = 100f;                     // 镜头最远距离private Quaternion tmpRotation = Quaternion.identity;private Vector3 tmpPosition = Vector3.zero;private float RotateDamping{get{if (RotateSmoothTime <= 0f) RotateSmoothTime = 0.001f;return 1f / RotateSmoothTime;}}void LateUpdate(){if (Target == null) return;tmpRotation = transform.rotation;tmpPosition = transform.position;UpdateDistance();UpdateRotation();UpdatePosition();transform.rotation = tmpRotation;transform.position = tmpPosition;}private void UpdateRotation(){if (!NeedRotate()) return;Quaternion wantedRotation = Quaternion.Euler(RotateX, RotateY, 0f);// 旋转采用球形插值tmpRotation = Quaternion.Slerp(tmpRotation, wantedRotation, Time.deltaTime * RotateDamping);}private void UpdatePosition(){// 如果有旋转插值,则位置根据旋转变换;否则,位置自己进行插值过渡if (!NeedRotate()){Offset = Quaternion.Euler(RotateX, RotateY, 0f) * Vector3.forward * Distance;Vector3 wantedPos = Target.transform.position - Offset + TargetOffset;// 位置采用平滑阻尼过渡tmpPosition = Vector3.SmoothDamp(tmpPosition, wantedPos, ref Velocity, MoveSmoothTime);}else{Offset = tmpRotation * Vector3.forward * Distance;tmpPosition = Target.transform.position - Offset + TargetOffset;}}private void UpdateDistance(){float horizontal = Input.GetAxis("Mouse ScrollWheel") * ScrollWheelSpeed * Time.deltaTime;Distance -= horizontal;Distance = Mathf.Clamp(Distance, MinDistance, MaxDistance);}private bool NeedRotate(){Vector3 eulerAngles = transform.rotation.eulerAngles;return !(FloatEqual(eulerAngles.x, RotateX) && FloatEqual(eulerAngles.y, RotateY));}public static bool FloatEqual(float value1, float value2){float ret = value1 - value2;return ret > -0.0005f && ret < 0.0005f;}}

  这个实现中,有几点需要注意的:

  (1)rotation使用四元素球形插值,这样保证每次旋转的角速度是恒定的,不过两次旋转各自的角速度不相等,这里可以改进;

  (2)position使用Vector3.SmoothDamp进行平滑阻尼过渡效果会比较好;

  (3)浮点数相等判断,不要直接用等号哟;

  (4)当同时有rotation和position时,以rotation为主;

  (5)是否需要旋转的判断,只有需要的时候才走旋转逻辑,这样可以减轻Update的压力。

  摄像机振动脚本:

public class ShakeCamera : MonoBehaviour
{public float ShakeTime = 1f;public float ShakeStrength = 0.2f;private Vector3 ShakeOffset = Vector3.zero;private Vector3 preShakeOffset = Vector3.zero;void LateUpdate(){transform.position = transform.position - preShakeOffset + ShakeOffset;}public void Shake(){StopCoroutine("ShakeCoroutine");StartCoroutine("ShakeCoroutine");}public void Shake(float time){ShakeTime = time;Shake();}IEnumerator ShakeCoroutine(){float endTime = Time.time + ShakeTime;while (Time.time < endTime){ShakeOffset = Random.insideUnitSphere * ShakeStrength;yield return null;}ShakeOffset = Vector3.zero;}}

转载于:https://www.cnblogs.com/sifenkesi/p/3994594.html

各种Camera,总有一款适合你(二)相关推荐

  1. html5的在线播放页面,整理5款html5网页播放器,总有一款适合你吧

    整理了5款html5网页播放器,总有一款适合你吧. 酷播云HTML5倍速功能视频播放器 介绍: 重要提示:本播放器为酷播云在线产品,用户可以免费注册使用,下载包仅提供代码使用示例及演示,并非播放器的下 ...

  2. PMCAFF出品|十一月30篇爆款文章合集,干货、技能、内涵齐飞,总有一款适合你

    十一月虽然天寒地冻,但却是PMCAFF社区原创文章丰收的一个月,十一月社区共产生了617原创文章.在小编比较懒.今天雾霾中毒等各种客观因素影响下,共筛选出30篇人气爆棚的文章,产品干货.运营技巧.设计 ...

  3. 2个recordset合并_史上最全!8种办法玩转Excel文字合并,总有一款适合你!

    本文作者丨 wayy - Excel 研究院 本文由「秋叶 Excel」原创发布 如需转载,请在公众号发送关键词「转载」查看说明 在日常工作过程中, 我们经常会遇到要把一串文字拼接到一起的情况. 你还 ...

  4. 手机相机里面的m_2020拍立得相机选购指南 富士乐魔徕卡推荐 总有一款适合你...

    在数字化的时代,拍立得,这种方便快捷又自带怀旧感觉的即时成像相机却成了许多人的心头好.相比起手机单反,拍立得相机「一拍立得」的特点让很多人对它情有独钟.按下快门,等待相纸显影,再做成「照片墙」.「成长 ...

  5. Visual Studio开发工具(5):VS2010 精美壁纸,总有一款适合你!

    下载地址:VS2010 精美壁纸,总有一款适合你! 最新收集的VS2010 精美壁纸,分享给大家,喜欢的朋友可以下载作为桌面!你可以到博客的相册里下载,也可以右键查看图片属性,拷贝URL,放IE里,下 ...

  6. MapperException: 无法获取实体类xxxxx对应的表名! 三种解决方法,总有一款适合你。

    MapperException: 无法获取实体类xxxxx对应的表名! 三种解决方法,总有一款适合你. 参考文章: (1)MapperException: 无法获取实体类xxxxx对应的表名! 三种解 ...

  7. 昊鼎王五:高级运维工程师的成长之路,总有一款适合你^_^

    #昊鼎王五:高级运维工程师的成长之路,总有一款适合你_ 本文关键词: 成长为高级运维工程师的打怪升级之路 本篇参考zhenliang同学的文章,一个从事多年运维的牛人,文章写的很好,人非常nice. ...

  8. python持续集成工具_21 个好用的持续集成工具,总有一款适合你

    原标题:21 个好用的持续集成工具,总有一款适合你 市场上持续集成工具众多,找到一个合适的工具并非易事,下面介绍了 21 个比较受欢迎的 CI 工具,并附上了下载链接. 1. Buddy 对 Web ...

  9. 分享75个JS特效倒计时,总有一款适合您

    分享75个JS特效倒计时,总有一款适合您 75个JS特效倒计时下载链接:https://pan.baidu.com/s/1SntVvt85nhN3JgqcsTFY6Q?pwd=q27q  提取码:q2 ...

  10. 益银达-分享10个在家就能赚钱的副业推荐,总有一款适合你

    副业是现代人的刚需,社畜的我们,很多人背着债,迫切需要一份可以赚到钱的副业. 今天就把自己实操过,觉得比较靠谱的10种副业整理出来,希望能对有需要的小伙伴多一些路子的选择,强烈建议大家先收藏,总有一款 ...

最新文章

  1. 算法时间复杂度lg是多少_算法时间复杂度空间复杂度(附github)
  2. 将自己可能存放库文件的路径都加入到/etc/ld.so.conf中是明智的选择
  3. 784. Letter Case Permutation
  4. 为C++程序添加文件保存加载功能
  5. MySQL(23)--- 正则表达式
  6. 【clickhouse】ClickHouse之DBA运维宝典
  7. 设备 esp32_「ESP 教程」ESP32 如何运行 TensorFlow 模型
  8. 既然现在处理器性能过剩,为什么PC用起来不流畅?
  9. 系统优化的方法有哪些
  10. 一文搞懂如何高效学习与进阶NLP or CV!
  11. jdbc连接数据库mysql视频_jdbc连接数据库mysql视频
  12. linux 分区100g整数,硬盘分区 整G 整数 法(从1g到200g最精确的整数分区)(转)...
  13. 华为手机怎样恢复Android,华为手机恢复出厂设置的教程和方法
  14. c语言 long int最大数,long整型的最大值跟处理器位数有关
  15. Java中的回溯算法
  16. springCloud报错No instances available
  17. 网络通信,IP地址, 端口,socket
  18. 转铁蛋白(Tf)修饰去氢骆驼蓬碱磁纳米脂质体/香豆素-6脂质体/多柔比星脂质体
  19. Verilog HDL三种描述方式
  20. 2023年“科学探索奖”申报启动及指南

热门文章

  1. How to run a estimaton
  2. what do we want for advertiesement
  3. formal method里面的并发问题
  4. 外国人看来也喜欢拜年
  5. CDE桌面环境中自动启动应用程序图形界面
  6. Centos7安装防火墙firewall
  7. 私有云存储搭建(owncloud)
  8. Java容器源码分析-HashSet vs TreeSet vs LinkedHashSet
  9. 《Photoshop修饰与合成专业技法》—第1章利用图层样式改进抠像
  10. 详解在 Linux 启动时,如何自动执行命令或脚本