基于Cinemachine的第一/三人称过肩/自由/斜45度/俯视角摄像机系统

专栏 / 基于Cinemachine的第一/三人称过肩/自由/斜45度/俯视角摄像机系统

基于Cinemachine的第一/三人称过肩/自由/斜45度/俯视角摄像机系统

2022年08月03日 11:19 --浏览 · --喜欢 · 视频地址: 【Unity】基于Cinemachine的第一/三人称过肩/自由/斜45度/俯视角摄像机系统演示(源码及文档见简介)

粉丝: 344 文章: 6

一、功能介绍

Cinemachine是Unity中一款强大的摄像机插件,可以无需代码实现一些复杂的效果,也支持通过脚本扩展更复杂的效果,上手简单,Unity2017以上版本都可以使用。

与Camera不同的是,虚拟相机不是真正的相机,不挂载Camera组件,只是一些数据,本质上是相机行为的配置文件,来控制真实相机参数,因此必须搭配一个Camera对象才能渲染画面,故性能消耗要比创建多个真实相机小很多。

本摄像机系统基于Cinemachine的Virtual Camara实现,实现了 锁定、旋转、缩放、移动、鼠标显示/隐藏、摄像机位置复位、限制摄像机角度、动态挂载跟随目标、切换视角、遮挡透视 等功能,并 自带摄像机碰撞,防止穿墙

相机锁定包含仅水平、仅垂直方向锁定。

相机旋转可由鼠标左键按下移动控制,也可直接移动鼠标控制。

相机缩放可由鼠标滚轮控制,但滚轮控制相对不够流畅,故也设置为鼠标Y轴,即上下移动鼠标控制缩放。

相机移动可由鼠标中键/右键按下移动控制。

玩家可通过相对灵活多变的控制方式,更自由的探索游戏场景。对于喜爱录制二创剧情的玩家,可以更方便的进行运镜,制作出自己的“大片”。

本系统提供了 五种视角 切换,第一人称、自由视角需要通过鼠标控制摄像机方向,进而控制角色移动方向;第三人称过肩视角通过A、D键控制旋转,鼠标仅可以上下移动视角;斜45度视角及俯视角为固定视角,不可移动,斜45度视角会自适应视角,无需鼠标控制;俯视角在角色被遮挡时,会将遮挡物材质替换为透明材质。

本案例摄像机系统对渲染管线没有要求,可升级到URP或HDRP渲染管线。

本案例摄像机系统基于PC端、旧输入系统开发,通过鼠标键盘进行控制,如需移植到其他平台,需要将相关输入修改为对应平台的输入。如果涉及到多平台发布,推荐替换为新输入系统,方便统一管理。案例中引入的官方最新角色控制器资源基于新输入系统开发,可以研究源码进行相关的学习,此文档不作详细说明。

二、相关按键

注:按键可根据自己喜好进行替换。

摄像机相关按键:

第一人称、自由视角切换: V

第三人称过肩视角、自由视角切换: B

斜45度视角、自由视角切换: N

俯视角、自由视角切换: M

是否显示鼠标: 0

锁定摄像机Y轴: 9

锁定摄像机X轴: 8

摄像机旋转控制: 按下鼠标左键移动鼠标、或直接移动鼠标

是否由鼠标左键/右键控制摄像机旋转: 右Ctrl

摄像机视野缩放: 鼠标滚轮、或鼠标Y轴

鼠标滚轮/鼠标Y轴控制摄像机视野缩放切换: 右Alt

摄像机移动: 按下鼠标中键/右键移动鼠标

自由视角摄像机位置复位: P

CharacterController角色控制器相关按键:

角色奔跑: 左Shift+WASD或左Shift+方向键

角色走路: WASD或方向键

角色跳跃: 空格

角色旋转(仅第三人称过肩视角时): A、D或方向键左右

Rigidbody角色控制器相关按键:

角色冲刺: 左Shift+WASD或左Shift+方向键

角色奔跑: WASD或方向键

角色跳跃: 空格

三、设计思路

为了降低开发复杂度,基于Unity资源商店最新第三人称角色控制器(下载链接见附录)进行改造,改造后的项目源码链接见附录。最新第三人称角色控制器支持的Unity版本:2020.3.0或更高。本项目使用Unity 2020.3.33f1c2进行开发,Cinemachine版本为2.6.15,不同版本插件的参数面板会有略微差异。

为了增加摄像机系统的灵活性及可移植性,将摄像机控制逻辑单独封装,可以搭配基于Character Controller的角色控制器或基于刚体的角色控制器使用。

摄像机控制使用的是旧版输入系统。本案例使用的最新的基于Character Controller的第三人称角色控制器以及第一人称角色控制器,使用了新版输入系统;而基于刚体的角色控制器使用了旧版输入系统。故在设置中选择新旧输入系统混合的模式,更改设置后会重新启动Unity(记得提前保存项目)。

