找回密码
 立即注册
查看: 81|回复: 2

游戏控制的摄像机

[复制链接]
发表于 2019-7-10 21:19:09 | 显示全部楼层 |阅读模式
本帖最后由 harbinxxh 于 2019-7-10 21:21 编辑

了解如何激活和切换不同的视角。
本教程将会向您展示如何激活摄像机以及如何切换您激活的摄像机。


1 - 在场景中放置摄像机[backcolor=rgba(192, 255, 192, 0.25)]
[size=1em]如果您是 虚幻引擎4 (UE4)的新手,您可需要先阅读我们的编程快速入门教程。对于本教程,我们假设您熟悉以下操作:创建项目,向项目添加C++代码,编译代码,以及在UE4中向 Actor 添加 组件

  • [size=1em]我们将从创建一个新的基本代码项目开始,名为“HowTo_AutoCamera”,其中包含初学者内容。我们需要做的第一件事是在我们的场景中创建两个摄像机。由于设置摄像机有多种方法,在这里我们将使用最常见的两种方法。对于我们的第一个摄像机,前往 放置浏览器(Placement Browser) 中的 模式(Modes) 选项卡,单击 放置(Place) 或按 Shift+1。在 所有类(All Classes) 部分,您将找到一个 摄像机(Camera) Actor。将其拖拽到 关卡编辑器(Level Editor) 中,并将其放置在合适的位置,以便它能清楚地看到我们的场景。
    [size=1em]

                                   
    登录/注册后可看大图

    [size=1em]完成此操作后,只要我们选择了新的 摄像机Actor(Camera Actor)关卡编辑器(Level Editor) 窗口就会有一个画中画视图,显示该 摄像机Actor(Camera Actor) 可以看到的内容。
    [size=1em]

                                   
    登录/注册后可看大图
  • [size=1em]对于我们的第二个摄像机,我们将使用一种更深入的方法,让我们可以进行更多的控制。首先,单击 放置浏览器(Placement Browser)模式(Mode) 选项卡中的 基本(Basic),并将一个 立方体(Cube) 拖放到 关卡编辑器(Level Editor) 窗口中。
    [size=1em]

                                   
    登录/注册后可看大图
    [backcolor=rgba(245, 240, 217, 0.75)]
    [size=1em]在这一步骤中,我们几乎可以使用任何Actor类。用我们在快速入门教程中创建的MyActor类来替代立方体(Cube)可能会很有趣。


  • [size=1em]放置我们的 立方体(Cube) Actor后,单击 详细信息(Details) 面板中的 +添加组件(+ Add Component) 按钮,来为 立方体(Cube) 添加 摄像机组件(CameraComponent)。您现在可以设置该 摄像机组件(CameraComponent) 的位置和旋转,让我们看到一个不同于我们之前放置的 摄像机Actor(CameraActor) 的场景视图。
    [size=1em]

                                   
    登录/注册后可看大图
  • [size=1em]我们应该打开 约束高宽比(Constrain Aspect Ratio) 来自定义我们的 摄像机组件(CameraComponent),以便它与我们的 摄像机Actor(CameraActor) 上的设置匹配。这会使摄像机视图之间的转换更流畅,但这不是必需的。
    [size=1em]

                                   
    登录/注册后可看大图

设置好我们的场景后,我们现在可以开始创建控制摄像机视图的类。


回复

使用道具 举报

 楼主| 发表于 2019-7-10 21:25:32 | 显示全部楼层
2 - 在C++中控制摄像机视图

我们现在可以创建一个C++类来控制摄像机视图了。在本教程中,我们可以扩展 Actor 为新类,我们将其称之为CameraDirector。
NameActorClass.png

在CameraDirector.h中,我们将以下代码添加到ACameraDirector类定义的底部位置:
  1. UPROPERTY(EditAnywhere)
  2. AActor* CameraOne;

  3. UPROPERTY(EditAnywhere)
  4. AActor* CameraTwo;

  5. float TimeToNextCameraChange;
复制代码


在CameraDirector.cpp中,将以下代码行添加到文件的顶部位置,位于其它#include行的正下方:
  1. #include "Kismet/GameplayStatics.h"
复制代码


GameplayStatics头文件允许我们访问一些有用的通用函数,在本教程中我们需要使用其中一个函数。完成后,将以下代码添加到 ACameraDirector::Tick 的底部位置:
  1. const float TimeBetweenCameraChanges = 2.0f;
  2. const float SmoothBlendTime = 0.75f;
  3. TimeToNextCameraChange -= DeltaTime;
  4. if (TimeToNextCameraChange <= 0.0f)
  5. {
  6.     TimeToNextCameraChange += TimeBetweenCameraChanges;

  7.     // 查找处理本地玩家控制的actor。
  8.     APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0);
  9.     if (OurPlayerController)
  10.     {
  11.         if ((OurPlayerController->GetViewTarget() != CameraOne) && (CameraOne != nullptr))
  12.         {
  13.             // 立即切换到摄像机1。
  14.             OurPlayerController->SetViewTarget(CameraOne);
  15.         }
  16.         else if ((OurPlayerController->GetViewTarget() != CameraTwo) && (CameraTwo != nullptr))
  17.         {
  18.             // 平滑地混合到摄像机2。
  19.             OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime);
  20.         }
  21.     }
  22. }
复制代码


现在我们的代码可进行编译,我们可以返回到 虚幻编辑器(Unreal Editor) 并按下 编译(Compile) 按钮。
无需其它代码。我们现在可以在场景中设置CameraDirector了。

完成的代码

