当你运行我们上次做完的项目,你可能会意识到我们移动的摄像机还是默认的那个摄像机,这个默认的摄像机可以自由飞翔。这一节,我们要使得开始的角色是我们的一个Avatar类的实例对象,并且使用键盘控制我们的角色。

创建游戏模式类

1. 创建游戏模式的步骤如下:
1) 点击文件 --> 新建C++类。
2) 选择Game Mode(游戏模式)。
3) 将其命名为“MyGameMode1”。
4) 点击创建类。

什么是GameMode?GameMode包含了各种各样的游戏规则和让游戏引擎描述这个游戏是怎么玩的。

2. 创建游戏模式的蓝图
UE4会自动启动VS开发环境,然后我们来创建MyGameMode1蓝图:

1) 如图所示操作:

2) 填写蓝图名称,我这里是“BP_GameMode1”,然后点好。

3) 从右侧的细节面板中的Default Pawn Class的下拉选项中选择上次我们创建好的角色蓝图BP_Avatar。

什么是Default Pawn Class?Default Pawn Class就是被角色使用的那一类物体,也就是可以被玩家控制的Actor角色。

4) 点击工具栏的保存,然后退出。

现在运行游戏的话,你可以看到我们使用的摄像头已经是BP_Avatar角色所包含的摄像头了。但是现在还是控制不了角色,因为我们还没设置控制器输入。

设置检测键盘输入

1) 点击工具栏的设置,然后点击项目设置。

2) 接下来,点击左侧面板的输入,然后在Axis Mappings(按键映射)后面点击加号,再点击前面的小三角形展开。输入一个名为Forward(前进)的按键映射,然后下面选择W键。接着再添加一个名为Back(后退)的按键映射,然后下面选择D键。Left(左移)对应A键,Right(右移)对于D键。

3) 直接关闭该窗口以保存设置。

通过C++代码控制角色行走

1) 现在打开你的VS里面的Avatar.h构造器,添加五个成员函数的声明:

  1. //添加如下三个成员函数,用于角色控制:
  2. void SetupPlayerInputComponent(class UInputComponent* InputComponent) override; //覆写虚函数,当有输入的时候被调用以绑定功能
  3. void MoveForward(float amount);
  4. void MoveBack(float amount);
  5. void MoveLeft(float amount);
  6. void MoveRight(float amount);

并删除原有的这一行:

virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;

2) 然后在Avatar.cpp完成函数体定义:

  1. //游戏开始时被调用以绑定设备输入功能
  2. void AAvatar::SetupPlayerInputComponent(class UInputComponent* InputComponent)
  3. {
  4. check(InputComponent); //检查空指针
  5. InputComponent->BindAxis("Forward", this, &AAvatar::MoveForward);
  6. InputComponent->BindAxis("Back", this, &AAvatar::MoveForward);
  7. InputComponent->BindAxis("Left", this, &AAvatar::MoveRight);
  8. InputComponent->BindAxis("Right", this, &AAvatar::MoveRight);
  9. }

上面的InputComponent::BindAxis(...)函数用于将按键信息于函数调用绑定。例如当玩家按下W键,引擎就会检测到有我们之前命名的"Forward"按键信息,然后自动去调用当前类的AAvatar::MoveForward(float amount)函数。其它三个按键也是如此运作。所以接下来定义好这四个函数就可以了,这里的参数amount是设备输入量经过与scale相乘后得出的结果:

  1. void AAvatar::MoveForward(float amount)
  2. {
  3. // Controller控制器当前拥有该actor。例如如果当前角色死了,actor不存在了,此时Controller控制器没有拥有任何一个actor,那么如果我们还想去控制它,就会出错。
  4. // 如果控制器没有拥有actor或者移动量是0,不能进入该函数。
  5. if (Controller && amount)
  6. {
  7. // GetActorForwardVector()取得角色向前的向量
  8. FVector fwd = GetActorForwardVector();
  9. // 我们调用AddMovementInput来在‘fwd’向量的方向上移动角色‘amount’个单位
  10. AddMovementInput(fwd, amount);
  11. }
  12. }
  13. void AAvatar::MoveBack(float amount)
  14. {
  15. if (Controller && amount)
  16. {
  17. // GetActorForwardVector()取得角色向前的向量,加上负号,该向量就向后,所以取得了角色向后的向量
  18. FVector back = -GetActorForwardVector();
  19. AddMovementInput(back, amount);
  20. }
  21. }
  22. // 后面的函数类似前面,很容易懂
  23. void AAvatar::MoveLeft(float amount)
  24. {
  25. if (Controller && amount)
  26. {
  27. FVector left = -GetActorRightVector();
  28. AddMovementInput(left, amount);
  29. }
  30. }
  31. void AAvatar::MoveRight(float amount)
  32. {
  33. if (Controller && amount)
  34. {
  35. FVector right = GetActorRightVector();
  36. AddMovementInput(right, amount);
  37. }
  38. }

设置检测鼠标移动

接下来我们用第二步同样的操作打开项目设置并添加Yaw和Pitch按键信息,分别对应的是鼠标的X坐标和Y坐标。

