查看: 465|回复: 11

[编程指南] 【4. Using our Pawn and Components together | Unreal Engine】

[复制链接]

1

主题

273

帖子

7万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
73038
发表于 2016-6-27 00:54:12 | 显示全部楼层 |阅读模式



Previous Step
Next Step



   
Programming Tutorials Home


In order to use our custom Pawn Movement Component, we will first need to add a variable to our Pawn class to keep track of it. At the bottom of our class definition in CollidingPawn.h, near where we added the "OurParticleSystem" variable, we should add:

class UCollidingPawnMovementComponent* OurMovementComponent;
Once we have a place to keep track of it, we will need to create a Colliding Pawn Movement Component to store in our new variable, so let's open CollidingPawn.cpp and add the following to the top of the file, underneath the "#include" lines, so that our code will be able to reference our new class:

#include "CollidingPawnMovementComponent.h"
Creating a Pawn Movement Component and associating it with our Pawn is simple. At the bottom of ACollidingPawn::ACollidingPawn, we can add this code:

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

Unlike the other Components we've seen so far, we don't need to attach this Component to our own Component hierarchy. This is because our other Components are all types of Scene Components, which inherently require physical locations. Movement Controllers, however, are not Scene Components and do not represent physical objects, so the concept of existing at a physical location or being physically attached to another Component does not apply to them.


Pawns have a function called "GetMovementComponent" that is used to enable other classes in the engine to access the Pawn Movement Component that the Pawn is currently using. We will need to override that function so that it returns our custom Pawn Movement Component. In the class definition in CollidingPawn.h, we need to add:

virtual UPawnMovementComponent* GetMovementComponent() const override;
And in CollidingPawn.cpp, we need to add the definition of our overridden function, as follows:

UPawnMovementComponent* ACollidingPawn::GetMovementComponent() const{    return OurMovementComponent;}
With our new Pawn Movement Component set up, we can create code to handle the input that our Pawn will receive. We will start by declaring a few functions in our class definition in CollidingPawn.h:

void MoveForward(float AxisValue);void MoveRight(float AxisValue);void Turn(float AxisValue);void ParticleToggle();
In CollidingPawn.cpp, we will add the definitions of those functions as follows:

    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);    }    void ACollidingPawn::ParticleToggle()    {
if (OurParticleSystem  OurParticleSystem-Template)
{
     OurParticleSystem-ToggleActive();
}    }
All that remains is to bind our functions to our input events. Let's add the following code to ACollidingPawn::SetupPlayerInputComponent:

InputComponent-BindAction("ParticleToggle", IE_Pressed, this, ACollidingPawn::ParticleToggle);InputComponent-BindAxis("MoveForward", this, ACollidingPawn::MoveForward);InputComponent-BindAxis("MoveRight", this, ACollidingPawn::MoveRight);InputComponent-BindAxis("Turn", this, ACollidingPawn::Turn);
We are done programming and can now return to the Unreal Editor and press the Compile button to load our changes.


Our programming work is done, and we can now place our custom Pawn in the world and move it around.


Finished Code


