【视角的跟随、旋转、缩放实现】

首先,在实现这些功能之前,我们给Hierarchy面板中的主摄像机额外包装几层Empty Object,形成一个新的摄像机结构,如下图(当然这些空物体的命名大家按自己方便就是了):

然后调整一下CameraUpAndDown、CameraZoomContainer的几个参数(注意,调参这个步骤一定不要漏掉,调参是为了使主摄像机在旋转拉伸时能始终对准物体):

如图:

CameraUpAndDown物体rotateZ轴90°。(旋转CameraUpAndDown的Z轴是为了使主摄像机视角在旋转、拉伸时始终对准物体,)

CameraZoomContainer物体RotateY轴-90°。(旋转CameraZoomContainer的Y轴是为了使编辑器状态下视角在旋转、拉伸时始终对准物体,但不修改的话并不会影响运行时的视角)

CameraZoomContainer物体Position.X改为一个正数,(不一定是4,只要能使你的主摄像机观察到物体就行,0的话会使主摄像机距离物体太近。)

第二步,在CameraFollowAndRotate的Inspector面板下添加一个脚本(这里我把这个脚本命名为CameraCtrl),代码如下:

 using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class CameraCtrl : MonoBehaviour
{
public static CameraCtrl Instance; /// <summary>
/// 摄像机结构下的几个子物体, m_CameraUpAndDown控制垂直观察角度,m_CameraZoomContainer控制镜头对准方向, m_CameraContainer控制物体与镜头间距离
/// </summary>
[SerializeField]
private Transform m_CameraUpAndDown;
[SerializeField]
private Transform m_CameraZoomContainer;
[SerializeField]
private Transform m_CameraContainer; private void Awake()
{
Instance = this;
} //初始化函数
public void Init()
{
//如果Camera垂直观察角度的初始值、Camera与物体距离的初始值在限定范围外,进行矫正
m_CameraUpAndDown.Rotate(, , 45f);
m_CameraUpAndDown.localEulerAngles = new Vector3(, , Mathf.Clamp(m_CameraUpAndDown.localEulerAngles.z, 1f, 90f));
m_CameraContainer.localPosition = new Vector3(, , Mathf.Clamp(m_CameraContainer.localPosition.z, -5f, ));
} //实时看向主角物体
public void AutoLookAt(Vector3 position)
{
m_CameraZoomContainer.LookAt(position);
} /// <summary>
/// 控制Camera水平旋转 左=0 右=1
/// </summary>
/// <param name="type"></param>
public void SetCameraRotate(int type)
{
transform.Rotate(, * Time.deltaTime * (type == ? : -), );
} /// <summary>
/// 控制Camera垂直旋转 上=0 下=1
/// </summary>
/// <param name="type"></param>
public void SetCameraUpAndDown(int type)
{
m_CameraUpAndDown.Rotate(, , * Time.deltaTime * (type == ? : -));
//锁定Camera垂直观察角度的范围1°至90°
m_CameraUpAndDown.localEulerAngles = new Vector3(, , Mathf.Clamp(m_CameraUpAndDown.localEulerAngles.z, 1f, 90f));
} /// <summary>
/// 控制Camera和物体的距离 拉近=0 拉远1
/// </summary>
/// <param name="type"></param>
public void SetCameraZoom(int type)
{ //注意,虽然方法名有Zoom,但是控制镜头与物体距离的是m_CameraContainer,所以这里修改m_CameraContainer的position的Z轴
m_CameraContainer.Translate(Vector3.forward * * Time.deltaTime * (type == ? : -));
m_CameraContainer.localPosition = new Vector3(, , Mathf.Clamp(m_CameraContainer.localPosition.z, -5f, ));
}
}

注意!  13、15、17三个序列化字段的赋值要在CameraFollowAndRotate的Inspector面板中进行,使这些变量指向对应的组件,如下图:

第三步,在 视角要跟随的Object 的脚本中 实现对CameraCtrl脚本方法的调用,这里就简单举例了:

 //该方法在要跟随的Object的脚本的Update()中调用即可实现视角的旋转、缩放以及视角的实时跟随
private void cameraAutoFollow()
{
if (CameraCtrl.Instance == null) { return; }
//Camera实时同步主角物体的位置并使镜头对准主角物体
CameraCtrl.Instance.transform.position = gameObject.transform.position;
CameraCtrl.Instance.AutoLookAt(gameObject.transform.position); //依照按键调整镜头视角,以按Q键实现顺时针水平旋转为例子
if (Input.GetKey(KeyCode.Q))
{
CameraCtrl.Instance.SetCameraRotate(); //参数为1 则为逆时针水平旋转
//CameraCtrl.Instance.SetCameraUpAndDown(0); //视角垂直旋转
//CameraCtrl.Instance.SetCameraZoom(0); //视角缩放
}
}

最后,对这个摄像机结构再总结一下:

CameraFollowAndRotate:通过修改该Object的Position,我们可以实现视角对移动物体的跟随、RotateY轴则可以实现视角对物体的水平旋转观察。

CameraUpAndDown:通过Rotate该Object的Z轴,我们可以实现视角对移动物体的垂直旋转观察。Z轴旋转要初始为90°

CameraZoomContainer:运行的时候Lookat方法会实时Rotate各个轴使摄像机镜头对准物体。Y轴旋转要初始为-90°以方便编辑器视窗下对Camera的调试,X轴设置为一个合适的正数就可以。

