配置方法

创建一个空对象挂载相机控制脚本(在代码中让该对象与角色的位置重合),相机作为其子物体

将相机相对于父物体的距离设定为理想的 相机-人物 距离

指定环绕中心和相机

原理

想要实现环绕,首先就需要获取环绕点和相机的Transform属性。

想要表示相机相对于环绕点的方位,你可能会觉得使用相对位置描述更为方便,其实不然,实际上使用两个欧拉角来描述比使用位置描述更为方便,因为我们后面需要对相机的旋转过程插值,使用位置来描述显然是不便于插值的。

这样,我们就有了相机相对于环绕点的角度,加上距离就可以精确描述相机的位置了。

线性插值

如果要对一个变量进行插值,首先要明确插值的实现。什么是线性插值?

给定两个数,a、b,对a、b进行一次线性插值,再给一个参数t,代表插值的位置。

比如对0、1插值,参数为0.1,那么进行一次插值得到的结果就是0.1。

线性插值的公式是 a + (b-a) * t 。

那么插值有哪些实际应用呢?

- 平滑运动中的相机与角色的距离

- 平滑旋转中的相机与角色的角度,并实现一定时长的惯性旋转效果。

为什么插值会产生延时呢?

因为插值有两个数,一个是当前值,一个是目标值,另外还有一个参数是百分比。

当目标值不再变化之后,当前值逼近目标值需要一定的时间。

两个数之间的差距随着时间的变化曲线,类似于一个方向向下的抛物线。

周围障碍检测

对角色前后左右四个方向进行射线检测,获取返回的距离,取得一个最小值。

如果想要更精确的结果,可以将正交的方向向量分别两两相加,得到四个斜的方向向量,这样就可以做八个方向的距离检测。

相机被遮挡处理

如果相机被遮挡,就将相机距离调整到小于 距离角色水平方向最近的障碍距离 。

在手动调整距离时,记录偏好距离。

如果不再被遮挡,就恢复偏好距离。

代码

