|
Unreal Engine 4 道具捡拾教程 C++ 实现
物品捡拾是游戏比较常用的功能,这个教程讲解实现简单的物品捡拾的过程。
1、 首先新建C++工程,输入好工程名称,注意选择C++页签
2. 先配置一下输入控制。选择Edit->ProjectSettings…
选择左侧Engine下的Input 配置键盘鼠标操作键
右侧显示Engine-Input, 点选Action Mappings 旁边的+号。
将NewActionMaping_0改名为Pickup,点选下面的输入设备选择鼠标右键Right Mouse Button
再增加一个Action Mapping,命名为Inventory, 输入方式设置为键盘I键
到这里输入方法设置完成,用鼠标右键拾取,用I键显示背包内容。
2、 现在开始编码。首先创建父类为Actor的C++类Item。
Unreal Engine自动创建好了Item C++类
先编辑一下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<UBoxComponent>(TEXT("Box"));
- TBox->bGenerateOverlapEvents= true;
- TBox->OnComponentBeginOverlap.AddDynamic(this, &AItem::TriggerEnter);
- TBox->OnComponentEndOverlap.AddDynamic(this, &AItem::TriggerExit);
-
- RootComponent= TBox;
-
- SM_TBox =CreateDefaultSubobject<UStaticMeshComponent>(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<AItemPickupPlayerController>(MyPlayerController->GetController());
- if (PlCtl->bIsPickingUP && bItemIsWithinRange)
- {
- Pickup();
- }
- }
- }
-
- void AItem::Pickup()
- {
- PlCtl =Cast<AItemPickupPlayerController>(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<AItemPickupCharacter>(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;
-
- TArray<FString>Inventory;
-
- };
-
-
-
-
- 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<AItemPickupCharacter>(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子目录
建立New Folder, 命名为Pickup
在C++ Classes 下的ItemPickup找到Item对象,点鼠标右键选择Create Blueprint class based on Item.
命名为BP_PickItem,选择存放在Pickup下。
4、编辑BP_PickItem,首先要为BP_PickItem创建一个Mesh,先选中RootComponent,然后点击Add Component
出现下拉列表后选择Static Mesh
命名为PickBox
选中PickBox,在右侧Static Mesh选中SM_Rock模型
缩小一下这个模型
选择编译Compile并存储一下,完成后关闭这个窗口。
6、将这个BP_PickItem拖拽到场景中。
将ItemPickup及ItemPickup1分别命名为Box1和Box2
7、编译一下游戏,选择运行游戏,移动到拾取物体上,按鼠标右键。
物品消失,被我们拾取到了。
按I键,显示背包内容。
8、这个教程比较相对比较简单,主要目的是理解如果用C++实现游戏的简单交互。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|