Unity 一种更为简洁明了的环绕相机方案
配置方法
创建一个空对象挂载相机控制脚本(在代码中让该对象与角色的位置重合),相机作为其子物体
将相机相对于父物体的距离设定为理想的 相机-人物 距离
指定环绕中心和相机
原理
想要实现环绕,首先就需要获取环绕点和相机的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 一种更为简洁明了的环绕相机方案相关推荐
- Unity三种物体溶解方法
Unity三种物体溶解方法 @[TOC](Unity三种物体溶解方法 效果展示 1. 利用Noise纹理进行溶解 shader要点 shader代码 2. 屏幕空间棋盘格 shader要点 shade ...
- 一种更为高效的WAL的实现方式
文章目录 前言 高效WAL的实现方式 高效WAL实现过程图 前言 在分布式存储系统的服务一致性实现中,WAL是其中经常被使用到的一个关键的数据文件.它可以有效地记录每一次的系统变更记录,而且还能够确保 ...
- 一种基于OpenCV的三维重建实现方案
一种基于OpenCV的三维重建实现方案 来源:淘金者论文范文 作者:Www.TaoJz.Com 日期:08/30/09 摘 要 本文以计算机视觉三维重建技术为研究对象,分析了开放计算机视觉函数库Ope ...
- 三维重建:深度相机方案对比-KinectFusion的基本原理(尺度)
KinectFusion算法原理依据2011年发表的Fusion重建的论文,主要重建方法为TSDF算法,并在GitHub上开源了相关代码,可以直接编译使用.Github: https://github ...
- 3D视觉之深度相机方案
随着机器视觉,自动驾驶等颠覆性的技术逐步发展,采用 3D 相机进行物体识别,行为识别,场景 建模的相关应用越来越多,可以说 3D 相机就是终端和机器人的眼睛. 3D 相机 3D 相机又称之为深度相机, ...
- AI中台:一种敏捷的智能业务支持方案|宜信技术学院沙龙分享实录
内容来源:宜信技术学院第1期技术沙龙-线上直播|AI中台:一种敏捷的智能业务支持方案 主讲人介绍:井玉欣 宜信技术研发中心AI应用团队负责人 本文字数:13479字 阅读用时:34分钟 导读:随着&q ...
- 从数据中台到AI中台:一种敏捷的智能业务支持方案( 附视频讲解) | 技术头条...
点击上方↑↑↑蓝字关注我们~ 「2019 Python开发者日」全日程揭晓,请扫码咨询 ↑↑↑ 来源 | 宜信技术学院第1期技术沙龙-线上直播 原标题为:AI中台:一种敏捷的智能业务支持方案 导读:随 ...
- 全景也要更清晰,基于RK3588核心板的8K全景相机方案【飞凌嵌入式】
内容来源:飞凌嵌入式官网 www.forlinx.com 伴随着虚拟现实技术(简称VR)的热潮,VR全景影像开始兴起,全景相机市场也迎来了高速发展.近年来,360°全景相机几乎成为了数码潮人和vlog ...
- 浅谈几种区块链网络攻击以及防御方案之其它网络攻击
旧博文,搬到 csdn 原文:http://rebootcat.com/2020/04/16/network_attack_of_blockchain_other_attack/ 写在前面的话 自比特 ...
- 浅谈几种区块链网络攻击以及防御方案之拒绝服务攻击
旧博文,搬到 csdn 原文:http://rebootcat.com/2020/04/14/network_attack_of_blockchain_ddos_attack/ 写在前面的话 自比特币 ...
最新文章
- Flash和JavaScript通信
- [Python学习] 专题五.列表基础知识 二维list排序、获取下标和处理txt文本实例
- pageadminCMS.Net Framework的安装教程
- 基于Spring Boot的“课程设计”的设计与实现
- 学Android的学习规划
- Java程序员从笨鸟到菜鸟之(一百零四)java操作office和pdf文件(二)利用POI实现数据导出excel报表...
- [UE4]单机游戏改网络游戏,不完全清单
- 用C#编写一个抓网页的应用程序
- 图片预览(适用于IE6,9,10,Firefox)
- Squid优化完全手册(2)
- 不可能解开的谜题 (程序员修炼之道,评注者序)
- Python-Cartopy制图学习01-中国区域SPEI空间制图
- 【教程】鼠标右键新建添加RTF文档
- oracle复合结构,动名词的复合结构作宾语
- 点成分享 | 探索生物学中的电泳
- 在PHP中用sleep导致诡异事件
- 大一计算机课如何做表格,电脑做表格的基本操作教程
- omv安装mysql插件_Openmediavault第三方插件安装教程
- java毕业设计软件源代码SSM酒店管理系统|旅店管理
- IOS appstore 发布
热门文章
- Python随记(27)bs4爬取豆瓣250
- 【题解】UVA177 分治
- SARscape之DInSAR处理(双轨法)
- 一元钱一瓶汽水,喝完后两个空瓶能换一瓶汽水,问:你有20元钱,可以喝到几瓶汽水?
- stress模拟CPU使用100%
- 服务器共享文件夹给广域网,广域网文件共享服务器
- c语言数据结构与算法参考文献,数据结构论文参考文献
- HHL论文及代码理解(Generalizing A Person Retrieval Model Hetero- and Homogeneously ECCV 2018)...
- Ffmpeg视频压制的基础知识
- pixel 3 Top Shot