using UnityEngine;
using System.Collections;
using UnityEngine.Animations;public class OrbitCamera : MonoBehaviour
{public Transform pivot;public Transform camera;private float distance;public bool distanceAdjustable = true;public bool rotationAdjustable = true;void Start(){targetSideRotation = transform.eulerAngles.y;currentSideRotation = transform.eulerAngles.y;targetUpRotation = transform.eulerAngles.x;currentUpRotation = transform.eulerAngles.x;distance = -camera.localPosition.z;             //相机局部坐标z值为-1.8,那么相机与距离人物为1.8}void LateUpdate(){if (!pivot) return;Follow();DragRotate();ScrollScale();OcclusionJudge();}void Follow(){if (!pivot.gameObject.GetComponentInParent<ParentConstraint>()){transform.position = Vector3.Lerp(transform.position, pivot.position, Time.deltaTime * 5);             //相机跟随角色的插值,相机当前帧的实际位置为它们中间10%的位置camera.localPosition = -Vector3.forward * distance;                                                     //仅z有值,并且方向为负}else       //高速运动下不再插值{transform.position = pivot.position;camera.localPosition = -Vector3.forward * distance;}}public float MinimumDegree = 0;public float MaximumDegree = 60;private float targetSideRotation;private float targetUpRotation;private float currentSideRotation;private float currentUpRotation;void DragRotate(){if (!rotationAdjustable) return;if (Input.GetMouseButton(0)){targetSideRotation += Input.GetAxis("Mouse X") * 5;targetUpRotation -= Input.GetAxis("Mouse Y") * 5;}targetUpRotation = Mathf.Clamp(targetUpRotation, MinimumDegree, MaximumDegree);currentSideRotation = Mathf.LerpAngle(currentSideRotation, targetSideRotation, Time.deltaTime * 5);currentUpRotation = Mathf.Lerp(currentUpRotation, targetUpRotation, Time.deltaTime * 5);transform.rotation = Quaternion.Euler(currentUpRotation, currentSideRotation, 0);}float MinimumDistance = 1;float MaximumDistance = 4;void ScrollScale(){if (!distanceAdjustable) return;distance *= (1 - Input.GetAxis("Mouse ScrollWheel") * 0.2f);        //在原值的基础上调整为原值的百分比distance = Mathf.Clamp(distance, MinimumDistance, MaximumDistance);if(Input.GetAxis("Mouse ScrollWheel")!=0)preferdDistance = distance;}float preferdDistance = 1;bool resumable = false;void OcclusionJudge(){if (Physics.Raycast(pivot.position, -camera.forward, distance))               {resumable = true;distance = NearestObstacleDistance(pivot);while (Physics.Raycast(pivot.position, -camera.forward, distance) && distance > MinimumDistance){distance *= 0.99f;distance = Mathf.Clamp(distance, MinimumDistance, MaximumDistance);float dist = Mathf.Lerp(-camera.transform.localPosition.z, distance, 1f);camera.localPosition = -Vector3.forward * dist;}}if (!resumable) return;if (resumable && !Physics.Raycast(pivot.position, -camera.forward, preferdDistance)){distance = preferdDistance;float dist = Mathf.Lerp(-camera.transform.localPosition.z, distance, 1f);camera.localPosition = -Vector3.forward * distance;resumable = false;}}float NearestObstacleDistance(Transform start){float dis = float.MaxValue;RaycastHit hit;Physics.Raycast(start.position, start.forward, out hit);if(hit.distance!=0) dis = Mathf.Min(dis, hit.distance);Physics.Raycast(start.position, -start.forward, out hit);if (hit.distance != 0) dis = Mathf.Min(dis, hit.distance);Physics.Raycast(start.position, start.right, out hit);if (hit.distance != 0) dis = Mathf.Min(dis, hit.distance);Physics.Raycast(start.position, -start.right, out hit);if (hit.distance != 0) dis = Mathf.Min(dis, hit.distance);return dis;}
}

效果就不演示了,比之前写的那个要好不少

Unity 一种更为简洁明了的环绕相机方案相关推荐

  1. Unity三种物体溶解方法

    Unity三种物体溶解方法 @[TOC](Unity三种物体溶解方法 效果展示 1. 利用Noise纹理进行溶解 shader要点 shader代码 2. 屏幕空间棋盘格 shader要点 shade ...

  2. 一种更为高效的WAL的实现方式

    文章目录 前言 高效WAL的实现方式 高效WAL实现过程图 前言 在分布式存储系统的服务一致性实现中,WAL是其中经常被使用到的一个关键的数据文件.它可以有效地记录每一次的系统变更记录,而且还能够确保 ...

  3. 一种基于OpenCV的三维重建实现方案

    一种基于OpenCV的三维重建实现方案 来源:淘金者论文范文 作者:Www.TaoJz.Com 日期:08/30/09 摘 要 本文以计算机视觉三维重建技术为研究对象,分析了开放计算机视觉函数库Ope ...

  4. 三维重建:深度相机方案对比-KinectFusion的基本原理(尺度)

    KinectFusion算法原理依据2011年发表的Fusion重建的论文,主要重建方法为TSDF算法,并在GitHub上开源了相关代码,可以直接编译使用.Github: https://github ...

  5. 3D视觉之深度相机方案

    随着机器视觉,自动驾驶等颠覆性的技术逐步发展,采用 3D 相机进行物体识别,行为识别,场景 建模的相关应用越来越多,可以说 3D 相机就是终端和机器人的眼睛. 3D 相机 3D 相机又称之为深度相机, ...

  6. AI中台:一种敏捷的智能业务支持方案|宜信技术学院沙龙分享实录

    内容来源:宜信技术学院第1期技术沙龙-线上直播|AI中台:一种敏捷的智能业务支持方案 主讲人介绍:井玉欣 宜信技术研发中心AI应用团队负责人 本文字数:13479字 阅读用时:34分钟 导读:随着&q ...

  7. 从数据中台到AI中台:一种敏捷的智能业务支持方案( 附视频讲解) | 技术头条...

    点击上方↑↑↑蓝字关注我们~ 「2019 Python开发者日」全日程揭晓,请扫码咨询 ↑↑↑ 来源 | 宜信技术学院第1期技术沙龙-线上直播 原标题为:AI中台:一种敏捷的智能业务支持方案 导读:随 ...

  8. 全景也要更清晰,基于RK3588核心板的8K全景相机方案【飞凌嵌入式】

    内容来源:飞凌嵌入式官网 www.forlinx.com 伴随着虚拟现实技术(简称VR)的热潮,VR全景影像开始兴起,全景相机市场也迎来了高速发展.近年来,360°全景相机几乎成为了数码潮人和vlog ...

  9. 浅谈几种区块链网络攻击以及防御方案之其它网络攻击

    旧博文,搬到 csdn 原文:http://rebootcat.com/2020/04/16/network_attack_of_blockchain_other_attack/ 写在前面的话 自比特 ...

  10. 浅谈几种区块链网络攻击以及防御方案之拒绝服务攻击

    旧博文,搬到 csdn 原文:http://rebootcat.com/2020/04/14/network_attack_of_blockchain_ddos_attack/ 写在前面的话 自比特币 ...

最新文章

  1. Flash和JavaScript通信
  2. [Python学习] 专题五.列表基础知识 二维list排序、获取下标和处理txt文本实例
  3. pageadminCMS.Net Framework的安装教程
  4. 基于Spring Boot的“课程设计”的设计与实现
  5. 学Android的学习规划
  6. Java程序员从笨鸟到菜鸟之(一百零四)java操作office和pdf文件(二)利用POI实现数据导出excel报表...
  7. [UE4]单机游戏改网络游戏,不完全清单
  8. 用C#编写一个抓网页的应用程序
  9. 图片预览(适用于IE6,9,10,Firefox)
  10. Squid优化完全手册(2)
  11. 不可能解开的谜题 (程序员修炼之道,评注者序)
  12. Python-Cartopy制图学习01-中国区域SPEI空间制图
  13. 【教程】鼠标右键新建添加RTF文档
  14. oracle复合结构,动名词的复合结构作宾语
  15. 点成分享 | 探索生物学中的电泳
  16. 在PHP中用sleep导致诡异事件
  17. 大一计算机课如何做表格,电脑做表格的基本操作教程
  18. omv安装mysql插件_Openmediavault第三方插件安装教程
  19. java毕业设计软件源代码SSM酒店管理系统|旅店管理
  20. IOS appstore 发布

热门文章

  1. Python随记(27)bs4爬取豆瓣250
  2. 【题解】UVA177 分治
  3. SARscape之DInSAR处理(双轨法)
  4. 一元钱一瓶汽水,喝完后两个空瓶能换一瓶汽水,问:你有20元钱,可以喝到几瓶汽水?
  5. stress模拟CPU使用100%
  6. 服务器共享文件夹给广域网,广域网文件共享服务器
  7. c语言数据结构与算法参考文献,数据结构论文参考文献
  8. HHL论文及代码理解(Generalizing A Person Retrieval Model Hetero- and Homogeneously ECCV 2018)...
  9. Ffmpeg视频压制的基础知识
  10. pixel 3 Top Shot