源码摘自官网guide,加上部分自己的理解和注释

接上篇博客 本文实现一个可用WASD控制滚动的球体

先创建一个可见的球体:

在CollidingPawn.cpp的构造函数ACollidingPawn::ACollidingPawn()中添加一个球体,一个网格组件(mesh),一个弹簧臂和相机,代码如下:

    //创建一个球体
USphereComponent* SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
//设置为根组件
RootComponent = SphereComponent;
//设置半径
SphereComponent->InitSphereRadius(40.0f);
SphereComponent->SetCollisionProfileName(TEXT("Pawn")); // 创建并放置网格物体组件,这样我们能看到球体的位置
UStaticMeshComponent* SphereVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
//如果不把网格附加到SphereComponent 就看不到球体
SphereVisual->AttachTo(RootComponent);
static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));
if (SphereVisualAsset.Succeeded()){
SphereVisual->SetStaticMesh(SphereVisualAsset.Object);
SphereVisual->SetRelativeLocation(FVector(0.0f, 0.0f, -40.0f));
SphereVisual->SetWorldScale3D(FVector(0.8f));
} // 使用弹簧臂来让相机获得一种平滑、自然的运动。
// 弹簧臂的目的是让视角跟SphereComponent保持一定距离,如果不加,效果像fps游戏的第一视角一样
USpringArmComponent* SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraAttachmentArm"));
SpringArm->AttachTo(RootComponent);
SpringArm->RelativeRotation = FRotator(-.f, .f, .f); //45度角
SpringArm->TargetArmLength = 400.0f; //弹簧臂长度
SpringArm->bEnableCameraLag = true;
SpringArm->CameraLagSpeed = .f; // 创建相机并附加到弹簧臂
// 如果没有相机 什么都看不到
UCameraComponent* Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("ActualCamera"));
Camera->AttachTo(SpringArm, USpringArmComponent::SocketName);

然后配置按键: 打开ue编辑器, 选择编辑->项目设置-> 输入, 然后在右边的axis mappings加入如下设置:

MoveForWard,MoveRight,Turn,Turn_Y 可自定义,表示跟各个按键的绑定关系。

然后创建一个类CollidingPawnMovementComponent继承自PawnMovementComponent(控制pawn移动的组件),我们可以把WASD绑定的行为绑定到这个component上,然后把该component绑定到我们刚才创建的球体上:

CollidingPawnMovementComponent.cpp

#include "Demo.h"
#include "CollidingPawnMovementComponent.h" void UCollidingPawnMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction); // Make sure that everything is still valid, and that we are allowed to move.
if (!PawnOwner || !UpdatedComponent || ShouldSkipUpdate(DeltaTime))
{
return;
} // Get (and then clear) the movement vector that we set in ACollidingPawn::Tick
FVector DesiredMovementThisFrame = ConsumeInputVector().GetClampedToMaxSize(1.0f) * DeltaTime * 150.0f;
if (!DesiredMovementThisFrame.IsNearlyZero())
{
FHitResult Hit;
SafeMoveUpdatedComponent(DesiredMovementThisFrame, UpdatedComponent->GetComponentRotation(), true, Hit); // If we bumped into something, try to slide along it
if (Hit.IsValidBlockingHit())
{
SlideAlongSurface(DesiredMovementThisFrame, .f - Hit.Time, Hit.Normal, Hit);
}
}
};

然后在CollidingPawn.h中加入如下代码:

class UCollidingPawnMovementComponent* OurMovementComponent;

先将movementComponent绑定到刚才加的球体上,在CollidingPawn构造函数底部加入如下代码:

    // Create an instance of our movement component, and tell it to update the root.
OurMovementComponent = CreateDefaultSubobject<UCollidingPawnMovementComponent>(TEXT("CustomMovementComponent"));
OurMovementComponent->UpdatedComponent = RootComponent;

为了让游戏中的其他类知道CollidingPawn目前正在使用CollidingPawnMovementComponent作为移动控制组件,需要在CollidingPawn.h中加入以下代码:

virtual UPawnMovementComponent* GetMovementComponent() const override;

然后在CollidingPawn.cpp中加入:

UPawnMovementComponent* ACollidingPawn::GetMovementComponent() const
{
return OurMovementComponent;
}

刚才我们已经将新创建的移动控制组件绑定到了球体上,现在需要把WASD触发的函数绑定到移动组件上,在CollidingPawn中实现往前移动,往左移动,转动视角的三个方法:

// 往前(后)移动
void ACollidingPawn::MoveForward(float AxisValue)
{
if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent))
{
OurMovementComponent->AddInputVector(GetActorForwardVector() * AxisValue);
}
} // 往左(右)移动
void ACollidingPawn::MoveRight(float AxisValue)
{
if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent))
{
OurMovementComponent->AddInputVector(GetActorRightVector() * AxisValue);
}
} // 左右转动视角
void ACollidingPawn::Turn(float AxisValue)
{
FRotator NewRotation = GetActorRotation();
NewRotation.Yaw += AxisValue;
SetActorRotation(NewRotation);
}

然后将这三个方法在ACollidingPawn::SetupPlayerInputComponent中注册:

void ACollidingPawn::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
Super::SetupPlayerInputComponent(InputComponent); InputComponent->BindAxis("MoveForward", this, &ACollidingPawn::MoveForward);
InputComponent->BindAxis("MoveRight", this, &ACollidingPawn::MoveRight);
InputComponent->BindAxis("Turn", this, &ACollidingPawn::Turn);
}