CameraContainer:通过修改该Object的Position.Z属性来拉近或拉远主摄像机与物体的距离,实现缩放。

【Unity3D】简单常用的功能实现2——视角的跟随、旋转、缩放的更多相关文章

  1. 【Unity3D】简单常用的功能实现1——鼠标点击实现移动

    [鼠标点击实现移动] 第一步,在要移动的GameObject的Inspector面板中添加角色控制器组件并调整参数. 参数的调整可以依照Scene面板,如下图的绿色线框(角色控制器组件是一种胶囊形状的 ...

  2. Unity3D事件顺序与功能

    Unity3D中所有控制脚本的基类MonoBehaviour有一些虚函数用于绘制中事件的回调,也可以直接理解为事件函数,例如大家都很清楚的Start,Update等函数,以下做个总结. Awake 当 ...

  3. iOS常用小功能

    CHENYILONG Blog 常用小功能 技术博客http://www.cnblogs.com/ChenYilong/ 新浪微博http://weibo.com/luohanchenyilong  ...

  4. iOS 常用小功能 总结

    常用小功能 iOS中的很多小功能都是非常简单的,几行代码就搞定了,比如打电话.打开网址.发邮件.发短信等 打电话 方法一(不被采用): 拨号之前会弹框询问用户是否拨号,拨完后能自动回到原应用 NSUR ...

  5. Pandas常用基本功能

    Series 和 DataFrame还未构建完成的朋友可以参考我的上一篇博文:https://www.cnblogs.com/zry-yt/p/11794941.html 当我们构建好了 Series ...

  6. Oracle简单常用的数据泵导出导入(expdp/impdp)命令举例(上)

    <Oracle简单常用的数据泵导出导入(expdp/impdp)命令举例(上)> <Oracle简单常用的数据泵导出导入(expdp/impdp)命令举例(下)> 目的:指导项 ...

  7. Oracle简单常用的数据泵导出导入(expdp/impdp)命令举例(下)

    <Oracle简单常用的数据泵导出导入(expdp/impdp)命令举例(上)> <Oracle简单常用的数据泵导出导入(expdp/impdp)命令举例(下)> 目的:指导项 ...

  8. WPF绘制简单常用的Path

    写代码出身的我们经常需要使用一些简单 但是不是规则图形的Path 但限于美工功底有限 不知道怎么去画 下面我告诉大家一些简单的小技巧 用代码来画Path 个人还是比较喜欢用代码 因为数值控制的更精细 ...

  9. ASP.NET MVC 学习4、Controller中添加SearchIndex页面,实现简单的查询功能

    参考:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-edit-method ...

随机推荐

  1. php - 二维数组转一维数组总结

    二维数组转一维数组总结 例如将如下二位数组转以为以为一维数组 $records = [ [ 'id' => 2135, 'first_name' => 'John', 'last_name ...

  2. mac下创建安卓应用 hello-world

    教程 https://www.jianshu.com/p/bf77cb5ce70b 需要注意的地方 jdk目录查找 jdk目录拷贝到tool目录下面(jdk可以拷贝,没有其他牵扯) https://w ...

  3. SQL语句中where 1=1的意义

    我们在看别人项目的时候,很多时候看到这样的SQL语句: select * from user where 1=1 其中这个where1=1是有特殊意义的,包含以下两种情境:动态SQL拼接和查询表结构. ...

  4. C#判断某元素是否存在数组中

    string s = "K2:CENTALINE\\lukshing|K2:CENTALINE"; string[] s1 = s.Split('|'); //判断方式是 等于 而 ...

  5. .NET 开源工作流: Slickflow流程引擎高级开发(七)--消息队列(RabbitMQ)的集成使用

    前言:工作流流程过程中,除了正常的人工审批类型的节点外,事件类型的节点处理也尤为重要.比如比较常见的事件类型的节点有:Timer/Message/Signal等.本文重点阐述消息类型的节点处理,以及实 ...

  6. Halcon斑点分析涉及算子及其高阶运用

    涉及算子 获取图像 使用ROI 对齐ROI或图像 校正图像 基础内容这里不再重述 预处理图像(过滤) 基础: mean_image(平均平滑过滤),gauss_filter(高斯滤波),binomia ...

  7. ES11来了,还学得动吗?

    写在前面 ES2020(即 ES11)上周(2020 年 6 月)已经正式发布,在此之前进入 Stage 4 的 10 项提案均已纳入规范,成为 JavaScript 语言的新特性 一.特性一览 ES ...

  8. 第一章 java基本多线程技能

    第一章 java多线程技能 1 线程:进程是操作系统结构的基础,是一次程序的执行,是一个程序及其数据在处理顺序时发生的活动:是程序在一个数据集合上运行的过程,他是系统进行资源分配和调度的一个独立单位. ...

  9. java语言基础(二)_IDEA_方法

    IDEA使用 项目结构: 所有代码放置在src文件夹内 新建包:在src文件夹上,右键新建包.包的命名:英文小写.数字.英文句点. 例如:使用公司域名倒写,如cn.itcast.day04.demo0 ...

  10. Python 简明教程 --- 22,Python 闭包与装饰器

    微信公众号:码农充电站pro 个人主页:https://codeshellme.github.io 当你选择了一种语言,意味着你还选择了一组技术.一个社区. 目录 本节我们来介绍闭包与装饰器. 闭包与 ...