第一/三人称/自由/斜45度/俯视角分别创建Virtual Camara进行控制,通过激活/禁用Virtual Camara以及挂载在Virtual Camara上的脚本完成视角的切换。

Cinemachine可以自动跟随目标,故将跟随目标设置为角色的子物体。

通过控制角色的移动,修改摄像机位置。

通过控制跟随目标的旋转,修改摄像机方向。

通过调整Virtual Camara上Cinemachine3rdPersonFollow的Shoulder Offset参数值,修改摄像机与角色相对位置。

通过调整Virtual Camara上Cinemachine3rdPersonFollow的Camera Distance参数值,修改摄像机与角色相对距离。

大多教程是直接移动鼠标控制摄像机旋转,对于一些要操作UI的游戏不是很方便,而且容易加重3D眩晕,故本案例提供 按下鼠标左键旋转摄像机 的功能。

由于网上教程大多是直接挂载虚拟相机的跟随目标,这使得动态创建出的角色无法绑定虚拟相机(比如一些MMO类的游戏),故案例中 对虚拟相机的跟随目标进行动态绑定 ,防止场景切换导致的摄像机目标丢失。

案例会添加动态创建/销毁角色,更好的模拟实际开发的需求。

四、具体实现

注:在编写过程中有对项目进行优化,故内容可能会与源码有细微出入,实际效果以源码为主!

(一)基于Character Controller的角色控制器

1、角色控制器及Cinemachine资源导入

首先创建3D空项目,删除Project Assets目录下的默认场景, 设置新旧输入系统为混合模式 ,点击应用后会自动重启Unity项目,耐心等待即可。

设置新旧输入系统为混合模式

打开浏览器,下载Unity资源商店最新第三人称角色控制器(下载链接见附录),通过Package Manager下载并导入。初次下载点击“添加至我的资源”,然后点击“在Unity中打开”,会自动跳转至当前已打开Unity项目的Package Manager。(如打开多个Unity项目需要进行选择)

Starter Assets - First Person Character Controller

一般情况在浏览器资源商店点击“在Unity中打开”会自动打开当前Unity项目的Package Manager,若无反应,可手动在Unity中点击“Window - Package Manager”打开Package Manager。

导入资源

选择“My Assets”,输入资源名称进行搜索。

初次下载需要点击“Download”下载资源,网速可能会导致Package Manager无法加载资源,或资源下载失败,可以等网络情况良好的时候再进行下载。下载完成后,点击“Import”导入所有资源。

再下载Unity资源商店最新第一人称角色控制器,方法同上。

Starter Assets - Third Person Character Controller

安装以上角色控制器,会自动导入Cinemachine资源。若使用自己实现的角色控制器,而非以上资源,需要手动导入Cinemachine资源。选择“Unity Registry”(查看所有Unity常见插件),可输入Cinemachine进行搜索,找到后安装Cinemachine。(若选择“In Project”可查看仅当前项目中安装的插件)

2、分析源码

打开第三人称角色控制器场景。

运行项目,点击Game窗口,发现鼠标被隐藏;按下键盘上的WASD或方向键移动角色,Shift+WASD或方向键跑步,同时摄像机自动跟随;移动鼠标,控制摄像机旋转。(按下Esc显示鼠标,退出运行)

通过查看源码可知,ThirdPersonController.cs控制摄像机的相关逻辑,StarterAssetsInputs.cs控制光标显示/隐藏与输入。故将相关的逻辑单独进行封装,便于摄像机系统的移植。

3、准备工作

(1)角色设置

双击打开角色预制体,将角色下的“PlayerCameraRoot”重命名为“FollowTarget_1st”,作为第一人称视角的跟随目标,一般位于角色眼睛高度。

选中FollowTarget_1st后按“Ctrl+D”复制一份,重命名为“FollowTarget_3rd”,作为第三人称过肩视角及斜45度/俯视角的跟随目标,一般位于角色肩膀高度。

选中FollowTarget_3rd后按“Ctrl+D”复制一份,重命名为“FollowTarget_Free”,作为自由视角的跟随目标,一般位于角色肩膀高度。

注:因为自由视角会控制角色身上的跟随目标,与其他视角无法复用,故需要新建一个followTarget_Free。

因为相机跟随目标与角色坐标保持相对位置,故部分角色动画可能出现模型移动,但实际角色坐标未移动,此时模型会穿过相机影响游戏体验。(在播放可能造成摄像机与角色发生穿模的技能时,建议切换到第三人称过肩视角、自由视角或斜45度视角)

虽然可以通过将跟随目标挂载到头部骨骼下解决此类问题,但会导致角色头部哪怕轻微移动,相机都会进行抖动,同样会影响游戏体验,更容易导致玩家出现3D眩晕的状况。

