๐ ์ ๋ฐ๋ฏธ GAS ๊ฐ์ ์ค ๊ธฐ๋กํด๋๊ณ ์ถ์ ๋ด์ฉ์ ์ ์ด๋ ํฌ์คํธ
Section 1 : ํ๋ก์ ํธ ์์ฑ๊ณผ ์บ๋ฆญํฐ, ์ธํ ๋ฑ ๊ธฐ๋ณธ ์ ์ ์ ๋ค๋ฃจ๊ณ ์์
{ํ๋ก์ ํธ๋ช
}.bulid.cs
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" , "EnhancedInput" });
Input Mapping Context , Input Action ํ์
// AuraPlayerController ํด๋์ค์ ๋ฉค๋ฒ
UPROPERTY(EditAnywhere, Category="Input")
TObjectPtr<UInputMappingContext> AuraContext;
UPROPERTY(EditAnywhere, Category="Input")
TObjectPtr<UInputAction> MoveAction;
EnhancedInput Subsystem์ ๋ฑ๋ก
EnhancedInputLocalPlayerSubsystem์ InputMappingContext ์ถ๊ฐํ๊ธฐcheck()์ผ๋ก ValidCheck : Throw ASSERTvoid AAuraPlayerController::BeginPlay()
{
Super::BeginPlay();
// Assert , ์ธํ์ด ์ ๋๋ก ์ ๋๋ฉด ์ด์ฐจํผ ๊ฒ์ ๋ชปํจ
check(AuraContext);
UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer());
check(Subsystem);
Subsystem->AddMappingContext(AuraContext,0);
}
SetupInputComponent์์ InputAction๊ณผ ๋์ ํจ์ ๋ฐ์ธ๋ฉํ๊ธฐ
InputComponent๋ ์ปจํธ๋กค๋ฌ์ ์๋ ์๋ ๋ฉค๋ฒ๊ณ ํ๋ก์ ํธ ์ค์ ์์ ์ธํธ์ค๋์ธํ ์ปดํฌ๋ํธ๊ฐ ๋ํดํธ ํด๋์ค๋ก ์ค์ ๋์ด ์๊ธฐ ๋๋ฌธ์ ์บ์คํ
์ด ๊ฐ๋ฅํ ๊ฒ.(๋ํดํธ ํด๋์ค ๋ณ๊ฒฝํ๋ฉด ์ ๋ ์ ์์)CastChecked<>() : ์บ์คํ
+ Valid Check (๋ฐ๋์ ์ฑ๊ณตํด์ผํ๋ ์ํฉ์ ์ฌ์ฉ)void AAuraPlayerController::SetupInputComponent()
{
Super::SetupInputComponent();
// ํ๋ก์ ํธ ๋ํดํธ ์ค์ ์ ์ธํธ์ค๋์ธํ ์ปดํฌ๋ํธ๊ฐ ์ค์ ๋์ด ์๊ธฐ๋๋ฌธ์ ์บ์คํ
๊ฐ๋ฅ
UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(InputComponent);
EnhancedInputComponent->BindAction(MoveAction,ETriggerEvent::Triggered,this,&AAuraPlayerController::Move);
}
์ ๋ ฅ ๋ฐ์ดํฐ ๋ฐ์์ค๊ธฐ
FInputActionValue ๋ฅผ ์ ์ ํ ๋ฐ์ดํฐ ์ ํ์ผ๋ก ์บ์คํ
ํด์ ์ฌ์ฉ (InputAction์ ์ด๋ฏธ ์ค์ ๋ ์ ํ์ด ์์)void AAuraPlayerController::Move(const FInputActionValue& InputActionValue)
{
const FVector2d InputAxisVector = InputActionValue.Get<FVector2D>();
...
}
bOrientRotationToMovement : ์
๋ ฅ ๋ฐฉํฅ์ ๋ฐ๋ผ ์บ๋ฆญํฐ ํ์
AAuraCharacter::AAuraCharacter()
{
// ํ๋ค์ด ๋ทฐ๋ก ์งํ๋๋ ๊ฒ์์ด๋ฏ๋ก ์นด๋ฉ๋ผ๋ ๊ณ ์ ๋์ด์๊ณ ์
๋ ฅ ๋ฐฉํฅ์ ๋ฐ๋ผ ์บ๋ฆญํฐ๊ฐ ํ์ ํ๋๋ก ์ค์
GetCharacterMovement()->bOrientRotationToMovement = true;
GetCharacterMovement()->RotationRate = FRotator(0.f, 400.f, 0.f);
// ์บ๋ฆญํฐ๊ฐ ๋ฐ๋ฅ์ ๋ถ์ด์๋๋ก ์ค์
GetCharacterMovement()->bConstrainToPlane = true;
GetCharacterMovement()->bSnapToPlaneAtStart = true;
bUseControllerRotationPitch = false;
bUseControllerRotationYaw = false;
bUseControllerRotationRoll = false;
}
TObjectPrt<T> : ์ค๋งํธ ํฌ์ธํฐ
TObjectPrt<T> ์ฌ์ฉ ๊ถ์ฅUPROPERTY(EditAnywhere,Category="Combat")
TObjectPtr<USkeletalMeshComponent> Weapon;
TScriptInterface<T> : ์ธํฐํ์ด์ค ํฌ์ธํฐ ๋ํผ
TScriptInterface<IEnemyInterface> LastActor;
FName ๊ตฌ์กฐ์ฒด๋ ๋์๋ฌธ์ ๊ตฌ๋ณ์ด ์๋ ๊ฐ์ํ๋ ๋ฌธ์์ด์ด๋ฏ๋ก ๊ตณ์ด ํ ์คํธ ๋งคํฌ๋ก ์ฌ์ฉํ์ง ์๊ณ ๋ฐ๋ก ๋๊ฒจ์ค๋ ๊ด์ฐฎ๋ค.
AAuraCharacterBase::AAuraCharacterBase()
{
PrimaryActorTick.bCanEverTick = false;
// FName์๋ ํ
์คํธ ๋งคํฌ๋ก ์ฐ์ง ์์๋ ๋จ , FString์ ์ฌ์ฉ
Weapon = CreateDefaultSubobject<USkeletalMeshComponent>("Weapon");
Weapon->SetupAttachment(GetMesh(),"WeaponHandSocket");
}