注意Yaw的意思是绕竖轴旋转,Pitch的意思是绕横向轴旋转。见下图:

通过C++代码控制角色镜头

在Avatar.h你需要添加两个函数声明:

  1. void Yaw(float amount);
  2. void Pitch(float amount);

然后在Avatar.cpp中实现它们:

  1. void AAvatar::Yaw(float amount)
  2. {
  3. if (Controller && amount)
  4. {
  5. // AddControllerYawInput()函数用于改变控制器的Yaw变量,即增加纵向轴旋转量。
  6. // GetWorld()函数取得世界指针UWorld*,通过世界指针调用GetDeltaSeconds()取得每帧耗费的时间。
  7. // 之所以要乘以每帧耗费的时间,是为了使得每一【秒】都增加200.0f * amount的改变量。
  8. // 如果不乘以每帧耗费的时间,那么每一【帧】都会增加200.0f * amount的改变量。(注意由于每秒渲染量不同,所以每秒的帧数不一定是固定的。)
  9. // 通过帧数来控制变量,那么游戏看起来就不那么流畅。试想,机子性能好的时候游戏角色动作就迅速,机子性能差的时候游戏角色动作就慢,这对于玩家公平吗?
  10. AddControllerYawInput(200.f * amount * GetWorld()->GetDeltaSeconds());
  11. }
  12. }
  13. // 下面的函数与上面雷同,不再赘述
  14. void AAvatar::Pitch(float amount)
  15. {
  16. if (Controller && amount)
  17. {
  18. AddControllerPitchInput(200.f * amount * GetWorld()->GetDeltaSeconds());
  19. }
  20. }

在void AAvatar::SetupPlayerInputComponent(class UInputComponent* InputComponent)函数体的下面添加这两条语句将输入信息和函数绑定:

  1. InputComponent->BindAxis("Yaw", this, &AAvatar::Yaw);
  2. InputComponent->BindAxis("Pitch", this, &AAvatar::Pitch);

完整代码贴出

Avatar.h完整代码如下:

  1. #pragma once
  2. #include "GameFramework/Character.h"
  3. #include "Avatar.generated.h"
  4. UCLASS()
  5. class DEMO1_API AAvatar : public ACharacter
  6. {
  7. GENERATED_BODY()
  8. //添加如下五个成员函数,用于角色控制:
  9. void SetupPlayerInputComponent(class UInputComponent* InputComponent) override; //覆写,游戏开始时被调用以绑定设备输入功能
  10. void MoveForward(float amount);
  11. void MoveBack(float amount);
  12. void MoveLeft(float amount);
  13. void MoveRight(float amount);
  14. void Yaw(float amount);
  15. void Pitch(float amount);
  16. public:
  17. // 设置角色属性的默认值
  18. AAvatar();
  19. // 当游戏开始的时候被调用
  20. virtual void BeginPlay() override;
  21. // 每帧被调用
  22. virtual void Tick( float DeltaSeconds ) override;
  23. };