故可以再复制2份模型网格,对3份网格进行设置,第一份不渲染阴影,第二份挂载透明材质并且不渲染阴影,第三份只渲染阴影。

第一人称视角时,隐藏第一份网格,显示第二份网格。

第三人称过肩视角、自由视角、斜45度视角、俯视角时,显示第一份网格,隐藏第二份网格。

如需要在第一人称视角时,只显示四肢,则只需要将身体设置为透明材质。

在ThirdPersonController.cs中添加图中代码,将上面创建的游戏对象挂载到脚本组件对应位置。

(2)相机设置

选中相机预制体,将相机的默认混合模式设置为“Cut”(瞬间切换)。(这样不同模式相机间会立即切换,防止第一人称相机和其他相机间切换时,相机穿过身体)

可以在Custom Blends项点击Create Asset创建一个资源文件,控制指定虚拟相机之间的切换模式。在第一人称相机和其他相机切换时选择Cut,防止穿帮;在其他相机之间切换时,设置合适的切换模式及切换时长。(下文中“Camera对象上的CinemachineBrain组件”部分会介绍具体参数)

创建Mono单例脚本,命名为“MonoSingleton”(源码见附录项目源码),这样在切换场景时,虚拟相机不会销毁,就不需要每个场景都添加了,防止遗漏。

创建空物体,命名为CMVcamManager,作为角色所有虚拟相机的父物体,方便统一管理。

创建C#脚本,命名为“CMVcamManager”,挂载到CMVcamManager上。

4、功能实现

(1)自由视角虚拟相机

实现思路:

在自由视角中,角色移动的方向为摄像机的方向,角色可以转身。摄像机方向与虚拟相机方向一致,而虚拟相机方向由跟随目标决定。那么只要控制跟随目标的方向,就可以控制角色移动的方向。而当跟随目标为角色的子物体时,跟随目标的方向会受到角色方向的影响,从而相机方向也会受到影响,这会导致角色在原地旋转。那么通常有两种解决方案,一种是 由虚拟相机脚本控制跟随目标的方向,使其与虚拟相机方向保持一致 ,这样无论角色朝向哪里,都不会影响到相机的方向;另一种是 动态创建一个游戏对象,使其与角色身上跟随目标的位置时刻保持一致,但方向由虚拟相机控制 ,这样角色方向就不会影响到相机了。

注:本案例两种方案都有涉及,基于Character Controller的角色控制器使用了直接控制跟随目标的方案,基于Rigidbody的角色控制器使用了创建一个跟随目标的方案。

可以删除场景中的PlayerFollowCamera,重新创建,也可以用PlayerFollowCamera直接修改。点击“Cinemachine – Create Virtual Camera”创建虚拟相机,命名为“CMVcam_Free”,在场景中首次创建虚拟相机会自动在Camera对象上挂载CinemachineBrain组件,此时Camera组件的部分属性已经无法修改,而是由虚拟相机控制,需要在虚拟相机组件上进行修改。CinemachineBrain组件会读取场景中某个虚拟相机的配置,并以此配置去控制相机的行为。

参数设置如图,可根据需求调整具体参数。

Status:Live/Standby/Disabled:虚拟相机运行状态(激活/待机/禁用)

待机状态表示虚拟相机并未被CinemachineBrain使用,但虚拟相机自身还在运行当中,下面的(Follow)跟随、(Look At)瞄准等计算不一定会停止。点击Solo可以将当前虚拟相机立即处于激活状态,方便在开发时随时观察虚拟相机的工作状态,并进行调整,但点击其他地方会关闭预览。

Game Window Guides:游戏窗口引导(Game窗口显示虚拟相机提示信息)

Save During Play:运行状态保存虚拟相机的部分参数修改

Priority:优先级(CinemachineBrain会使用优先级较高的虚拟相机,在Timeline中无效)

Follow:虚拟相机要跟随的目标(具体行为设置在Body中,Body影响虚拟相机的位置,是否绕跟随目标旋转)

Look At:虚拟相机要看向的目标(具体行为设置在Aim中,Aim影响虚拟相机自身的旋转)

Standby Update:待机状态Follow和Look At之类的计算要以什么频率执行/刷新(计算帧率/刷新频率)

Never:永远不执行/刷新

Always:执行和刷新的频率与激活的相机一致

Round Robin:一种轮替的更新策略(每一帧选择一个Standby相机进行更新)

Lens:镜头设置

Field Of View:视野角度(一般不要超过60)

Near Clip Plane:近裁剪平面(与相机距离小于这个数值的游戏对象不会被渲染)

Far Clip Plane:远裁剪平面(与相机距离大于这个数值的游戏对象不会被渲染)

Dutch:Dutch Angle(斜角镜头的角度)(荷兰角,Dutch是德国Deutsch,这种斜角拍摄方式流行于德国表现主义作品当中)

Transitions:一些虚拟相机切换时的属性设置

