找回密码
 立即注册
查看: 306|回复: 0

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

[复制链接]
发表于 2023-4-11 23:10 | 显示全部楼层 |阅读模式
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的内容,避免后面编译错误

  1. public classItemPickup : ModuleRules
  2. {
  3.     public ItemPickup(TargetInfo Target)
  4.     {
  5.         PublicDependencyModuleNames.AddRange(newstring[] { "Core","CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "GameplayTasks"});
  6.     }
  7. }
复制代码
主要代码在Item及ItemPickupPlayherController里,下面列出代码内容
  1. Item.h
  2. #include "GameFramework/Actor.h"
  3. #include "Item.generated.h"
  4. class AItemPickupCharacter;
  5. class AItemPickupPlayerController;
  6. UCLASS()
  7. class ITEMPICKUP_API AItem : public AActor
  8. {
  9.     GENERATED_BODY()
  10.    
  11. public:
  12.     // Sets default values for this actor's properties
  13.     AItem();
  14.     // Called when the game starts or when spawned
  15.     virtual void BeginPlay() override;
  16.    
  17.     // Called every frame
  18.     virtual void Tick( float DeltaSeconds ) override;
  19.     UShapeComponent* TBox;
  20.    
  21.     UPROPERTY(EditAnyWhere)
  22.         UStaticMeshComponent* SM_TBox;
  23.     AItemPickupCharacter* MyPlayerController;
  24.     AItemPickupPlayerController* PlCtl;
  25.     UPROPERTY(EditAnyWhere)
  26.         FString ItemName =FString(TEXT(""));
  27.     void Pickup();
  28.     void GetPlayer(AActor*Player);
  29.     bool bItemIsWithinRange;
  30.     UFUNCTION()
  31.         void TriggerEnter(class UPrimitiveComponent*MyComp,class AActor * OtherActor,class UPrimitiveComponent*OtherComp,int32 OtherBodyIndex, bool bFromSweep,  const FHitResult & SweepResult);
  32.     UFUNCTION()
  33.         void TriggerExit(class UPrimitiveComponent*MyComp,class AActor * OtherActor,class UPrimitiveComponent* OtherComp,int32OtherBodyIndex);
  34. };
  35. Item.cpp
  36. // Fill out your copyright notice in theDescription page of Project Settings.
  37. #include "ItemPickup.h"
  38. #include "Item.h"
  39. #include "Engine.h"
  40. #include "ItemPickupCharacter.h"
  41. #include "ItemPickupPlayerController.h"
  42. // Sets default values
  43. AItem::AItem()
  44. {
  45.     // Set this actor tocall Tick() every frame.  You can turnthis off to improve performance if you don't need it.
  46.     PrimaryActorTick.bCanEverTick= true;
  47.     TBox=  CreateDefaultSubobject<UBoxComponent>(TEXT("Box"));
  48.     TBox->bGenerateOverlapEvents= true;
  49.     TBox->OnComponentBeginOverlap.AddDynamic(this, &AItem::TriggerEnter);
  50.     TBox->OnComponentEndOverlap.AddDynamic(this, &AItem::TriggerExit);
  51.    
  52.     RootComponent= TBox;
  53.     SM_TBox =CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BoxMesh"));
  54.     SM_TBox->SetupAttachment(RootComponent);
  55. }
  56. // Called when the game starts or when spawned
  57. void AItem::BeginPlay()
  58. {
  59.     Super::BeginPlay();
  60.    
  61. }
  62. // Called every frame
  63. void AItem::Tick( float DeltaTime )
  64. {
  65.     Super::Tick( DeltaTime );
  66.     if (MyPlayerController != NULL)
  67.     {
  68.         PlCtl= Cast<AItemPickupPlayerController>(MyPlayerController->GetController());
  69.         if (PlCtl->bIsPickingUP && bItemIsWithinRange)
  70.         {
  71.             Pickup();
  72.         }
  73.     }
  74. }
  75. void AItem::Pickup()
  76. {
  77.     PlCtl =Cast<AItemPickupPlayerController>(MyPlayerController->GetController());
  78.     PlCtl->Inventory.Add(*ItemName);
  79.     GEngine->AddOnScreenDebugMessage(1,5.f, FColor::Green,TEXT("Pick Up the Item"));
  80.     Destroy();
  81. }
  82. void AItem::GetPlayer(AActor * Player)
  83. {
  84.     MyPlayerController= Cast<AItemPickupCharacter>(Player);
  85. }
  86. void AItem::TriggerEnter(class UPrimitiveComponent*MyComp, class AActor * OtherActor, class  UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
  87. {
  88.     bItemIsWithinRange= true;
  89.     GEngine->AddOnScreenDebugMessage(1,5.f,FColor::Green,FString::Printf(TEXT("Press Mouse Right ButtonTo Pickup %s"),*ItemName));
  90.     GetPlayer(OtherActor);
  91. }
  92. void AItem::TriggerExit(class UPrimitiveComponent*MyComp, class AActor * OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
  93. {
  94.     bItemIsWithinRange= false;
  95. }
  96. ItemPickupPlayerController.h
  97. // Copyright 1998-2016 Epic Games, Inc. All RightsReserved.
  98. #pragma once
  99. #include "GameFramework/PlayerController.h"
  100. #include "ItemPickupPlayerController.generated.h"
  101. UCLASS()
  102. class AItemPickupPlayerController : public APlayerController
  103. {
  104.     GENERATED_BODY()
  105. public:
  106.     AItemPickupPlayerController();
  107. protected:
  108.     /** True if the controlled character should navigate to the mouse cursor.*/
  109.     uint32 bMoveToMouseCursor : 1;
  110.     // Begin PlayerController interface
  111.     virtual void PlayerTick(float DeltaTime) override;
  112.     virtual void SetupInputComponent() override;
  113.     // End PlayerController interface
  114.     /** Resets HMD orientation in VR. */
  115.     void OnResetVR();
  116.     /** Navigate player to the current mouse cursor location. */
  117.     void MoveToMouseCursor();
  118.     /** Navigate player to the current touch location. */
  119.     void MoveToTouchLocation(constETouchIndex::Type FingerIndex,const FVector Location);
  120.    
  121.     /** Navigate player to the given world location. */
  122.     void SetNewMoveDestination(constFVector DestLocation);
  123.     /** Input handlers for SetDestination action. */
  124.     void OnSetDestinationPressed();
  125.     void OnSetDestinationReleased();
  126.     void BeginPickup();
  127.    
  128.     void EndPickup();
  129.     void ShowInventory();
  130. public:
  131.     bool bIsPickingUP = false;
  132.     TArray<FString>Inventory;
  133. };
  134. ItemPickupPlayerController.cpp
  135. // Copyright 1998-2016 Epic Games, Inc. All RightsReserved.
  136. #include "ItemPickup.h"
  137. #include "ItemPickupPlayerController.h"
  138. #include "AI/Navigation/NavigationSystem.h"
  139. #include "Runtime/Engine/Classes/Components/DecalComponent.h"
  140. #include "Kismet/HeadMountedDisplayFunctionLibrary.h"
  141. #include "ItemPickupCharacter.h"
  142. #include "Engine.h"
  143. AItemPickupPlayerController::AItemPickupPlayerController()
  144. {
  145.     bShowMouseCursor= true;
  146.     DefaultMouseCursor= EMouseCursor::Crosshairs;
  147. }
  148. void AItemPickupPlayerController::PlayerTick(floatDeltaTime)
  149. {
  150.     Super::PlayerTick(DeltaTime);
  151.     // keep updating the destination every tick while desired
  152.     if (bMoveToMouseCursor)
  153.     {
  154.         MoveToMouseCursor();
  155.     }
  156. }
  157. void AItemPickupPlayerController::SetupInputComponent()
  158. {
  159.     // set up gameplay key bindings
  160.     Super::SetupInputComponent();
  161.     InputComponent->BindAction("SetDestination",IE_Pressed, this, &AItemPickupPlayerController::OnSetDestinationPressed);
  162.     InputComponent->BindAction("SetDestination",IE_Released, this, &AItemPickupPlayerController::OnSetDestinationReleased);
  163.     // support touch devices
  164.     InputComponent->BindTouch(EInputEvent::IE_Pressed,this, &AItemPickupPlayerController::MoveToTouchLocation);
  165.     InputComponent->BindTouch(EInputEvent::IE_Repeat,this, &AItemPickupPlayerController::MoveToTouchLocation);
  166.     InputComponent->BindAction("ResetVR",IE_Pressed, this, &AItemPickupPlayerController::OnResetVR);
  167.     //Set Pickup Callback
  168.     InputComponent->BindAction("Pickup",IE_Pressed, this, &AItemPickupPlayerController::BeginPickup);
  169.     InputComponent->BindAction("Pickup",IE_Released, this, &AItemPickupPlayerController::EndPickup);
  170.     InputComponent->BindAction("Inventory",IE_Pressed, this, &AItemPickupPlayerController::ShowInventory);
  171. }
  172. void AItemPickupPlayerController::OnResetVR()
  173. {
  174.     UHeadMountedDisplayFunctionLibrary::ResetOrientationAndPosition();
  175. }
  176. void AItemPickupPlayerController::MoveToMouseCursor()
  177. {
  178.     if (UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayEnabled())
  179.     {
  180.         if (AItemPickupCharacter* MyPawn= Cast<AItemPickupCharacter>(GetPawn()))
  181.         {
  182.             if (MyPawn->GetCursorToWorld())
  183.             {
  184.                 UNavigationSystem::SimpleMoveToLocation(this, MyPawn->GetCursorToWorld()->GetComponentLocation());
  185.             }
  186.         }
  187.     }
  188.     else
  189.     {
  190.         // Trace to see what is under the mouse cursor
  191.         FHitResult Hit;
  192.         GetHitResultUnderCursor(ECC_Visibility,false, Hit);
  193.         if (Hit.bBlockingHit)
  194.         {
  195.             // We hit something, move there
  196.             SetNewMoveDestination(Hit.ImpactPoint);
  197.         }
  198.     }
  199. }
  200. void AItemPickupPlayerController::MoveToTouchLocation(constETouchIndex::TypeFingerIndex, constFVector Location)
  201. {
  202.     FVector2D ScreenSpaceLocation(Location);
  203.     // Trace to see what is under the touch location
  204.     FHitResult HitResult;
  205.     GetHitResultAtScreenPosition(ScreenSpaceLocation,CurrentClickTraceChannel,true,HitResult);
  206.     if (HitResult.bBlockingHit)
  207.     {
  208.         // We hit something, move there
  209.         SetNewMoveDestination(HitResult.ImpactPoint);
  210.     }
  211. }
  212. void AItemPickupPlayerController::SetNewMoveDestination(constFVector DestLocation)
  213. {
  214.     APawn* const MyPawn= GetPawn();
  215.     if (MyPawn)
  216.     {
  217.         UNavigationSystem*const NavSys = GetWorld()->GetNavigationSystem();
  218.         float const Distance = FVector::Dist(DestLocation,MyPawn->GetActorLocation());
  219.         // We need to issue move command only if far enough in order for walkanimation to play correctly
  220.         if (NavSys && (Distance > 120.0f))
  221.         {
  222.             NavSys->SimpleMoveToLocation(this,DestLocation);
  223.         }
  224.     }
  225. }
  226. void AItemPickupPlayerController::OnSetDestinationPressed()
  227. {
  228.     // set flag to keep updating destination until released
  229.     bMoveToMouseCursor= true;
  230. }
  231. void AItemPickupPlayerController::OnSetDestinationReleased()
  232. {
  233.     // clear flag to indicate we should stop updating the destination
  234.     bMoveToMouseCursor= false;
  235. }
  236. void AItemPickupPlayerController::BeginPickup()
  237. {
  238.     GEngine->AddOnScreenDebugMessage(-1,5.f,FColor::Blue,TEXT("Begin Pickup"));
  239.     bIsPickingUP= true;
  240. }
  241. void AItemPickupPlayerController::EndPickup()
  242. {
  243.     GEngine->AddOnScreenDebugMessage(-1,5.f, FColor::Blue, TEXT("End Pickup"));
  244.     bIsPickingUP= false;
  245. }
  246. void AItemPickupPlayerController::ShowInventory()
  247. {
  248.     GEngine->AddOnScreenDebugMessage(-1,5.f, FColor::Blue, TEXT("Show Inventory"));
  249.     for (auto& Item : Inventory)
  250.     {
  251.         GEngine->AddOnScreenDebugMessage(-1,5.f, FColor::Blue, FString::Printf(TEXT("Item: %s"),*Item));
  252.     }
  253. }
复制代码
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++实现游戏的简单交互。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-5 17:06 , Processed in 0.123631 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表