CollidingPawn.h

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.#pragma once#include "GameFramework/Pawn.h"#include "CollidingPawn.generated.h"UCLASS()class HOWTO_COMPONENTS_API ACollidingPawn : public APawn{    GENERATED_BODY()public:    // Sets default values for this pawn's properties    ACollidingPawn();    // Called when the game starts or when spawned    virtual void BeginPlay() override;    // Called every frame    virtual void Tick( float DeltaSeconds ) override;    // Called to bind functionality to input    virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;    UParticleSystemComponent* OurParticleSystem;    class UCollidingPawnMovementComponent* OurMovementComponent;    virtual UPawnMovementComponent* GetMovementComponent() const override;    void MoveForward(float AxisValue);    void MoveRight(float AxisValue);    void Turn(float AxisValue);    void ParticleToggle();};
CollidingPawn.cpp

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.#include "HowTo_Components.h"#include "CollidingPawn.h"#include "CollidingPawnMovementComponent.h"// Sets default valuesACollidingPawn::ACollidingPawn(){    // Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.    PrimaryActorTick.bCanEverTick = true;    // Our root component will be a sphere that reacts to physics    USphereComponent* SphereComponent = CreateDefaultSubobjectUSphereComponent(TEXT("RootComponent"));    RootComponent = SphereComponent;    SphereComponent-InitSphereRadius(40.0f);    SphereComponent-SetCollisionProfileName(TEXT("Pawn"));    // Create and position a mesh component so we can see where our sphere is    UStaticMeshComponent* SphereVisual = CreateDefaultSubobjectUStaticMeshComponent(TEXT("VisualRepresentation"));    SphereVisual-AttachTo(RootComponent);    static ConstructorHelpers::FObjectFinderUStaticMesh 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));    }    // Create a particle system that we can activate or deactivate    OurParticleSystem = CreateDefaultSubobjectUParticleSystemComponent(TEXT("MovementParticles"));    OurParticleSystem-AttachTo(SphereVisual);    OurParticleSystem-bAutoActivate = false;    OurParticleSystem-SetRelativeLocation(FVector(-20.0f, 0.0f, 20.0f));    static ConstructorHelpers::FObjectFinderUParticleSystem ParticleAsset(TEXT("/Game/StarterContent/Particles/P_Fire.P_Fire"));    if (ParticleAsset.Succeeded())    {
OurParticleSystem-SetTemplate(ParticleAsset.Object);    }    // Use a spring arm to give the camera smooth, natural-feeling motion.    USpringArmComponent* SpringArm = CreateDefaultSubobjectUSpringArmComponent(TEXT("CameraAttachmentArm"));    SpringArm-AttachTo(RootComponent);    SpringArm-RelativeRotation = FRotator(-45.f, 0.f, 0.f);    SpringArm-TargetArmLength = 400.0f;    SpringArm-bEnableCameraLag = true;    SpringArm-CameraLagSpeed = 3.0f;    // Create a camera and attach to our spring arm    UCameraComponent* Camera = CreateDefaultSubobjectUCameraComponent(TEXT("ActualCamera"));    Camera-AttachTo(SpringArm, USpringArmComponent::SocketName);    // Take control of the default player    AutoPossessPlayer = EAutoReceiveInput::Player0;    // Create an instance of our movement component, and tell it to update our root component.    OurMovementComponent = CreateDefaultSubobjectUCollidingPawnMovementComponent(TEXT("CustomMovementComponent"));    OurMovementComponent-UpdatedComponent = RootComponent;}// Called when the game starts or when spawnedvoid ACollidingPawn::BeginPlay(){    Super::BeginPlay();}// Called every framevoid ACollidingPawn::Tick( float DeltaTime ){    Super::Tick( DeltaTime );}// Called to bind functionality to inputvoid ACollidingPawn::SetupPlayerInputComponent(class UInputComponent* InputComponent){    Super::SetupPlayerInputComponent(InputComponent);    InputComponent-BindAction("ParticleToggle", IE_Pressed, this, ACollidingPawn::ParticleToggle);    InputComponent-BindAxis("MoveForward", this, ACollidingPawn::MoveForward);    InputComponent-BindAxis("MoveRight", this, ACollidingPawn::MoveRight);    InputComponent-BindAxis("Turn", this, ACollidingPawn::Turn);}UPawnMovementComponent* ACollidingPawn::GetMovementComponent() const{    return OurMovementComponent;}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);}void ACollidingPawn::ParticleToggle(){    if (OurParticleSystem  OurParticleSystem-Template)    {
OurParticleSystem-ToggleActive();    }}
CollidingPawnMovementComponent.h

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.#pragma once#include "GameFramework/PawnMovementComponent.h"#include "CollidingPawnMovementComponent.generated.h"/** *  */UCLASS()class HOWTO_COMPONENTS_API UCollidingPawnMovementComponent : public UPawnMovementComponent{    GENERATED_BODY()public:    virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;  };
CollidingPawnMovementComponent.cpp

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.#include "HowTo_Components.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, 1.f - Hit.Time, Hit.Normal, Hit);
}    }};


   
Previous Step
Next Step



   
Programming Tutorials Home
回复

使用道具 举报

0

主题

873

帖子

2914

积分

vip会员

Rank: 1

积分
2914
发表于 2016-7-2 19:35:08 来自手机 | 显示全部楼层
恩,好资源~ 哈哈~
回复 支持 反对

使用道具 举报

0

主题

869

帖子

2874

积分

vip会员

Rank: 1

积分
2874
发表于 2016-7-3 23:52:17 来自手机 | 显示全部楼层
哈哈哈好大呀
回复 支持 反对

使用道具 举报

0

主题

819

帖子

2702

积分

vip会员

Rank: 1

积分
2702
发表于 2016-7-4 11:31:22 来自手机 | 显示全部楼层
快没金币了,看看需要多少?
回复 支持 反对

使用道具 举报

拉倒 该用户已被删除
发表于 2016-7-9 13:32:01 来自手机 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

0

主题

1199

帖子

3858

积分

vip会员

Rank: 1

积分
3858
发表于 2016-7-9 20:57:20 来自手机 | 显示全部楼层
不错的资源啊
回复 支持 反对

使用道具 举报

0

主题

886

帖子

2919

积分

vip会员

Rank: 1

积分
2919
发表于 2016-7-9 23:30:55 来自手机 | 显示全部楼层
好东西 好东西 好东西 好东西
回复 支持 反对

使用道具 举报

0

主题

827

帖子

2744

积分

vip会员

Rank: 1

积分
2744
发表于 2016-7-17 05:38:31 | 显示全部楼层
这就是为什么春哥在天朝这么火的原因啊!
回复 支持 反对

使用道具 举报

0

主题

852

帖子

2808

积分

vip会员

Rank: 1

积分
2808
发表于 2016-7-18 10:57:42 来自手机 | 显示全部楼层
好吗
回复 支持 反对

使用道具 举报

0

主题

878

帖子

2925

积分

vip会员

Rank: 1

积分
2925
发表于 2016-7-20 05:18:06 来自手机 | 显示全部楼层
楼主辛苦
回复 支持 反对

使用道具 举报

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

本版积分规则

 
 



邮件留言:


 
返回顶部