ํ๋ก์ ํธ ์ธํ
- ์์ง ๋ ๋๋ง ์ธํ
- Custom Depth Stencil Pass ๋ถ๋ถ - Enable with Stencil๋ก ์ค์
ํฌ์คํธ ํ๋ก์ธ์ค ๋ณผ๋ฅจ์ ๋จธํฐ๋ฆฌ์ผ ์ถ๊ฐ ํ์
(๋จธํฐ๋ฆฌ์ผ์ ๋ฐ๋ก ๋ง๋ค์ด์ค์ผ ํจ. ์ด ๊ฐ์์์๋ ๊ฐ์ด ์ ๊ณตํด์ฃผ๋ ์ธ๊ณฝ์ ๋จธํฐ๋ฆฌ์ผ์ ์ฌ์ฉํ์)
์กํฐ์์ ๋ ๋ ์ต์
์ผ์ฃผ๊ธฐ
SetCustomDepthStencilValue(CUSTOM_DEPTH_RED) : ๋จธํฐ๋ฆฌ์ผ์์ ์ฌ์ฉํ ์ปค์คํ
๋ฐธ๋ฅ์ ์ผ์น์์ผ์ฃผ๋ฉด ๋๋ค.
SetRenderCustomDepth(true)
AAuraEnemy::AAuraEnemy()
{
GetMesh()->SetCollisionResponseToChannel(ECC_Visibility,ECR_Block);
// #define ๋งคํฌ๋ก๋ฅผ ์ฌ์ฉํด์ ์์ ์ฌ์ฉ ์ต์ํ
GetMesh()->SetCustomDepthStencilValue(CUSTOM_DEPTH_RED);
if (Weapon)
{
Weapon->SetCustomDepthStencilValue(CUSTOM_DEPTH_RED);
}
}
void AAuraEnemy::HighlightActor()
{
GetMesh()->SetRenderCustomDepth(true);
if (Weapon)
{
Weapon->SetRenderCustomDepth(true);
}
}
LastActor์ ThisActor๋ฅผ ํ์ฉํ ์กํฐ ์ ํ ๊ฒฝ์ฐ์ ์
/**
* Line trace from cursor. There are several scenarios:
* A. LastActor is null && ThisActor is null
* - Do nothing
* B. LastActor is null && ThisActor is valid
* - Highlight ThisActor
* C. LastActor is valid && ThisActor is null
* - UnHighlight LastActor
* D. Both actors are valid, but LastActor != ThisActor
* - UnHighlight LastActor, and Highlight ThisActor
* E. Both actors are valid, and are the same actor
* - Do nothing
*/
if (LastActor == nullptr)
{
if (ThisActor != nullptr)
{
// Case B
ThisActor->HighlightActor();
}
else
{
// Case A - both are null, do nothing
}
}
else // LastActor is valid
{
if (ThisActor == nullptr)
{
// Case C
LastActor->UnHighlightActor();
}
else // both actors are valid
{
if (LastActor != ThisActor)
{
// Case D
LastActor->UnHighlightActor();
ThisActor->HighlightActor();
}
else
{
// Case E - do nothing
}
}
}