Blend Hint:相机切换的行为具有怎样的物理空间特征

None:对角度和位置做差值,线性的切换

Spherical Position:球形切换(如果Look At有对象,则以它为球心做球形切换)

Cylindrical Position:圆柱形切换(如果Look At有对象,则以它为中心,在水平平面上做圆形切换,在垂直方向上做线性切换)

Screen Space Aim When Targets Differ:当Look At的对象不一样时,在屏幕空间之间做切换。在位置上使用世界坐标系,表现出普通的线性切换;在角度上根据两个相机构成的屏幕空间的夹角间做切换

Inherit Position:当前虚拟相机被激活时,不改变Camera位置,而是虚拟相机移动到Camera位置

Noise:添加相机抖动效果,可以模拟手持相机抖动,本案例关闭抖动效果,可根据需求选择是否开启。

Add Extension:添加额外的功能(比如相机碰撞体,可以防止穿墙)

点击“Add Extension – CinemachineCollider”添加虚拟相机碰撞体。(Cinemachine实现防穿墙很方便,相关参数可以查看官方手册)

创建C#脚本,命名为“CMVcam_Free”,挂载到CMVcam_Free虚拟相机上。

<1> 移除角色控制器中关于摄像机的逻辑

①    剪切ThirdPersonController.cs中代码

剪切ThirdPersonController.cs图中 黄色框 框选的代码至CMVcam_Free.cs。修改白色框框内代码为“Public”。

② 剪切StarterAssetsInputs.cs中代码

剪切StarterAssetsInputs.cs图中 黄色框 框选的代码至CMVcam_Free.cs,白色框框选的代码可以暂时保留,删除 红色框 框选的代码。(OnApplicationFocus(bool hasFocus)函数在玩家获得或失去焦点时,会执行里面的方法,此处由于cursorLocked = true,即光标默认设置为隐藏,所以只要运行游戏,就会隐藏光标,可以改为“cursorLocked = false”,这样默认是显示光标的。如果想要手动控制光标的显示/隐藏,建议删除OnApplicationFocus(bool hasFocus)函数)

分析可知“cursorInputForLook”可以控制是否获取鼠标移动的值,若保留了新输入系统,则也可以通过控制“cursorInputForLook”的值锁定摄像机旋转。但由于此处是同时获取鼠标X和Y轴的位移量,若锁定摄像机会同时锁定X轴和Y轴,无法单独控制其中一个轴,除非在新输入系统中进行设置,分别获取鼠标的X轴和Y轴。

为了提高摄像机系统的可移植性,摄像机部分的逻辑最终不会使用到新输入系统,此处可以选择删除cursorInputForLook字段及OnLook(InputValue value)函数,在CMVcam_Free.cs中通过“Input.GetAxis("Mouse X")”和“Input.GetAxis("Mouse Y")”获取鼠标的X轴和Y轴位移量。(详细代码见源码)

<2> 修复报错

全部剪切之后会发现CMVcam_Free.cs中的“IsCurrentDeviceMouse”和“_input”报错,这是因为没有引用ThirdPersonController.cs和StarterAssetsInputs.cs脚本。将“_input”全部修改为“inputController”。添加对应的命名空间(“using StarterAssets;”),并暂时创建为公开变量,通过面板赋值,后面会改为动态获取。

将需要的对象挂载到脚本组件对应位置。

暂时将跟随目标挂载到虚拟相机上,后面会改为动态挂载。

<3> 测试逻辑

运行项目可以正常控制摄像机旋转,鼠标不会隐藏。此时禁用CMVcam_Free.cs进行测试,移动鼠标无法控制摄像机旋转,角色移动时相机会自动跟随,但在角色旋转时,和直接将相机作为角色子物体效果一样,相机会旋转的很快,容易导致玩家3D眩晕,影响游戏体验。说明已将角色控制器中摄像机相关逻辑正确独立封装。

<4> 优化摄像机逻辑(动态获取跟随目标、切换视角)

首先删除场景中的角色对象,创建一个脚本,比如GameManager.cs,用来动态生成及销毁角色,按下R可以控制角色的生成及销毁。(源码见下图)

GameManager.cs:

将需要的角色预制体挂载到脚本组件对应位置。

实现思路:

跟随目标是角色的子物体,且在ThirdPersonController.cs中引用,故可以通过获取ThirdPersonController.cs上的对象,实现对虚拟相机跟随目标的动态赋值。

为了方便统一管理及逻辑复用,将CMVcam_Free.cs中的部分逻辑移动到CMVcamManager.cs中,比如ThirdPersonController.cs及StarterAssetsInputs.cs的获取,光标的显示/隐藏等。(源码如图)

CMVcamManager.cs:

面板脚本组件上挂载相关对象。

CMVcam_Free.cs:

面板脚本组件上挂载相关对象,并将虚拟相机上的Follow和Look At设置为None。

