플레이어, 적 또는 오브젝트에 대해 모든 종류의 대미지를 입힐 수 있는 게임을 제작하는 경우 그러한 오브젝트가 누구에게 맞았는지, 맞았다면 무엇으로 맞았는지, 임팩트 포인트는 어디인지, 기타 탐지된 히트와 관련된 정보를 판정해야 하는 상황이 발생합니다. OnHit 이벤트는 콜리전이 발생할 때 이러한 정보를 제공하며, 이 데이터를 활용하여 게임 내에서 변화를 유발할 수 있습니다. 여기에는 체력에 영향을 미치거나, 오브젝트를 파괴하거나, 기타 게임플레이와 관련된 액션을 발생시키는 것 등이 포함됩니다.
이 튜토리얼에서는 OnComponentHit 및 함수 이벤트를 사용하여 액터에 대미지를 적용하고 액터의 메시 머티리얼을 변경하여 이를 표현하는 방법을 살펴봅니다. 또한 이 이벤트는 히트 위치에 임펄스를 적용하여 액터를 밀어내고 발사체로 인한 히트 이펙트를 시뮬레이션하여 히트 위치에 힘을 적용합니다.
Project Setup
Begin by creating a new Games > First Person > C++ Project named OnHit.
Creating the Mesh Material
Navigate to the Content Browser, and find the LevelPrototyping/Materials folder.
Select MI_SolidBlue, then duplicate (CTRL+ D) and rename the newly duplicated asset MI_Solid_Red.
Double-click to open the asset, then select and edit the Base Color to the color red.
Save the Asset.
Creating the Cube Actor
In the Editor, click Add(+) > New C++ Class, then choose Actor as your parent class and name your class Cube.
Declare the following class defaults in your
cube.hfileC++UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) class UStaticMeshComponent* CubeMesh; UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) UMaterialInstance* CubeMaterial; UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) UMaterialInstance* DamagedCubeMaterial; FTimerHandle DamageTimer;Next, in your
cube.cppfile, declare the following class libraries.C++#include "Kismet/GameplayStatics.h" #include "OnHitProjectile.h"Navigate to the cube constructor and implement the following functionality.
C++ACube::ACube() { CubeMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CubeMesh")); DamagedCubeMaterial = CreateDefaultSubobject<UMaterialInstance>(TEXT("DamageMaterial")); CubeMaterial = CreateDefaultSubobject<UMaterialInstance>(TEXT("CubeMaterial")); CubeMesh->SetSimulatePhysics(true); }
Implementing the Damage functionality
Now that you created a cube, you need to implement a function that sets the mesh's material when it receives damage, then after a delay resets the mesh back to its original material.
Declare the following code in your
cube.hfile.C++void OnTakeDamage(); void ResetDamage();Navigate to the
cube.cppfile and implement the following for theACube::BeginPlayfunction.C++void ACube::BeginPlay() { CubeMesh->OnComponentHit.AddDynamic(this, &ACube::OnComponentHit); }Implement the
ACube::OnTakeDamagefunction.C++void ACube::OnTakeDamage() { CubeMesh->SetMaterial(0, DamagedCubeMaterial); GetWorld()->GetTimerManager().SetTimer(DamageTimer, this, &ACube::ResetDamage, 1.5f, false); }Next, implement the
ACube::ResetDamagefunction.C++void ACube::ResetDamage() { CubeMesh->SetMaterial(0,CubeMaterial); }Finally, navigate to the
ACube::OnComponentHitfunction and implement the following code.C++void ACube::OnComponentHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) { if (AOnHitProjectile* HitActor = Cast<AOnHitProjectile>(OtherActor)) { UGameplayStatics::ApplyDamage(this, 20.0f, nullptr, OtherActor, UDamageType::StaticClass()); OnTakeDamage(); } }Compile your code.
In the editor, navigate to C++ Classes > Cube then right-click on the Cube Actor and select Create Blueprint class based on Cube.
From the Components tab, select the Cube Mesh, then navigate to Details > Static Mesh and select the SM_ChamferCube asset.
In the class defaults of the BP_Cube, set the Cube Material to the MI_Solid_Blue asset, and the Damaged Cube Material to the MI_Solid_Red asset.
Compile and Save.
CubeActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Cube.generated.h"
UCLASS()
class ONHIT_API ACube : public AActor
{
GENERATED_BODY()
CubeActor.cpp
#include "Cube.h"
#include "Kismet/GameplayStatics.h"
#include "OnHitProjectile.h"
// Sets default values
ACube::ACube()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
Setting up the Level
Drag the BP_Cube into the level from the Content Browser.
Navigate to the Outliner > Simulated Cubes, select all SM_ChauferCubes then right-click and select Replace Selected Actors with > BP_Cube.
Click Play to play in the editor and use the left-mouse button to fire a projectile at the cube.
When you play in the editor, you will see that when you hit the cube with the projectile fired it causes the cube to take damage and change its mesh material, and applies an impulse at the location where it was hit causing it to move opposite the direction of the projectile.
The amount of force applied is defined inside the
OnHitProjectile.cppfile which uses the OnHit function to determine when the projectile actually hits something.C++void AOnHitCPPProjectile::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) { // Only add impulse and destroy projectile if we hit a physics if ((OtherActor != nullptr) && (OtherActor != this) && (OtherComp != nullptr) && OtherComp->IsSimulatingPhysics()) { OtherComp->AddImpulseAtLocation(GetVelocity() * 100.0f, GetActorLocation()); Destroy(); }