Unreal Engine 4 道具捡拾教程 C++ 实现

Unreal Engine 4  道具捡拾教程 C++ 实现

 

  物品捡拾是游戏比较常用的功能,这个教程讲解实现简单的物品捡拾的过程。

 

1、  首先新建C++工程,输入好工程名称,注意选择C++页签

 Unreal Engine 4 道具捡拾教程 C++ 实现_第1张图片

 

2. 先配置一下输入控制。选择Edit->ProjectSettings…

 Unreal Engine 4 道具捡拾教程 C++ 实现_第2张图片

选择左侧Engine下的Input 配置键盘鼠标操作键

Unreal Engine 4 道具捡拾教程 C++ 实现_第3张图片

右侧显示Engine-Input, 点选Action Mappings 旁边的+号。

Unreal Engine 4 道具捡拾教程 C++ 实现_第4张图片

将NewActionMaping_0改名为Pickup,点选下面的输入设备选择鼠标右键Right Mouse Button

 Unreal Engine 4 道具捡拾教程 C++ 实现_第5张图片

 Unreal Engine 4 道具捡拾教程 C++ 实现_第6张图片


Unreal Engine 4 道具捡拾教程 C++ 实现_第7张图片

再增加一个Action Mapping,命名为Inventory, 输入方式设置为键盘I键

 Unreal Engine 4 道具捡拾教程 C++ 实现_第8张图片

 Unreal Engine 4 道具捡拾教程 C++ 实现_第9张图片

Unreal Engine 4 道具捡拾教程 C++ 实现_第10张图片


到这里输入方法设置完成,用鼠标右键拾取,用I键显示背包内容。

 

2、  现在开始编码。首先创建父类为Actor的C++类Item。


 Unreal Engine 4 道具捡拾教程 C++ 实现_第11张图片

 Unreal Engine 4 道具捡拾教程 C++ 实现_第12张图片

 Unreal Engine自动创建好了Item C++类

Unreal Engine 4 道具捡拾教程 C++ 实现_第13张图片


 Unreal Engine 4 道具捡拾教程 C++ 实现_第14张图片

先编辑一下ItemPickup.Build.cs的内容,避免后面编译错误


 

