在游戏中,摄像头的效果是非常重要的,将会直接影响到呈现在玩家眼中的画面,好的效果可以直接提高玩家的游戏体验,给予一种身临其境的感觉。例如在一个FPS游戏中,我们往往需要摄像头跟随我们的角色,做一些第一人称第三人称的切换,当角色进入室内时需要调整摄像头位置来防止被墙挡住,在使用倍镜时需要摄像头观察远处的画面等等。以为要实现这些效果我们需要编写很多的控制代码来控制我们的Camera,然而再有了Cinemachine之后,一切都会变得简单起来。
Cinemachine是Unity在2017版本推出的一套处理Camera的组件,利用Cinemachine我们可以不通过敲代码就实现很多摄像机功能。例如上面提到的那些需求,Cinemachine都可以帮我们快速的实现,此外我们还可以利用Cinemachine加上Timeline,做一些过场动画等效果。
官方文档:https://docs.unity3d.com/Packages/[email protected]/manual/index.html
我们可以通过Package Manager来安装Cinemachine(如下左图),安装好后,在我们的Unity工具栏就会多出一项Cinemachine的选项供我们使用(如下右图)。
注:文章中使用的是Cinemachine2.6的版本,需要Unity版本为2018.4.17f1或者更新。
安装好Cinemachine后,我们来看看点击Cinemachine菜单下的 Create Virtual Camera 之后会发生什么,可以发现我们场景中多了一个名为 CM vcam1 的GameObject,挂载着 CinemachineVirtualCamera 组件(如下左图,后续称为VirtualCamera)。同时我们的Main Camera身上也多了一个 CinemachineBrain 组件(如下右图),这两个组件就是我们Cinemachine的核心了。
接着我们在场景中新建一个Cube,将这个Cube拖到VirtualCamera的Follow和Look At的设置当中。此时就会发现,我们的Main Camera看向了我们的Cube,并且当我们移动Cube的时候,Camera也会跟着一起移动。
没有写一行代码,就实现了最简单的Camera跟随物体的功能了!
接着,我们创建第二个VirtualCamera(CM vcam2),此时画面会变为新的VirtualCamera看见的画面。我们调整该VirtualCamera的坐标和旋转,从另个角度看向Cube,例如下图。
然后我们隐藏该VirtualCamera,会重新显示CM vcam1的画面,然后运行Unity。运行后,我们再将CM vcam2设为active状态,此时可以发现,我们的画面会从CM vcam1切换到CM vcam2,例如下图:
这个过程我们称之为Blend,没有代码就实现了镜头切换(混合)的效果。
CinemachineVirtualCamera是Cinemachine的核心组件之一,前面我们利用了其Follow和Look At就简单的实现了Camera的跟随和看向物体的功能,接下来我们来详细的看看它各个设置的作用。
先来看看如下图这些基础设置的含义
在任何时间,我们的VirtualCamera都处于下面三种状态中的一种:
Live | 当前控制着Camera(带有CinemachineBrain组件)的VirtualCamera,即处于Live状态。当一个VirtualCamera混合到另一个时,该过程中,两个VirtualCamera都处于Live状态,当混合结束或者其他情况下,同一时刻内只会存在一个Live状态下的VirtualCamera。 |
Standby | 没有控制着Camera的VirtualCamera,即处于Standby状态。该状态下的VirtualCamera还是会一直跟随和看向设置的目标,并且每帧都会更新。该状态下的VirtualCamera属于激活状态(active与enable等于true),并且其 priority 的值小于或等于Live状态的VirtualCamera。 注:2.6.3新增StandbyUpdate设置,可以设置更新频率(详情见下) |
Disabled | 当VirtualCamera属于未激活状态(active或enable等于false),即处于Disable状态。该状态下没有任何的性能消耗,即不会控制Camera,不会跟随目标,不会每帧更新等。不过如果该VirtualCamera参与混合或者被Timeline调用,那么依旧可以控制Camera |
Solo按钮:选中该按钮,可以将当前的VirtualCamera临时的设置为Live状态,帮助我们查看对应的镜头效果。
开启后,会在Game视图中显示一些辅助线(如下图)。这些辅助线会在VirtualCamera看向(Look At)一个指定的GameObject并且Aim设置为Composer或Group Composer或者跟随(Follow)一个指定的目标并且Body设置为Framing Transposer时出现。
注:该设置应用于所有的VirtualCamera,例如我们在其中一个VirtualCamera开启或关闭该功能,那么所有的VirtualCamera的该项设置都会开启或关闭。
我们来了解下这些区块的含义:图中的透明区域我们称之为dead zone,蓝色的区域称之为soft zone,红色的区域称之为no pass area,而图中的小黄点就是我们的target。我们可以在Game视图将鼠标放置在每个区域的分割线上,然后按住拖动,来调整每个区域的大小。也可以在Aim中进行更精确的设置,在后续的介绍中会提及到。
dead zone:当我们的target(小黄点)在这个区域时,VirtualCamera不会调整rotation值。适用于忽略target进行一些微小的移动的情况。
soft zone:当我们的target进入到这个区域时,VirtualCamera将会通过调整rotation值,重新把target放回到dead zone。这步操作的快慢,我们可以通过Damping来设置。
no pass area:我们的target永远不会进入到这个区域。
开启后,可以在运行状态下直接保存我们对VirtualCamera设置的修改,而不需要我们通过复制粘贴的方式来记住这些修改了的属性。
当我们停止运行时,会扫描我们修改过的属性进行保存,我们可以使用ctrl+z来回退这些修改。
注:和Game Window Guides一样,是一个应用于所有VirtualCamera的设置。
Cinemachine为我们提供了一个标签 [SaveDuringPlay] ,可以支持上述特征。我们可以将这个标签加在我们的自定义组件中,来实现运行时保存修改。此外若我们组件中有些属性不想保存修改的值,可以在属性前面添加 [NoSaveDuringPlay] 来过滤。例如:
[SaveDuringPlay]
public class MyComponent : MonoBehaviour
{
public int a;
[NoSaveDuringPlay] public string b;
}
权重,值越大说明优先权越高。例如:一个非Live状态的VirtualCamera,当其Priority值大于等于当前Live状态下VirtualCamera并且自己属于激活状态,那么CinemachineBrain会选择它作为新的Live状态的VirtualCamera。
注:使用Timeline处理VirtualCamera时,该属性不起作用
跟随目标,即VirtualCamera会跟着设置的目标移动而移动。会根据Live状态的VirtualCamera所设置的目标结合Body中的设置来更新Camera的Position。若不设置目标,Camera的Position就会与VirtualCamera同步。例如我们可以用Timeline来给VirtualCamera添加动画,然后Camera也会产生相同效果。
看向目标,即Camera看向的目标(Transform.LookAt)。会根据Live状态的VirtualCamera所设置的目标结合Aim中的设置来更新Camera的Rotation。若不设置目标,Camera的Rotation就会与VirtualCamera同步。
设置处于Standby状态的VirtualCamera的更新频率(2.6.3新增),有如下三个选项
Always | 每帧更新 |
Never | 不更新 |
Round Robin | 偶尔更新,具体更新频率取决于Standby状态的VirtualCamera数量 |
如下三个设置和Camera中的相同设置所对应,Camera中的值会跟此同步。例如一个带有CinemachineBrain的Camera,当它对应的Live状态的VirtualCamera的FOV值改为77,那么Camera中的FOV值也会相应的变为77。
Field Of View | FOV,控制Camera的视窗大小 |
Near Clip Plane | Camera最近能看见的距离 |
Far Clip Plane | Camera最远能看见的距离 |
Presets:在Field Of View右侧有个小的下拉框,点击Edit Presets可以新建或修改用做预设的Asset文件。Lens Presets Asset文件内容如下:
Presets可以帮助我们快速的设置FOV等属性。
Dutch:用于修改Camera中Rotating的z轴值,取值范围 -180~180 。
2.6.3新增
BlendHint
从最开始的例子中可以看见,当一个VirtualCamera混合到另一个VirtualCamera的过程中,Camera会有一个行径的路线,并且伴随着Camera的旋转。该设置可以选择混合到该VirtualCamera或从该VirtualCamera混合到别的时的路线方式。
None | 坐标和朝向以一种标准的线性混合 |
SphericalPosition | 如果两个VirtualCamera有共同的LookAt目标,那么坐标的行径路线会像在圆的面上一样。 |
CylindricalPosition | 如果两个VirtualCamera有共同的LookAt目标,那么坐标的行径路线会像在圆柱的面上一样。 |
ScreenSpaceAimWhenTargetsDiffer | Standard linear position blend, radial blend between LookAt targets |
Inherit Position:开启时,当VirtualCamera状态变为Live时,则会继承上一个Live状态的VirtualCamera的Position信息。
On Camera Live:回调
Body的设置主要用于指定VirtualCamera的移动规则,主要有如下七大类:
Do nothing | 不移动VirtualCamera |
3rd Person Follow | 适用于第三人称或第一人称的跟随效果 |
Framing Transposer | 根据Follow设置的目标,以固定的屏幕空间关系移动 |
Hard Lock To Target | 根据Follow设置的目标,以固定的关系移动 |
Orbital Transposer | 根据Follow设置的目标,以可变的关系移动,例如可以选择接收玩家的输入 |
Tracked Dolly | 沿着预先设置的路径移动 |
Transposer | 根据Follow设置的目标,以固定的关系移动 |
由于不同的设置扩展出来的参数非常之多,这边就不做过多的介绍了,简单介绍几个常见的设置,其他设置请大家自行查阅文档,若后续有使用到也会进行介绍。
该选项主要影响VirtualCamera的偏移(Offset)和阻尼(Damping)的计算方式,有以下几种坐标空间供选择:
Lock To Target | VirtualCamera相对于Follow目标的模型空间计算偏移,当目标旋转,Camera也会跟着旋转,保持偏移量不变。 |
Lock To Target With World Up | 与Lock To Target不同的是,该模式下会忽略模型的x和z的转动,只有y轴转动时,Camera才会跟着旋转 |
Lock To Target No Roll | 与Lock To Target不同的是,该模式下会忽略模型的z的转动,当x或y轴转动时,Camera会跟着旋转 |
Lock To Target On Assign | 测试时感觉和Lock To Target没什么区别,待定。。。 |
World Space | VirtualCamera在世界坐标中相对于Follow目标原点的计算偏移,当目标旋转时,VirtualCamera的位置不会发生变化 |
Simple Follow With World Up | VirtualCamera在世界坐标中相对于Follow目标在世界坐标中移动的方向的计算偏移和阻尼(不受在Y轴移动影响),例如一开始Camera在目标的世界坐标z轴负方向位置,当目标向世界坐标x轴正方向移动时,Camera会慢慢移动到目标的世界坐标x轴负方向位置。类似于小弟在屁股后面跟着的效果 |
注:单独测试跟随效果的时候最好不要设置Look At目标,以防干扰。
阻尼,数值越小,Camera响应的越快。当Damping设置为0时,Camera会和目标同步运动,若Damping大于0,Camera的运动会慢于目标。
X Damping | 维持offset的x轴值时的阻尼 |
Y Damping | 维持offset的y轴值时的阻尼 |
Z Damping | 维持offset的z轴值时的阻尼 |
Pitch Damping | 当目标沿自身x轴转动时,Camera跟随目标时的阻尼 |
Yaw Damping | 当目标沿自身y轴转动时,Camera跟随目标时的阻尼 |
Roll Damping | 当目标沿自身z轴转动时,Camera跟随目标时的阻尼 |
Aim的设置主要用于指定VirtualCamera的旋转规则,主要有如下六大类:
Do nothing | 不对Virtual Camera做任何旋转 |
Composer | 保持Camera始终看向目标 |
Group Composer | 可以使Camera看向多个目标,如果看向的目标是Cinemachine Target Group,会自动调整Camera的FOV和距离,来确保组里的所有对象都能被看见 |
Hard Look At | 保持Look At的目标始终在屏幕中间,该选项没有额外的设置 |
POV | 通过用户输入来旋转Virtual Camera |
Same As Follow Target | Virtual Camera的Rotation值保持和Follow目标的Rotation值相同(因此使用此模式必须设置Follow目标)。如果我们Body选择的是Hard Lock to Target,那么就可以通过Follow的目标来控制Camera的路径和旋转 |
同样的,我们先来看看最常见的Composer模式下的各项设置的含义:
在目标的对象空间中,相对于目标中心点的偏移。
基于目标的运动轨迹调整偏移,会估算未来几秒(即我们设置的这个时间)内目标的位置。该特征对噪点动画(noise)非常敏感,会放大噪声导致相机不正常的抖动。若无法接受该抖动,请关闭该属性,或者让目标的运动轨迹更加平滑。
平滑值,较大的值可以使抖动预测的更加平滑,但是也会增加预测的延时。
计算时是否忽略Y轴上的移动。
水平或垂直的阻尼,这会影响到目标中心从soft zone到dead zone的速度。(有关soft zone和dead zone的信息可以看上面Game Window Guides相关的介绍)若Damping设置为0,则中心点永远不会到soft zone。
soft zone和dead zone在屏幕中的位置,使用的是屏幕空间。
调整dead zone的宽度和高度。
调整soft zone的宽度和高度。
soft zone相对于dead zone的偏移。
若开启,当VirtualCamera被激活时,强制目标在屏幕的中心点。
噪点,使用该属性可以利用Virtual Camera模拟Camera抖动的效果。Cinemachine中有一个名为 Basic Multi Channel Perlin 的组件,可以利用Perlin noise来移动Virtual Camera(Perlin noise是一种可以通过自然行为计算随机运动的技术)。
Basic Multi Channel Perlin组件需要设置一个配置文件,每个配置文件都属于一个Asset,用来定义随着时间变化的噪点行为。
Cinemachine自带了几个配置文件,我们可以编辑它们或者创建自己的配置文件,内容如下:
当相机因为抖动旋转时,偏移相机中心点的坐标。(2.6.3新增)
振幅,该值会与Profile中设置的Amplitude值相乘,例如设置为1,等于使用Profile中设置的Amplitude。
Amplitude值越大,则抖动的幅度会越大。
频率,该值会与Profile中设置的Frequency值相乘,例如设置为1,等于使用Profile中设置的Frequency。
Frequency值越大,则抖动的速度会越快。
该部分内容较多,留到后续讲解。
CinemachineBrain是Cinemachine中另一个核心组件,可以称之为大脑。它挂载在Camera上,监控着场景中所有active状态(Live和Standby)的VirtualCamera。若一个inactive状态的VirtualCamera,其Priority值大于等于当前Live状态的VirtualCamera,当我们将其设置为active状态,那么CinemachineBrain就会选择它作为新的Live状态的VirtualCamera。我们可以使用这种方法来实现镜头的切换。
注:我们也可以使用Timeline来控制VirtualCamera,这种情况Timeline的处理逻辑会覆盖CinemachineBrain的。
CinemachineBrain的设置如下:
开启后会在Game视图中显示当前Live状态下的VirtualCamera的文本信息,如图:
开启后在Scene视图中会始终显示Camera的视锥体。
使VirtualCamera响应用户的输入和阻尼时忽视TimeScale的设置。
用于指定VirtualCamera在世界空间中向上的向量,若为空,则为世界空间中Y轴的方向,即 (0, 1, 0)。否则使用设置的目标的Y轴的方向。使用好该设置对于避免万向节锁(gimbal-lock)非常重要。
VirtualCamera更新位置和旋转的方式
Fixed Update | VirtualCamera的更新与物理模块同步 |
Late Update | 在MonoBehaviour的LateUpdate中更新 |
Smart Update | 每个VirtualCamera根据其目标的更新方式来更新,推荐使用。 |
Manual Update | VirtualCamera不会自动更新,必须我们手动的调用ManualUpdate()来更新(应该在Camera跟随或看向的目标移动后调用) |
注:Smart Update具体是通过UpdateTracker实现的。在一定时间内(UpdateStatus.kWindowSize = 30,即30帧内),通过调用UpdateTracker.OnUpdate(UpdateTracker.UpdateClock),可以计算出VirtualCamera的目标在fixedUpdate移动次数多还是在lateupdate移动的次数多,用来判断下一段时间用fixedUpdate还是lateUpdate。具体可以看UpdateTracker.OnUpdate方法。
主摄像机混合和更新的时机
Fixed Update | 仅在Update Method使用的是Fixed Update并且在混合时发现剧烈震动时使用 |
Late Update | 在MonoBehaviour的LateUpdate中出来,推荐使用 |
用于设置两个VirtualCamera混合的方式,除Cut外,其它方式可在后面设置一个混合的持续时间。
Cut | 瞬切,立马显示下个VirtualCamera的画面 |
Ease In Out | S型曲线,混合开始和结束时比较平滑(慢->匀速->慢) |
Ease In | 混合结束时比较平滑(匀速->慢) |
Ease Out | 混合开始时比较平滑,然后匀速到结束(慢->匀速) |
Hard In | 混合开始时很很慢(从超级慢开始加速) |
Hard Out | 混合结束时很很慢(从较快速度减速到超级慢) |
Linear | 匀速移动 |
Custom | 自定义混合曲线 |
在前面的设置中,设置的是所有的VirtualCamera的混合方式,但是假如当我们的场景中有多个VirtualCamera,并且不同的VirtualCamera之间的混合方式不尽相同的时候,就需要通过该属性来设置不同VirtualCamera之间的混合方式了。会生成一个Asset用来存储数据,具体设置如下。
需要注意的是,在From和To中设置的是VirtualCamera的名称,也就是一个字符串,而非是VirtualCamera的引用。我们可以通过设置内置的**ANY CAMERA**来代表任何一个VirtualCamera。
当要执行Blend操作时,首先会从Custom Blends中查找匹配项,若没有,则使用Default Blend的设置。若有多条匹配项,则优先选择最符合要求的。(例如vc1混合到vc2,一项是From:vc1,To:vc2,一项是From:vc1,To:ANY CAMERA,那么前面那项是更符合要求的,会被使用)若有多条最符合要求的,则选择最先找到的那一条。
当一个VirtualCamera变为Live状态,并且其混合方式为Cut的情况下触发
brain.m_CameraCutEvent.AddListener(CameraCutEvent);
void CameraCutEvent(CinemachineBrain brain)
{
Debug.Log(brain);
}
当一个VirtualCamera变为Live状态时触发,若带有混合,则触发在混合开始的第一帧。
brain.m_CameraActivatedEvent.AddListener(CameraActivatedEvent);
//第一个参数为新的Live状态的VirtualCamera,第二个参数为上一个Live状态的VirtualCamera
void CameraActivatedEvent(ICinemachineCamera liveCamera, ICinemachineCamera lastCamera)
{
Debug.Log(liveCamera);
Debug.Log(lastCamera);
}
Cinemachine鼓励我们多创建VirtualCamera,因为VirtualCamera只会消耗很小的性能。我们可以将除了正在使用的VirtualCamera都关闭,来达到最佳的性能。
也建议一个镜头使用一个VirtualCamera,例如两个角色对话的过场动画,我们可以使用三个VirtualCamera,一个看向两个角色中间,另外两个分别给角色特写,然后利用Timeline来同步声音和VirtualCamera。例如一开始开启着看向屏幕中间的VirtualCamera,当其中一个角色需要单独特写的时候,再开启对应的VirtualCamera,当不需要特写的时候关闭,镜头就又会回到看向屏幕中间的VirtualCamera。
暂时先只介绍了具体参数含义,后续将介绍更多的使用情景