Avatar.cpp完整代码如下:

  1. #include "Demo1.h"
  2. #include "Avatar.h"
  3. // 设置默认值
  4. AAvatar::AAvatar()
  5. {
  6. // 设置这个角色每帧调用Tick()。 如果不需要的话你可以关掉它以提高性能。
  7. PrimaryActorTick.bCanEverTick = true;
  8. }
  9. // 当游戏开始时调用它
  10. void AAvatar::BeginPlay()
  11. {
  12. Super::BeginPlay();
  13. }
  14. // 每帧被调用
  15. void AAvatar::Tick( float DeltaTime )
  16. {
  17. Super::Tick( DeltaTime );
  18. }
  19. //游戏开始时被调用以绑定设备输入功能
  20. void AAvatar::SetupPlayerInputComponent(class UInputComponent* InputComponent)
  21. {
  22. check(InputComponent); //检查空指针
  23. InputComponent->BindAxis("Forward", this, &AAvatar::MoveForward);
  24. InputComponent->BindAxis("Back", this, &AAvatar::MoveForward);
  25. InputComponent->BindAxis("Left", this, &AAvatar::MoveRight);
  26. InputComponent->BindAxis("Right", this, &AAvatar::MoveRight);
  27. InputComponent->BindAxis("Yaw", this, &AAvatar::Yaw);
  28. InputComponent->BindAxis("Pitch", this, &AAvatar::Pitch);
  29. }
  30. void AAvatar::MoveForward(float amount)
  31. {
  32. // Controller控制器当前拥有该actor。例如如果当前角色死了,actor不存在了,此时Controller控制器没有拥有任何一个actor,那么如果我们还想去控制它,就会出错。
  33. // 如果控制器没有拥有actor或者移动量是0,不能进入该函数。
  34. if (Controller && amount)
  35. {
  36. // GetActorForwardVector()取得角色向前的向量
  37. FVector fwd = GetActorForwardVector();
  38. // 我们调用AddMovementInput来在‘fwd’向量的方向上移动角色‘amount’个单位
  39. AddMovementInput(fwd, amount);
  40. }
  41. }
  42. void AAvatar::MoveBack(float amount)
  43. {
  44. if (Controller && amount)
  45. {
  46. // GetActorForwardVector()取得角色向

转自: http://www.52vr.com/article-562-1.html

[unreal4入门系列之十一] 在UE4中编写C++代码控制角色相关推荐

  1. c语言游戏人物控制,在UE4中编写C++代码控制角色

    当你运行我们上次做完的项目,你可能会意识到我们移动的摄像机还是默认的那个摄像机,这个默认的摄像机可以自由飞翔.这一节,我们要使得开始的角色是我们的一个Avatar类的实例对象,并且使用键盘控制我们的角 ...

  2. [unreal4入门系列之十六] UE4中的集合:TSet容器

    一.TSet<T>是什么 UE4中,除了TArray动态数组外,还提供了各种各样的模板容器.这一节,我们就介绍集合容器--TSet<T>.类似于TArray<T>, ...

  3. [unreal4入门系列之十五] UE4中的动态数组:TArray容器

    为什么使用UE4提供的容器类? 如果你用过C++的STL库,你就知道STL提供了各种各样的容器/数据结构,使得你对处理很多数据的时候非常快捷高效.UE4同样也提供了类似的库,库里面的类型是以T开头的, ...

  4. 【深度学习之美】局部连接来减参,权值共享肩并肩(入门系列之十一)

    系列文章: 一入侯门"深"似海,深度学习深几许(深度学习入门系列之一) 人工"碳"索意犹尽,智能"硅"来未可知(深度学习入门系列之二) 神经 ...

  5. 如何在Go中编写防弹代码:不会失败的服务器工作流程

    by Tal Kol 通过塔尔科尔 如何在Go中编写防弹代码:不会失败的服务器工作流程 (How to write bulletproof code in Go: a workflow for ser ...

  6. java代码如何与界面联系在一起_如何在Visual Studio Code 中编写Java代码

    本文将展示如何在Visual Studio Code中用Java编写和运行一个简单的Hello World程序. 首先您必须在本地开发环境中安装Java SE开发工具包(JDK) Visual Stu ...

  7. java代码中添加事务_C#和JAVA中编写事务代码

    C#  DAL层代码,执行多条增删改,使用事务操作: /// /// 执行 多条增删改 (非查询语句) /// /// /// /// public static int ExcuteNonQuery ...

  8. twig php代碼,有没有办法在wordpress的.twig文件中编写php代码?我试图使用.twig模板文件中的表单值发送邮件...

    有没有办法在wordpress的.twig文件中编写php代码?我正在尝试使用.twig模板文件中的表单值发送邮件. 第PAGE-SHORTEFORM.TWIG页 {% extends "b ...

  9. Visual Studio 2010 中编写C代码的一些常见问题

    VS2010中编写C代码时常见的问题及相关解决办法 1.碰到VS2010调试的时候命令符窗口一闪而过,看不到自己的调试结果. 通过查找问题的解决方法并对方法进行了检验,得到以下几种解决方案 解决方案 ...

最新文章

  1. 面试官:你能说说事务的几个特性是啥?有哪几种隔离级别?
  2. R包corrplot绘图相关系数矩阵
  3. 计算机研究生自我介绍,计算机专业研究生英文的自我介绍
  4. vuex - 基础篇
  5. Bzoj 3343: 教主的魔法(分块+二分答案)
  6. 开关电源之防浪涌、防雷电路
  7. c#.net中创建带图标的ListBox
  8. 并查集——营救(洛谷 P1396)
  9. Picasso(毕加索)加载圆形图片、圆角图片
  10. 惠普打印机墨盒更换教程_惠普打印机安装步骤 打印机墨盒加墨方法
  11. 服务器:CPU虚拟化_服务器虚拟化技术
  12. 为什么从此电脑访问不了ftp_ftp无法访问此文件夹怎么解决_ftp文件夹错误无法访问此文件夹如何处理-win7之家...
  13. 【RTT】SPI Flash 与文件系统(3):DFS 和 EasyFlash
  14. 【改进和增强Microsoft Office应用程序】ExtendOffice软件产品介绍
  15. springboot整合Jasypt对数据库密码进行加密
  16. 从“青铜”到“王者”,企业数字化上分三大秘诀收好了
  17. python编程语言创始人-人工智能“网红”编程语言Python进入山东小学课本
  18. 仓库管理的几个常见难题,以及WMS仓储管理系统解决方案
  19. 一定能解决“糟糕无法安装SQLServer(setup.exe)”问题
  20. 98 分形之城(找规律,递归-分治)

热门文章

  1. 解决Canvas.toDataURL 图片跨域问题
  2. 如何在自定义指令中获取评估属性
  3. 通过HTTPS使用HttpClient信任所有证书
  4. 将字符串转换为DateTime
  5. 检查列表中是否存在值的最快方法
  6. 推荐一个当前互联网很火的技术
  7. java注解,通过反射解析注解,模仿hibernate,获取sql语句。
  8. 解决struts.xml文件提示问题
  9. 【每日一记3.21】initrd
  10. AnyProxy代理