<5> 测试动态获取跟随目标、切换视角

经测试,运行之后自动会创建角色,并获取跟随目标。按R角色会被销毁,虚拟相机丢失跟随目标,再按R会创建角色,并获取跟随目标。

默认是自由视角,按下V切换到第一人称视角,再按V切换回自由视角;按下B切换到第三人称过肩视角,再按B切换回自由视角;按下N切换到斜45度视角,再按N切换回自由视角;按下M切换到俯视角,再按M切换回自由视角;相互之间也可以转换。

<6> 增加鼠标左键旋转、仅X轴或Y轴旋转、鼠标滚轮缩放、鼠标中键/右键移动摄像机

由于将摄像机中所有输入替换为旧输入系统,故可以删除或注释ThirdPersonController.cs中PlayerInput组件相关脚本以及IsCurrentDeviceMouse属性。(不要删除角色上挂载的PlayerInput组件,因为StarterAssetsInputs.cs中会调用)

实现思路:

利用bool变量控制虚拟相机参数改变的相关命令何时执行,按键更改bool值即可。(源码见下图)

CMVcam_Free.cs:

(2)第一人称视角虚拟相机

打开第一人称视角场景,运行项目,发现由于角色是胶囊体,所以没有角色动画,角色旋转由摄像机控制,所以在角色旋转逻辑上与其他视角会有一定的差别。

第一人称视角不需要做缩放、移动、锁定X/Y轴等,比自由视角逻辑要少一些,其余逻辑基本一致,可以参考自由视角编写。

实现思路:

把第一人称的相关逻辑添加到之前的角色控制器逻辑中,通过视角切换的bool值控制这两者逻辑执行的时机。由于跟随目标是角色的子物体,虚拟相机控制它的旋转并不能直接影响到角色,所以虚拟相机需要同时控制角色的方向。而跟随目标作为子物体,会受到角色方向的影响。所以需要单独控制两者的X轴和Y轴,分别控制角色的X轴方向,以及跟随目标的Y轴方向。

打开FirstPersonController.cs,将角色移动旋转相关的源码复制到ThirdPersonController.cs中,将_rotationVelocity开放一个属性。(源码见下图)

ThirdPersonController.cs:

创建虚拟相机,重命名为:“CMVcam_1st”,创建CMVcam_1st.cs脚本,将CMVcam_1st.cs挂载到CMVcam_1st上。(相关设置见下图)

CMVcam_1st.cs:

由于控制角色转向的变量在ThirdPersonController.cs脚本中,所以虚拟相机控制角色转向时要调用ThirdPersonController.cs脚本中的变量。

CMVcamManager.cs:

(3)名字调整

为了做区分,将“ThirdPersonController.cs”重命名为“PlayerController_CC.cs”,将“StarterAssetsInputs.cs”重命名为“PlayerInputController_CC.cs”,将角色预制体“PlayerArmature” 重命名为“Player_CharacterController”。

注:右键类名,点击“重命名”修改类名,可以一次性将所有引用修改,更加方便。 (为了方便大家对比,本案例重新导入了一份资源包)(修改类名可能会导致面板上拖拽的引用丢失,检查并重新拖拽即可)

(4)第三人称过肩视角

实现思路:

第三人称过肩视角与其他视角不同的是,角色的方向以世界坐标为基准,不由相机控制,虚拟相机的X轴旋转是由角色控制的,鼠标仅控制Y轴旋转。所以在角色控制脚本中需要进行修改移动方式,WS或上下键控制角色前进、后退,AD或左右键控制角色旋转。并且需要添加专门的动画,可以前进、后退、向左旋转、向右旋转(可以通过镜像旋转动画,省去一个动画资源,补充的动画资源来自mixamo网站,详细网址见附录)。

创建虚拟相机,重命名为:“CMVcam_3rd”,创建CMVcam_3rd.cs脚本,将CMVcam_3rd.cs挂载到CMVcam_3rd上。(相关设置见下图)

CMVcam_3rd.cs:

修改状态机:

创建一个Bool变量,命名为“IsStrafe”,创建两个Float变量,分别命名为“Horizontal”、“Vertical”。

注:可以参考下面Rigidbody角色控制器中的状态机进行封装,将移动动画和跳跃动画分离。

创建三组混合树,分别命名为:“Idle”、“Walk”、“Run”。

PlayerController_CC.cs:

(5)斜45度视角

创建虚拟相机,重命名为:“CMVcam_Quarter”,创建CMVcam_Quarter.cs脚本,将CMVcam_Quarter.cs挂载到CMVcam_Quarter上。(相关设置见下图)

斜45度视角是固定视角,脚本只需要挂载跟随目标即可。

CMVcam_Quarter.cs:

(6)俯视角