MyPawn.h
  1. // 版权所有 1998-2017 Epic Games, Inc。保留所有权利。

  2. #pragma once

  3. #include "GameFramework/Actor.h"
  4. #include "CameraDirector.generated.h"

  5. UCLASS()
  6. class HOWTO_AUTOCAMERA_API ACameraDirector : public AActor
  7. {
  8.     GENERATED_BODY()

  9. public:
  10.     // 为此Actor的属性设置默认值
  11.     ACameraDirector();

  12. protected:
  13.     // 当游戏开始或生成时调用
  14.     virtual void BeginPlay() override;

  15. public:
  16.     // 每一帧调用
  17.     virtual void Tick( float DeltaSeconds ) override;

  18.     UPROPERTY(EditAnywhere)
  19.     AActor* CameraOne;

  20.     UPROPERTY(EditAnywhere)
  21.     AActor* CameraTwo;

  22.     float TimeToNextCameraChange;
  23. };
复制代码



回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-7-10 21:27:22 | 显示全部楼层
3 - 在场景中放置Camera Director

在代码编译完成后,我们可以将 内容浏览器(Content Browser) 中的新类的实例拖曳到 关卡编辑器(Level Editor) 中。
CameraDirectorInContentBrowser.png

接下来,我们需要设置摄像机1(CameraOne)和摄像机2(CameraTwo)变量。在 World Outliner (世界大纲视图) 中找到CameraDirector,并在 详细信息面板(Details Panel) 中进行编辑。
CameraDirectorDetails.png

单击标记为“无(None)”的下拉框,然后将变量设置为 Cube(立方体) 和我们之前创建的 摄像机Actor (CameraActor)。

CameraDirectorDetails2.png

如果我们按下播放(Play),我们将会看到与此视图对齐的摄像机:
CameraOneView.png

然后平滑混合到此视图:

CameraTwoView.png

需要等待几秒才会对齐。

我们现在的这个系统会完全基于游戏逻辑来移动玩家的摄像机。如果玩家在游戏中无法直接控制摄像机,或者混合摄像机视图十分有用时,我们可以修改代码以在这些游戏中使用。

完成的代码

MyPawn.h
  1. // 版权所有 1998-2017 Epic Games, Inc。保留所有权利。

  2. #pragma once

  3. #include "GameFramework/Actor.h"
  4. #include "CameraDirector.generated.h"

  5. UCLASS()
  6. class HOWTO_AUTOCAMERA_API ACameraDirector : public AActor
  7. {
  8.     GENERATED_BODY()

  9. public:
  10.     // 为此Actor的属性设置默认值
  11.     ACameraDirector();

  12. protected:
  13.     // 当游戏开始或生成时调用
  14.     virtual void BeginPlay() override;

  15. public:
  16.     // 每一帧调用
  17.     virtual void Tick( float DeltaSeconds ) override;

  18.     UPROPERTY(EditAnywhere)
  19.     AActor* CameraOne;

  20.     UPROPERTY(EditAnywhere)
  21.     AActor* CameraTwo;

  22.     float TimeToNextCameraChange;
  23. };
复制代码


MyPawn.cpp
  1. // 版权所有 1998-2017 Epic Games, Inc。保留所有权利。

  2. #include "HowTo_AutoCamera.h"
  3. #include "CameraDirector.h"
  4. #include "Kismet/GameplayStatics.h"

  5. // 设置默认值
  6. ACameraDirector::ACameraDirector()
  7. {
  8.     // 将此Actor设置为每一帧调用Tick()。如果不需要,可以关闭此选项来提高性能。
  9.     PrimaryActorTick.bCanEverTick = true;

  10. }

  11. // 当游戏开始或生成时调用
  12. void ACameraDirector::BeginPlay()
  13. {
  14.     Super::BeginPlay();

  15. }

  16. // 每一帧调用
  17. void ACameraDirector::Tick( float DeltaTime )
  18. {
  19.     Super::Tick( DeltaTime );

  20.     const float TimeBetweenCameraChanges = 2.0f;
  21.     const float SmoothBlendTime = 0.75f;
  22.     TimeToNextCameraChange -= DeltaTime;
  23.     if (TimeToNextCameraChange <= 0.0f)
  24.     {
  25.         TimeToNextCameraChange += TimeBetweenCameraChanges;

  26.         //查找处理本地玩家控制的Actor。
  27.         APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0);
  28.         if (OurPlayerController)
  29.         {
  30.             if (CameraTwo && (OurPlayerController->GetViewTarget() == CameraOne))
  31.             {
  32.                 //平滑地混合到摄像机2。
  33.                 OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime);
  34.             }
  35.             else if (CameraOne)
  36.             {
  37.                 //立即切换到摄像机1。
  38.                 OurPlayerController->SetViewTarget(CameraOne);
  39.             }
  40.         }
  41.     }
  42. }
复制代码

4 - 自主操作!

利用您所学到知识,尝试执行以下操作:

将摄像机附加到移动Actor上来创建摇臂或移动车镜头。
使用一个数组变量来存储摄像机,而不是摄像机1(CameraOne)和摄像机2(CameraTwo),这样您就可以遍历任意数量摄像机的序列,而不是仅仅两个。
不要使用Actor指针来存储摄像机,而是创建一个结构来保持指针以及在更改视图之前的时间,并将时间混合到新视图中。
有关本教程介绍的细节:

有关摄像机以及其控制方法的更多信息,请参阅摄像机框架页面,或尝试玩家控制的摄像机教程。
有关进一步教程,请参阅[C++编程教程]页面。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|虚拟现实  

GMT+8, 2019-7-21 11:00 , Processed in 0.053045 second(s), 19 queries .

快速回复 返回顶部 返回列表