๋ง์ฐ์ค๋ฅผ ์ฌ๋ ธ์ ๋ ์ํ๋ ์กํฐ์ ๋ค์ํ๊ฒ ์ ๋์ ์ผ๋ก ์ ์ฉํ ์ ์๋๋ก ์ธํฐํ์ด์ค๋ฅผ ๋ง๋ค์๋ค.
Unreal Interface์ ์์ ํด๋์ค
UINTERFACE(MinimalAPI)
class UEnemyInterface : public UInterface
{
GENERATED_BODY()
};
class AURA_API IEnemyInterface
{
GENERATED_BODY()
public:
// ์์ ๊ฐ์ ํจ์
virtual void HighlightActor() = 0;
virtual void UnHighlightActor() = 0;
};
์ธํฐํ์ด์ค ์์ ๋ฐ๊ธฐ
UCLASS()
class AURA_API AAuraEnemy : public AAuraCharacterBase, public IEnemyInterface // ์ธํฐํ์ด์ค ์์
{
GENERATED_BODY()
public:
AAuraEnemy();
virtual void HighlightActor() override;
virtual void UnHighlightActor() override;
};

ํฌ์ธํฐ๋ ์ฐธ์กฐํ ๋ฉค๋ฒ์ธ ๊ฒฝ์ฐ ํค๋์ ํด๋น ํด๋์ค๋ ๊ตฌ์กฐ์ฒด๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ๋ค๋ฅธ ํค๋๋ฅผ include ํ ํ์๊ฐ ์๋ค.
class UCapsuleComponent* CapsuleComp;AuraPlayerController ์์
// ์ ๋ฐฉ์ ์ธ
class IEnemyInterface;
struct FInputActionValue; // Ftype ๊ตฌ์กฐ์ฒด๋ struct๋ก ์ ๋ฐฉ์ ์ธ
class UInputAction;
class UInputMappingContext;
UCLASS()
class AURA_API AAuraPlayerController : public APlayerController
{
GENERATED_BODY()
public:
AAuraPlayerController();
virtual void PlayerTick(float DeltaTime) override;
protected:
virtual void BeginPlay() override;
virtual void SetupInputComponent() override;
private:
UPROPERTY(EditAnywhere, Category="Input")
TObjectPtr<UInputMappingContext> AuraContext; // ์ ๋ฐฉ์ ์ธ
UPROPERTY(EditAnywhere, Category="Input")
TObjectPtr<UInputAction> MoveAction; // ์ ๋ฐฉ์ ์ธ
void Move(const FInputActionValue& InputActionValue); // ์ ๋ฐฉ์ ์ธ
void CursorTrace();
TScriptInterface<IEnemyInterface> LastActor; // ์ ๋ฐฉ์ ์ธ
TScriptInterface<IEnemyInterface> ThisActor; // ์ ๋ฐฉ์ ์ธ
};
https://github.com/jongmin7759/Unreal_GAS/commit/78bec3f628f2db222f3c95159b420ca135ac8360