UnrealEngine4入门(二) 实现一个可用按键控制的球体
源码摘自官网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入门(二) 实现一个可用按键控制的球体的更多相关文章
- OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型
OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型 目录 背景介绍 请参考前文OpenGL ES 2.0 Shader 调试新思路(一): 改变提问方式 优化 ledCha ...
- 微信硬件H5面板开发(二) ---- 实现一个灯的控制
在第一节中讲解了openApi的调用,这一篇讲一下如何实现一个灯的控制.就用微信提供的lamp例子来做,将代码扒下来(实在是没办法,没有示例),整合到自己的项目中.lamp源码:http://file ...
- UnrealEngine4入门(一) 新建一个c++项目
epic games宣布ue4免费使用(游戏发布之后,每个季度大于3000美元则收取收益的5%)之后,吸引了大批看好VR和AR前景的游戏开发者.不过国内(中文)ue4教程和资料太少,而且一大部分资料都 ...
- Asp.Net MVC4.0 官方教程 入门指南之二--添加一个控制器
Asp.Net MVC4.0 官方教程 入门指南之二--添加一个控制器 MVC概念 MVC的含义是 “模型-视图-控制器”.MVC是一个架构良好并且易于测试和易于维护的开发模式.基于MVC模式的应用程 ...
- Netty入门二:开发第一个Netty应用程序
Netty入门二:开发第一个Netty应用程序 时间 2014-05-07 18:25:43 CSDN博客 原文 http://blog.csdn.net/suifeng3051/article/ ...
- redis入门(二)
目录 redis入门(二) 前言 持久化 RDB AOF 持久化文件加载 高可用 哨兵 流程 安装部署 配置技巧 集群 原理 集群搭建 参考文档 redis入门(二) 前言 在redis入门(一)简单 ...
- 【原创】NIO框架入门(二):服务端基于MINA2的UDP双向通信Demo演示
前言 NIO框架的流行,使得开发大并发.高性能的互联网服务端成为可能.这其中最流行的无非就是MINA和Netty了,MINA目前的主要版本是MINA2.而Netty的主要版本是Netty3和Netty ...
- 电赛菜鸟营培训(二)——STM32F103CB之中断控制
一.中断的概念 中断可以理解为一个有激励给它就会立马给你响应的一个东东.就是说在你执行main函数的内容时,当有这个触发时便会跳转到这个中断内存,执行这段代码. Attention: 1.中断的用法, ...
- DevExpress XtraReports 入门二 创建 data-aware(数据感知) 报表
原文:DevExpress XtraReports 入门二 创建 data-aware(数据感知) 报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的, ...
随机推荐
- 如何用Redlock实现分布式锁
转载请标明出处: http://blog.csdn.net/forezp/article/details/70305336 本文出自方志朋的博客 之前写过一篇文章<如何在springcloud分 ...
- MySQL表结构(含数据类型、字段备注注释)导出成Excel
方法一: 1.用的是Navicat Premium,可以换成任意图形化客户端 SELECT COLUMN_NAME 列名, COLUMN_TYPE 数据类型, DATA_TYPE 字段类型, CHAR ...
- Webpack4 学习笔记八 开发环境和生产环境配置
webpack resolve属性 webpack 区分开发环境和生产环境 webpack resolve属性 该选项的作用是设置模块如何被解析. resolve.alias: 设置别名, 在vue中 ...
- vue、html与iframe html事件相互调用
一.html文件中引入的iframe标签 1.在父html中调用子iframe html 中的事件 通过contentwindow属性 document.getElementById("my ...
- jquery图片滚动demo.css
body, html { font-size: 100%; padding: 0; margin: 0;} /* Reset */*,*:after,*:before { -webkit-box-si ...
- 21.1 XMLHttpRequest 对象【JavaScript高级程序设计第三版】
IE5 是第一款引入XHR 对象的浏览器.在IE5 中,XHR 对象是通过MSXML 库中的一个ActiveX对象实现的.因此,在IE 中可能会遇到三种不同版本的XHR 对象,即MSXML2.XMLH ...
- 20.2 解析与序列化【JavaScript高级程序设计第三版】
JSON 之所以流行,拥有与JavaScript 类似的语法并不是全部原因.更重要的一个原因是,可以把JSON 数据结构解析为有用的JavaScript 对象.与XML 数据结构要解析成DOM 文档而 ...
- tomcat+nginx+keepalived的配置
tomcat+nginx+keepalived的配置 1.在官网上下载Tomcat 2.将压缩包解压,并且移动到/opt/data/的目录下. .tar.gz /opt/data/ 3.进入到Tomc ...
- poj3308 Paratroopers
Description It is year 2500 A.D. and there is a terrible war between the forces of the Earth and the ...
- python基础之反射、面向对象进阶
isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象,如果是返回True 1 class F ...