public classItemPickup : ModuleRules
{
    public ItemPickup(TargetInfo Target)
    {
        PublicDependencyModuleNames.AddRange(newstring[] { "Core","CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "GameplayTasks"});
    }
}

 

主要代码在Item及ItemPickupPlayherController里,下面列出代码内容


 

Item.h
 
#include "GameFramework/Actor.h"
#include "Item.generated.h"
 
 
class AItemPickupCharacter;
class AItemPickupPlayerController;
 
UCLASS()
class ITEMPICKUP_API AItem : public AActor
{
    GENERATED_BODY()
   
public:
    // Sets default values for this actor's properties
    AItem();
 
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;
   
    // Called every frame
    virtual void Tick( float DeltaSeconds ) override;
 
    UShapeComponent* TBox;
   
    UPROPERTY(EditAnyWhere)
        UStaticMeshComponent* SM_TBox;
 
    AItemPickupCharacter* MyPlayerController;
 
    AItemPickupPlayerController* PlCtl;
 
    UPROPERTY(EditAnyWhere)
        FString ItemName =FString(TEXT(""));
 
    void Pickup();
 
    void GetPlayer(AActor*Player);
 
    bool bItemIsWithinRange;
 
    UFUNCTION()
        void TriggerEnter(class UPrimitiveComponent*MyComp,class AActor * OtherActor,class UPrimitiveComponent*OtherComp,int32 OtherBodyIndex, bool bFromSweep,  const FHitResult & SweepResult);
 
    UFUNCTION()
        void TriggerExit(class UPrimitiveComponent*MyComp,class AActor * OtherActor,class UPrimitiveComponent* OtherComp,int32OtherBodyIndex);
 
};
 
Item.cpp
 
// Fill out your copyright notice in theDescription page of Project Settings.
 
#include "ItemPickup.h"
#include "Item.h"
#include "Engine.h"
 
#include "ItemPickupCharacter.h"
#include "ItemPickupPlayerController.h"
 
// Sets default values
AItem::AItem()
{
    // Set this actor tocall Tick() every frame.  You can turnthis off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick= true;
 
    TBox=  CreateDefaultSubobject(TEXT("Box"));
    TBox->bGenerateOverlapEvents= true;
    TBox->OnComponentBeginOverlap.AddDynamic(this, &AItem::TriggerEnter);
    TBox->OnComponentEndOverlap.AddDynamic(this, &AItem::TriggerExit);
   
    RootComponent= TBox;
 
    SM_TBox =CreateDefaultSubobject(TEXT("BoxMesh"));
 
    SM_TBox->SetupAttachment(RootComponent);
}
 
// Called when the game starts or when spawned
void AItem::BeginPlay()
{
    Super::BeginPlay();
   
}
 
// Called every frame
void AItem::Tick( float DeltaTime )
{
    Super::Tick( DeltaTime );
    if (MyPlayerController != NULL)
    {
        PlCtl= Cast(MyPlayerController->GetController());
        if (PlCtl->bIsPickingUP && bItemIsWithinRange)
        {
            Pickup();
        }
    }
}
 
void AItem::Pickup()
{
    PlCtl =Cast(MyPlayerController->GetController());
    PlCtl->Inventory.Add(*ItemName);
    GEngine->AddOnScreenDebugMessage(1,5.f, FColor::Green,TEXT("Pick Up the Item"));
    Destroy();
}
 
void AItem::GetPlayer(AActor * Player)
{
    MyPlayerController= Cast(Player);
}
 
void AItem::TriggerEnter(class UPrimitiveComponent*MyComp, class AActor * OtherActor, class  UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
{
    bItemIsWithinRange= true;
 
    GEngine->AddOnScreenDebugMessage(1,5.f,FColor::Green,FString::Printf(TEXT("Press Mouse Right ButtonTo Pickup %s"),*ItemName));
 
    GetPlayer(OtherActor);
}
 
void AItem::TriggerExit(class UPrimitiveComponent*MyComp, class AActor * OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
    bItemIsWithinRange= false;
}
 
ItemPickupPlayerController.h
 
// Copyright 1998-2016 Epic Games, Inc. All RightsReserved.
#pragma once
#include "GameFramework/PlayerController.h"
#include "ItemPickupPlayerController.generated.h"
 
UCLASS()
class AItemPickupPlayerController : public APlayerController
{
    GENERATED_BODY()
 
public:
    AItemPickupPlayerController();
 
protected:
    /** True if the controlled character should navigate to the mouse cursor.*/
    uint32 bMoveToMouseCursor : 1;
 
    // Begin PlayerController interface
    virtual void PlayerTick(float DeltaTime) override;
    virtual void SetupInputComponent() override;
    // End PlayerController interface
 
    /** Resets HMD orientation in VR. */
    void OnResetVR();
 
    /** Navigate player to the current mouse cursor location. */
    void MoveToMouseCursor();
 
    /** Navigate player to the current touch location. */
    void MoveToTouchLocation(constETouchIndex::Type FingerIndex,const FVector Location);
   
    /** Navigate player to the given world location. */
    void SetNewMoveDestination(constFVector DestLocation);
 
    /** Input handlers for SetDestination action. */
    void OnSetDestinationPressed();
    void OnSetDestinationReleased();
 
    void BeginPickup();
   
    void EndPickup();
 
    void ShowInventory();
 
public:
    bool bIsPickingUP = false;
 
    TArrayInventory;
 
};
 
 
 
 
ItemPickupPlayerController.cpp
 
// Copyright 1998-2016 Epic Games, Inc. All RightsReserved.
 
#include "ItemPickup.h"
#include "ItemPickupPlayerController.h"
#include "AI/Navigation/NavigationSystem.h"
#include "Runtime/Engine/Classes/Components/DecalComponent.h"
#include "Kismet/HeadMountedDisplayFunctionLibrary.h"
#include "ItemPickupCharacter.h"
#include "Engine.h"
 
AItemPickupPlayerController::AItemPickupPlayerController()
{
    bShowMouseCursor= true;
    DefaultMouseCursor= EMouseCursor::Crosshairs;
}
 
void AItemPickupPlayerController::PlayerTick(floatDeltaTime)
{
    Super::PlayerTick(DeltaTime);
 
    // keep updating the destination every tick while desired
    if (bMoveToMouseCursor)
    {
        MoveToMouseCursor();
    }
}
 
void AItemPickupPlayerController::SetupInputComponent()
{
    // set up gameplay key bindings
    Super::SetupInputComponent();
 
    InputComponent->BindAction("SetDestination",IE_Pressed, this, &AItemPickupPlayerController::OnSetDestinationPressed);
    InputComponent->BindAction("SetDestination",IE_Released, this, &AItemPickupPlayerController::OnSetDestinationReleased);
 
    // support touch devices
    InputComponent->BindTouch(EInputEvent::IE_Pressed,this, &AItemPickupPlayerController::MoveToTouchLocation);
    InputComponent->BindTouch(EInputEvent::IE_Repeat,this, &AItemPickupPlayerController::MoveToTouchLocation);
 
    InputComponent->BindAction("ResetVR",IE_Pressed, this, &AItemPickupPlayerController::OnResetVR);
 
    //Set Pickup Callback
    InputComponent->BindAction("Pickup",IE_Pressed, this, &AItemPickupPlayerController::BeginPickup);
    InputComponent->BindAction("Pickup",IE_Released, this, &AItemPickupPlayerController::EndPickup);
 
    InputComponent->BindAction("Inventory",IE_Pressed, this, &AItemPickupPlayerController::ShowInventory);
}
 
void AItemPickupPlayerController::OnResetVR()
{
    UHeadMountedDisplayFunctionLibrary::ResetOrientationAndPosition();
}
 
void AItemPickupPlayerController::MoveToMouseCursor()
{
    if (UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayEnabled())
    {
        if (AItemPickupCharacter* MyPawn= Cast(GetPawn()))
        {
            if (MyPawn->GetCursorToWorld())
            {
                UNavigationSystem::SimpleMoveToLocation(this, MyPawn->GetCursorToWorld()->GetComponentLocation());
            }
        }
    }
    else
    {
        // Trace to see what is under the mouse cursor
        FHitResult Hit;
        GetHitResultUnderCursor(ECC_Visibility,false, Hit);
 
        if (Hit.bBlockingHit)
        {
            // We hit something, move there
            SetNewMoveDestination(Hit.ImpactPoint);
        }
    }
}
 
void AItemPickupPlayerController::MoveToTouchLocation(constETouchIndex::TypeFingerIndex, constFVector Location)
{
    FVector2D ScreenSpaceLocation(Location);
 
    // Trace to see what is under the touch location
    FHitResult HitResult;
    GetHitResultAtScreenPosition(ScreenSpaceLocation,CurrentClickTraceChannel,true,HitResult);
    if (HitResult.bBlockingHit)
    {
        // We hit something, move there
        SetNewMoveDestination(HitResult.ImpactPoint);
    }
}
 
void AItemPickupPlayerController::SetNewMoveDestination(constFVector DestLocation)
{
    APawn* const MyPawn= GetPawn();
    if (MyPawn)
    {
        UNavigationSystem*const NavSys = GetWorld()->GetNavigationSystem();
        float const Distance = FVector::Dist(DestLocation,MyPawn->GetActorLocation());
 
        // We need to issue move command only if far enough in order for walkanimation to play correctly
        if (NavSys && (Distance > 120.0f))
        {
            NavSys->SimpleMoveToLocation(this,DestLocation);
        }
    }
}
 
void AItemPickupPlayerController::OnSetDestinationPressed()
{
    // set flag to keep updating destination until released
    bMoveToMouseCursor= true;
}
 
void AItemPickupPlayerController::OnSetDestinationReleased()
{
    // clear flag to indicate we should stop updating the destination
    bMoveToMouseCursor= false;
}
 
void AItemPickupPlayerController::BeginPickup()
{
    GEngine->AddOnScreenDebugMessage(-1,5.f,FColor::Blue,TEXT("Begin Pickup"));
    bIsPickingUP= true;
}
 
void AItemPickupPlayerController::EndPickup()
{
    GEngine->AddOnScreenDebugMessage(-1,5.f, FColor::Blue, TEXT("End Pickup"));
    bIsPickingUP= false;
}
 
void AItemPickupPlayerController::ShowInventory()
{
    GEngine->AddOnScreenDebugMessage(-1,5.f, FColor::Blue, TEXT("Show Inventory"));
    for (auto& Item : Inventory)
    {
        GEngine->AddOnScreenDebugMessage(-1,5.f, FColor::Blue, FString::Printf(TEXT("Item: %s"),*Item));
    }
}

3、  基于Item创建Blueprint 对象,先在Content主目录下创建一个Pickup子目录

 Unreal Engine 4 道具捡拾教程 C++ 实现_第15张图片


建立New Folder, 命名为Pickup


Unreal Engine 4 道具捡拾教程 C++ 实现_第16张图片

在C++ Classes 下的ItemPickup找到Item对象,点鼠标右键选择Create Blueprint class based on Item.

Unreal Engine 4 道具捡拾教程 C++ 实现_第17张图片

命名为BP_PickItem,选择存放在Pickup下。

Unreal Engine 4 道具捡拾教程 C++ 实现_第18张图片

4、编辑BP_PickItem,首先要为BP_PickItem创建一个Mesh,先选中RootComponent,然后点击Add Component

 Unreal Engine 4 道具捡拾教程 C++ 实现_第19张图片


Unreal Engine 4 道具捡拾教程 C++ 实现_第20张图片

出现下拉列表后选择Static Mesh

Unreal Engine 4 道具捡拾教程 C++ 实现_第21张图片


命名为PickBox


Unreal Engine 4 道具捡拾教程 C++ 实现_第22张图片

选中PickBox,在右侧Static Mesh选中SM_Rock模型


Unreal Engine 4 道具捡拾教程 C++ 实现_第23张图片

缩小一下这个模型

Unreal Engine 4 道具捡拾教程 C++ 实现_第24张图片

选择编译Compile并存储一下,完成后关闭这个窗口。

 Unreal Engine 4 道具捡拾教程 C++ 实现_第25张图片

6、将这个BP_PickItem拖拽到场景中。


Unreal Engine 4 道具捡拾教程 C++ 实现_第26张图片

将ItemPickup及ItemPickup1分别命名为Box1和Box2

 Unreal Engine 4 道具捡拾教程 C++ 实现_第27张图片


Unreal Engine 4 道具捡拾教程 C++ 实现_第28张图片

 

7、编译一下游戏,选择运行游戏,移动到拾取物体上,按鼠标右键。

 Unreal Engine 4 道具捡拾教程 C++ 实现_第29张图片

 

物品消失,被我们拾取到了。

Unreal Engine 4 道具捡拾教程 C++ 实现_第30张图片


按I键,显示背包内容。

 Unreal Engine 4 道具捡拾教程 C++ 实现_第31张图片

8、这个教程比较相对比较简单,主要目的是理解如果用C++实现游戏的简单交互。

 

你可能感兴趣的:(unreal,engine,4,游戏玩法系统开发,c++,网络游戏开发)