创建虚拟相机,重命名为:“CMVcam_OverLook”,创建CMVcam_OverLook.cs脚本,将CMVcam_OverLook.cs挂载到CMVcam_OverLook上。(相关设置见下图)

俯视角是固定视角,脚本只需要挂载跟随目标即可。

CMVcam_OverLook.cs:

(7)遮挡透视

除第一人称视角和俯视角外,其他视角都添加了相机碰撞体,可以避免相机被遮挡。

但在俯视角中,因为若添加相机碰撞体会导致机位改变,故不具有防遮挡以及防穿墙功能。在角色进入室内或一些遮挡物下时,将无法观察到角色,故需要采取一定的防遮挡效果。

实现原理:

常见的防遮挡方案有两种,一种是当相机被遮挡时, 改变相机的位置、高度 等,以此保证相机能够看到角色, 添加相机碰撞体 就使用了这一原理;另一种是将角色和相机之间的 遮挡物变透明 ,比如 改变遮挡物材质的透明度属性 (可以保留材质原本的颜色,但对材质Shader类型有要求,材质要能支持透明效果,且需要操作Shader,相对比较复杂,且可移植性不如替换材质),或直接 替换为预设的透明材质

本案例选取了直接替换遮挡物材质为预设透明材质的方案,适用范围更广。

实现思路:

遮挡物的获取可以用射线检测,从摄像机发出一条射线到角色,“Physics.RaycastAll”可以一次性返回所有检测到的对象信息。只需要在信息发生改变时,判断是否需要替换材质即可。

注:若一个对象上存在多个材质,需要创建材质数组,逐个添加透明材质,通过材质数组替换对象上的材质。通过查阅Unity API(链接见附录)可知,直接使用“GetComponent<Renderer>().materials[i]= alphaMaterial;”会对材质实例化,无法替换材质。

创建透明材质:

创建Obstacle2Transparente.cs脚本,挂载到Camera相机上。射线是从此脚本挂载的对象向指定目标发出一条射线,检测两者之间的对象,所以要实现相机遮挡透视,此脚本一定要挂载在Camera相机上。(之所以没有之间挂载到俯视角虚拟相机上,是因为切换其他虚拟相机时,俯视角虚拟相机由于组件被禁用,故不会跟随移动,所以可能会导致材质无法还原,因此要挂载在Camera相机上,这样再切换相机时仍然可以保证透视相关逻辑正常执行)

Obstacle2Transparente.cs:

效果展示:

运行项目,当角色被遮挡时,遮挡物变透明,角色不被遮挡时,还原材质。当相机与角色之间存在多层遮挡时,可以同时控制多个遮挡物。

(8)Camera对象上的CinemachineBrain组件

<1> Live Camera:当前正在使用的虚拟相机配置

<2> Live Blend:当前的虚拟相机切换过程(在切换时显示)

<3> Show Debug Text:显示Debug文本

可以在Game视窗看到当前使用的虚拟相机和当前正在执行的相机转换。

<4> Show Camera Frustum:显示当前的视锥体(相机的可视范围)

默认只有选中相机才会在场景中看到视锥体,勾选之后,无论是否选中都会看到,前提是在Gizmos中打开了相关项,默认是打开的。

<5> Ignore Time Scale:相机的行为是否受时间缩放值的影响

<6> World Up Override:世界上方覆盖

相机在运行时默认的“上方”为世界坐标系下Y轴的方向,在相机发生旋转的时候,如果相机本地坐标下的Y轴和“上方”之间的夹角大于90°时,相机会重设自己的方向,保证和“上方”的夹角小于90°。比如在俯视角游戏中,不希望出现这种视角的自动调整,就可以在这里放置一个游戏对象,使用这个游戏对象的Y轴代替相机默认的“上方”。

<7> Update Method:虚拟相机的行为与什么同步

Fixed Update:与物理引擎同步

Late Update:与画面绘制同步

Smart Update:Unity根据实际情况智能选择同步

Manual Update:编写代码控制相机行为的同步时间

<8> Blend Update Method:两个虚拟相机之间的切换行为与什么同步

Fixed Update:与物理引擎同步

Late Update:与画面绘制同步

<9> Default Blend:默认相机切换模式

Cut:瞬间切换

Ease In Out:加速切出,减速切入

Ease In:匀速切出,减速切入

Ease In Out:加速切出,减速切入

Ease Out:加速切出,匀速切入

Hard In:加速切入

Hard Out:加速切出

Linear:匀速切换

Custom:自定义切入切出曲线

<10> Custom Blends:自定义切换模式

点击Create Asset创建一个资源文件,指定不同虚拟相机之间的切换模式。

<11> Events:相机事件触发

Camera Cut Event(CinemachineBrain):相机之间发生Cut(瞬间切换)时触发的事件

Camera Activated Event(ICinemachineCamera, ICinemachineCamera):相机之间发生其他切换的第一帧时触发的事件

