
在本文中3D天堂将向你提供一个如何在Unity中创建飞行模拟器相机系统的学习知识,首先我们需要创建一个摄像机。
创建摄像机
将在飞船驾驶舱中创建一个 pov 摄像机,并将其放置在想要的位置,Pov 摄像机需要是游戏对象的子对象,将其添加到驾驶舱内。

这个过程中,会在船后添加第三个人跟随相机。

缓存摄像机
这里需要在虚拟相机之间进行切换,因此创建此变量并缓存虚拟相机。
public class CameraManager : MonoBehaviour
{
[serializeField]
private CinemachineVirtualCamera[] _cameras;
[serializeField]
private int _currentCameraIndex;
[serializeField]
private bool _isCurrentCameraActive;
[serializeField]
private GameObject[]_shipviews;
private CinemachineVirtualCamera _currentCamera;
private void Awake()
{
foreach (var _VirtualCamera in _cameras)
{
_currentCamera = _VirtualCamera.GetComponent<CinemachineVirtualCamera>();
}
}
设置相机的优先级
游戏开始时,将要重置当前的相机索引和虚拟相机的优先级值,然后设置当前相机,然后再将 bool 变量设置为 true。
void Start()
{
_currentCameraIndex = 0;
SetPriorityDefault();
SetCurrentCamera();
_isCurrentCameraActive = true;
}
这是实现 SetPriorityDefault 的方法,这个方法的说明很少,没有检查当前的相机索引,因为想重置所有相机优先级值,然后将 bool 设置为 false。
注意:这里为什么要把这个 bool 设置为 false,因为要重置所有的摄像头,这意味着不再打算将之前的摄像头作为当前摄像头,看到输入逻辑你就会明白了。
public void SetPriorityDefault()
{
Debug.Log("what is the problem");
_currentCamera.Priority = 10;
_currentCamera.Priority = 10;
_isCurrentCameraActive = false;
}
在 SetCurrentCamera 中,需要确保为特定相机分配优先级值,设置相机优先级值后,需将 bool 设置为 true 以确保调用此方法一次以节省性能成本。
public void SetCurrentCamera()
{
switch (_currentCameraIndex)
{
case 0:
_cameras[_currentCameraIndex].Priority =15;
_isCurrentCameraActive = true;
break;
case 1:
_cameras[_currentCameraIndex].Priority =15;
_isCurrentCameraActive = true;
Debug.Log("Third Person Camera");
break;
}
}
添加逻辑
现在将向更新添加逻辑,先要检查键代码是否被按下,然后检查 iscurrentcamera 是否为真,因此需要增加 currentCamera 索引,然后重置所有摄像机优先级,以确保即使有 5 个摄像机,在分配当前摄像机时也不会出现摄像机渲染冲突。
这里会有疑问吧?为什么会发生冲突?因此第一个虚拟摄像头将接管主摄像头,因此如果没有将它们全部重置并赋予当前摄像头最高优先级,那么如果当前摄像头不是列表中较高的,则当前摄像头将不会接管主摄像头与以前的相机相比的层次结构。
注意:现在正在检查当前相机索引是否超出相机数组长度,如果超出绑定,则将重置当前相机索引。
void Update()
{
if (Input.GetKeyDown(KeyCode.R) &&_isCurrentCameraActive == true)
{
_currentCameraIndex++;
SetPriorityDefault();
if (_currentCameraIndex >=_cameras.Length)
{
_currentCameraIndex = 0;
}
SetCurrentCamera();
}
}
这是在虚拟相机之间交换的结果。

当在 pov 摄像机中时想禁用一件事,这艘船将在第三人称视角摄像机中禁用驾驶舱,所以添加了 ship and cockpit 和 on-ship views 数组变量。然后,当为特定的船舶部件设置当前相机时,需要启用其中之一。

public void SetCurrentCamera()
{
switch (_currentCameraIndex)
{
case 0:
_shipViews[_currentCameraIndex].SetActive(true);
_cameras[_currentCameraindex].Priority =15;
_isCurrentCameraActive = true;
break;
case 1:
_shipViews[_currentCameraIndex].SetActive(true);
_cameras[_currentCameraIndex].Priority = 15;
_isCurrentCameraActive = true;
Debug.Log("Third Person Camera");
break;
}
}
这是用于启用和禁用船舶部分的代码,以避免网格在彼此之上闪烁。
然后想在按下 R 时禁用前一部分,如果 currentcameraActive 为真,在增量之前这样做是为了确保不会关闭当前的相机船视图部分。
void Update()
{
if (Input.GetKeyDown(KeyCode.R)&& _isCurrentCameraActive == true)
{
_shipviews[_currentCameraIndex].SetActive(false);
_currentCameraIndex++;
SetPriorityDefault();
if (_currentCameraIndex >= _cameras.Length)
{
_currentCameraIndex= 0;
}
SetcurrentCamera();
}
}
例如下面的效果:

如果不想向玩家展示已经禁用了整艘船,要解决这个问题,需要更改虚拟相机之间的主相机混合状态。
请选择主摄像机,然后选择 Inspector → Cinemachine Brain → Custom Blend List,在这里单击显示创建资产的按钮。然后点击加号按钮添加拥有的摄像机数量,然后选择过渡类型。
由于想要隐藏禁用飞船,因此解决方案是选择剪切混合。

例如下面的效果:

创建电影序列
3D天堂将创建五个不同类型的虚拟摄像机,然后将它们添加到时间轴中以制作序列。

电影摄影机的逻辑
要检查玩家是否有 5 秒没有移动鼠标或者玩家是否有 5 秒没有按下任何按钮。
因此需要创建一个 vector3 变量来存储鼠标位置,然后将此变量分配给 Input to mouse position ins start 的方法,然后将创建 if 语句来检查时间过去了,如果玩家没有移动鼠标 5 秒,或者如果玩家在 5 秒内没有按下任何按钮。
注意:如果鼠标位置在同一个位置5秒表示玩家没有移动鼠标

void Start()
{
_currentCameraIndex = 0;
SetPriorityDefault();
SetCurrentCamera();
isCurrentCameraActive = true;
_temporaryMousePos = Input.mousePosition;
}
if (_temporaryMousePos == Input.mousePosition && Time.time >_canPlayCinematicCamera
|| !Input.anyKeyDown && Time.time > _canPlayCinematicCamera)
现在在上面的 if 条件之后要定义另一个 3 变量。
private float _canPlayCinematicCamera = 10.0f;
private float _timeRate = 10.of;
[SerializeField]
private PlayableDirector _cameracinematicDirector;
如果不想再次播放,只需进入 if condition 检查过场动画是否播放,然后添加时间以播放返回,如果希望它继续播放,需要返回。
在 else 语句中需要激活过场动画,然后播放和更新时间。
if (_cameracinematicDirector.state == PlayState.playing)
{
_canPlayCinematicCamera = Time.time + _timeRate;
return;
else
{
_cameracinematicDirector.gameObject.SetActive(true);
_cameracinematicDirector.Play();
_canPlayCinematicCamera = Time.time + _timeRate;
Debug.Log("Play Director: ");
}
想在玩家移动鼠标或按下任意键然后更新时间时禁用导演。
if (_temporaryMousePos != Input.mousePosition || Input.anyKeyDown)
{
_cameracinematicDirector.gameObject.SetActive(false);
_temporaryMousePos = Input.mousePosition;
_canPlayCinematicCamera = Time.time + _timeRate;
}
//when player hasnot moved the mouse
//or pressed a key within 5 seconds
//have cinematic camera
当玩过场动画时,希望船处于全视野而不是显示驾驶舱,所以在这里将禁用第一个全船视图。
else
{
_cameracinematicDirector.gameObject.SetActive(true);
_shipViews[0].SetActive(true);
_cameracinematicDirector.Play();
_canPlayCinematicCamera = Time.time + _timeRate;
Debug.Log("Play Director: ");
}
例如下面的最终效果:

…
以上是3D天堂关于制作飞行模拟器相机系统的全部内容,如果你有任何反馈,请随时在本页面下方留言。