以上就完成了一个可用WASD移动和鼠标控制左右视角的球体

如果上下移动视角,可仿照以上的ACollidingPawn::Turn方法,将NewRotation.Yaw += AxisValue; 改为NewRotation.Pitch += AxisValue;即可

UnrealEngine4入门(二) 实现一个可用按键控制的球体的更多相关文章

  1. OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型

    OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型 目录 背景介绍 请参考前文OpenGL ES 2.0 Shader 调试新思路(一): 改变提问方式 优化 ledCha ...

  2. 微信硬件H5面板开发(二) ---- 实现一个灯的控制

    在第一节中讲解了openApi的调用,这一篇讲一下如何实现一个灯的控制.就用微信提供的lamp例子来做,将代码扒下来(实在是没办法,没有示例),整合到自己的项目中.lamp源码:http://file ...

  3. UnrealEngine4入门(一) 新建一个c++项目

    epic games宣布ue4免费使用(游戏发布之后,每个季度大于3000美元则收取收益的5%)之后,吸引了大批看好VR和AR前景的游戏开发者.不过国内(中文)ue4教程和资料太少,而且一大部分资料都 ...

  4. Asp.Net MVC4.0 官方教程 入门指南之二--添加一个控制器

    Asp.Net MVC4.0 官方教程 入门指南之二--添加一个控制器 MVC概念 MVC的含义是 “模型-视图-控制器”.MVC是一个架构良好并且易于测试和易于维护的开发模式.基于MVC模式的应用程 ...

  5. Netty入门二:开发第一个Netty应用程序

    Netty入门二:开发第一个Netty应用程序 时间 2014-05-07 18:25:43  CSDN博客 原文  http://blog.csdn.net/suifeng3051/article/ ...

  6. redis入门(二)

    目录 redis入门(二) 前言 持久化 RDB AOF 持久化文件加载 高可用 哨兵 流程 安装部署 配置技巧 集群 原理 集群搭建 参考文档 redis入门(二) 前言 在redis入门(一)简单 ...

  7. 【原创】NIO框架入门(二):服务端基于MINA2的UDP双向通信Demo演示

    前言 NIO框架的流行,使得开发大并发.高性能的互联网服务端成为可能.这其中最流行的无非就是MINA和Netty了,MINA目前的主要版本是MINA2.而Netty的主要版本是Netty3和Netty ...

  8. 电赛菜鸟营培训(二)——STM32F103CB之中断控制

    一.中断的概念 中断可以理解为一个有激励给它就会立马给你响应的一个东东.就是说在你执行main函数的内容时,当有这个触发时便会跳转到这个中断内存,执行这段代码. Attention: 1.中断的用法, ...

  9. DevExpress XtraReports 入门二 创建 data-aware(数据感知) 报表

    原文:DevExpress XtraReports 入门二 创建 data-aware(数据感知) 报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的, ...

随机推荐

  1. vue进阶语法及生命周期函数

    1.calss和style绑定 操作元素的 class 列表和内联样式style是数据绑定的一个常见需求,它两都是属性,所以可以通过v-bind来绑定 1.1绑定HTML class 可以给v-bin ...

  2. 简析--Java中常见的一些关键字的解析

    在Java开发中我们经常会用到一些关键字,关键字的定义很有意思"Java事先定义好的,具有特殊含义的单词",那么我们怎么来用好关键字呢?下面我们对一些常见的关键字进行分析和比较; ...

  3. PL/SQL 条件控制语句

    1.if-then 语句 语法: IF 条件 THEN 语句序列; END IF; 实例: DECLARE i ) :; BEGIN THEN dbms_output.put_line('True') ...

  4. 一个logstash引发的连环案,关于logstash提示:Reached open files limit: 4095, set by the 'max_open_files' option or default, files yet to open: 375248

    不多说,直接上问题.版本logstash-2.4.0,启动后提示错误: !!! Please upgrade your java version, the current version '1.7.0 ...

  5. luogu p2615神奇的幻方题解

    目录 题目部分 讲解部分 代码实现 题目部分 题目来源:洛谷p2615 题目描述 幻方是一种很神奇的 N*N矩阵:它由数字 1,2,3,⋯⋯,N×N 构成,且每行.每列及两条对角线上的数字之和都相同. ...

  6. (转)Dubbo 简单Dome搭建

    (转)原地址https://blog.csdn.net/noaman_wgs/article/details/70214612/ Dubbo背景和简介 Dubbo开始于电商系统,因此在这里先从电商系统 ...

  7. 关于SSM项目注解事务不回滚的问题

    <!--扫描service包(包含子包)下所有使用注解的类型--> <context:component-scan base-package="com.song.ssm.s ...

  8. PyCharm+QT Designer整合

    CMD下使用pip安装PyQt4或者PYQT5 这里要注意,你下载的PYQT5不包含QT designer 还要:pip3 install PyQt5-tools,好像Pyqt5中将designer分 ...

  9. 【转载】vue.js实现格式化时间并每秒更新显示功能示例

    引用:https://www.jb51.net/article/143351.htm 这篇文章主要介绍了vue.js实现格式化时间并每秒更新显示功能,结合实例形式分析了vue.js时间格式化显示与基于 ...

  10. Linux Shell常用命令(长期更新)

    #判断某个字段是否匹配指定值 awk -F"," '{if($4=="value"){print $1} else {print $0}}' file.txt ...