此处在第一人称相机和其他相机相互切换时选择Cut,防止穿帮;其他相机之间切换会使用默认为“1秒”的匀速切出,减速切入(Ease In)模式。

(9)Virtual Camara相关设置介绍补充

<1> Body

① Transposer

虚拟相机将在某个固定的偏移或距离(Follow Offset)上跟随目标移动。

Binding Mode:

Lock To Target On Assign:虚拟相机会锁定自己和目标之间的距离(锁定仅发生在当前虚拟相机和Follow对象建立关系(On Assign)的时候,此时虚拟相机会出现在目标本地坐标系下的Follow Offset位置)

Lock To Target With World Up:虚拟相机可以绕跟随目标的垂直方向的偏航轴(Yaw Axis)旋转,但自己不会旋转(可以设置Yaw Damping)

Lock To Target No Roll:虚拟相机可以绕跟随目标的偏航轴(Yaw Axis)和俯仰轴(Pitch Axis)旋转,但自己不会旋转(可以设置Pitch Damping和Yaw Damping)

Lock To Target:虚拟相机可以绕跟随目标的偏航轴(Yaw Axis)、俯仰轴(Pitch Axis)、横滚轴(Roll Axis)旋转,但自己不会旋转(如果选择Euler(欧拉角),可以单独设置Pitch Damping、Yaw Damping、Roll Damping;如果选择Quaternion(四元数),则统一设置所有方向旋转的延迟)

World Space:与Lock To Target On Assign类型,但使用的是世界坐标系下的坐标

Simple Follow With World Up:虚拟相机不会绕跟随对象的任何一个轴旋转,且尽量不会沿X轴方向移动

Follow Offset默认为(0,0,-10),即相机处于(Follow)跟随目标身后10米位置左右。

Damping是阻尼系数,可以理解为相机移动的延迟。系数越小,相机的反应就越快。

<2> Aim

① Do nothing

什么都不做。

② Composer

标准的瞄准模式,可以用来保证相机看着目标。

Tracked Object Offset:偏移量,虚拟相机瞄准的位置(Game视窗上会显示一个黄色的小方块)与跟随目标位置的偏移

Lookahead Time:目标当前移动速度推测出偏移量,虚拟相机会计算当前目标的速度,并预测出一段时间后目标的位置,然后添加一个偏移量。(如果目标运动很随机,或带有一定的噪声(Noise),预测可能会将噪声放大)

Lookahead Smoothing:可以让预测算法更加平滑,当目标的运动情况变化比较大时,可以调整数值,消除镜头抖动;但数值过大会导致预测的延迟

Lookahead Ignore Y:勾选后,不会预测目标垂直方向上的运动

Horizontal Damping:水平方向阻尼,值越大,虚拟相机旋转越慢

Vertical Damping:垂直方向阻尼,值越大,虚拟相机旋转越慢

(Dead Zone(死区)减小虚拟相机敏感程度,只要瞄准点(黄色的小方块)位于Dead Zone区域内,虚拟相机不做转动)

Screen X:Dead Zone的X轴中心位置(0.5为正中央)

Screen Y:Dead Zone的Y轴中心位置(0.5为正中央)

Dead Zone Width:Dead Zone宽度

Dead Zone Height:Dead Zone高度

(Soft Zone,当瞄准点(黄色的小方块)位于Soft Zone区域内,虚拟相机通过转动让瞄准点(黄色的小方块)回到Dead Zone内。Soft Zone永远大于等于Dead Zone)

Soft Zone Width:Soft Zone宽度

Soft Zone Height:Soft Zone高度

Bias X:Soft Zone的X轴偏移量

Bias Y:Soft Zone的Y轴偏移量

(最外层的红色区域是瞄准点(黄色的小方块)绝对不会落入的区域,虚拟相机会通过转动,让瞄准点(黄色的小方块)至少落在蓝色区域(Soft Zone)内)

Center On Activate:勾选后,当前虚拟相机被启用时,会将目标放在屏幕的正中央,否则会把目标放在最近的Dead Zone的边缘位置

③ Same As Follow Target

虚拟相机角度与跟随目标的角度保持一致。

(二)基于Rigidbody的角色控制器

1、角色控制器资源导入

复制一份项目,删除与Character Controller角色控制器相关的资源及脚本。

打开浏览器,下载Unity资源商店Rigidbody的第三人称角色控制器(下载链接见附录),通过Package Manager下载并导入。

Third Person Controller - Basic Locomotion FREE

2、分析源码

打开角色控制器场景。

运行项目,点击Game窗口,发现鼠标不会隐藏;按下键盘上的WASD或方向键移动角色,Shift+WASD或方向键冲刺,同时摄像机自动跟随;移动鼠标,控制摄像机旋转。

通过查看源码可知,vThirdPersonCamera.cs控制摄像机的相关逻辑,没有用到插件,vThirdPersonController.cs控制角色行为,vThirdPersonInput.cs获取角色输入。

故可以删除vThirdPersonCamera.cs脚本及ThirdPersonCamera_LITE摄像机预制体,替换为之前做好的摄像机预制体,并对角色控制器脚本中的逻辑进行改造。

3、准备工作

(1)名字调整

如图,修改预制体、脚本为对应的名字。(为了方便大家做对比,此处复制了一份,进行操作,操作时把导入的资源包先剪切到其他位置,防止重命名时受到影响)

(2)修复报错

由于删除了之前项目相关的脚本,故一些引用处会出现引用丢失的报错,修改对应的命名空间及类名。

CMVcamManager.cs:

PlayerController_RB.cs:

PlayerInputController_RB.cs:

删除 红色框 框选的代码。

在角色预制体上创建相关的对象:

由于角色模型运用了LOD技术,所以需要进行一些设置。

由于仅在第一人称视角时需要切换到部分透明的模型,所以只需要修改LOD 0层的网格,将其添加到LOD 0层。其他设置参数之前的做法,此处不做赘述。

将相关的对象挂载到脚本组件对应位置。

先注释CMVcam_1st.cs及CMVcam_3rd.cs中报错的旋转逻辑相关代码。

由于场景中角色的位置及坐标不是默认值,故在实例化对象时设置位置及坐标。

4、功能实现

(1)测试分析

全部设置好后,运行项目,发现除斜45度和俯视角等固定视角正常外,其他三种视角在旋转时出现问题。

(2)自由视角虚拟相机

经过测试,发现自由视角无法直接使用控制角色身上跟随目标方向的方案,会出现相机抖动的情况,跟随目标似乎受到除虚拟相机之外的逻辑控制,所以这里采用动态创建跟随目标的方案。那么可以删除角色身上的“FollowTarget_Free” 对象以及PlayerController_RB.cs和CMVcamManager.cs中的引用,替换为“FollowTarget_3rd”,因为它们的位置、方向是一样且都不会受到除父物体以外的影响。

CMVcam_Free.cs:

(3)第一人称视角虚拟相机

CMVcamManager.cs:

自由视角、斜45度视角、俯视角时,角色是由按键控制转身的,而第一人称视角是由鼠标控制转身,因此要锁定角色方向,通过“isStrafing”变量切换为“Strafe Locomotion”移动方式。

CMVcam_1st.cs:

与Character Controller的角色控制器中不同,由于没有其他地方控制角色转向,所以虚拟相机需要创建变量,命名为“_cinemachineTargetYaw”来控制角色X轴方向。

(4)第三人称过肩视角

实现思路:

与Character Controller的角色控制器相同,也要调整为WS或上下键控制角色前进、后退,AD或左右键控制角色旋转。并且需要添加专门的动画,可以前进、后退、向左旋转、向右旋转。

Rigidbody的角色控制器中已经实现了Strafe Locomotion移动方式,但AD或左右键是控制角色左右移动,而非旋转,因此需要修改脚本和动画。创建bool变量,命名为“CanRotate”,用来控制动画及相关逻辑的切换。

添加动画变量及新的混合树:

CMVcamManager.cs:

CMVcam_3rd.cs:

PlayerMotor_RB.cs:

附录

资源:

【Unity资源商店】最新第一人称角色控制器(Starter Assets - First Person Character Controller): https://assetstore.unity.com/packages/essentials/starter-assets-first-person-character-controller-196525

【Unity资源商店】最新第三人称角色控制器(Starter Assets - Third Person Character Controller):https://www.jianshu.com/go-wild?ac=2&url=https%3A%2F%2Fassetstore.unity.com%2Fpackages%2Fessentials%2Fstarter-assets-third-person-character-controller-196526

【Unity资源商店】第三人称角色控制器(Third Person Controller - Basic Locomotion FREE):https://assetstore.unity.com/packages/tools/game-toolkits/third-person-controller-basic-locomotion-free-82048

【动画资源】Mixamo动画资源网站(外网,加载会比较慢):https://www.mixamo.com/#/

Unity API:

Renderer.materials(英文):https://docs.unity3d.com/2020.3/Documentation/ScriptReference/Renderer-materials.html

Renderer.materials(中文):https://docs.unity.cn/cn/2020.3/ScriptReference/Renderer-materials.html

源码:

基于Character Controller角色控制器的摄像机系统源码:https://github.com/LeahLee13/UnityCameraSystem_CC

基于Rigidbody角色控制器的摄像机系统源码:https://github.com/LeahLee13/UnityCameraSystem_RB

效果演示:

【Unity】基于Cinemachine的第一/三人称过肩/自由/斜45度/俯视角摄像机系统演示: https://www.bilibili.com/video/BV1xF411A7PS/?vd_source=949e43fe30377952898533774f02e413