[Unreal] Hard Reference vs. Soft Reference
Hard Reference
// PlayerCharacter.h
#include "Engine/StaticMesh.h"
#include "Components/StaticMeshComponent.h"
UCLASS()
class MYGAME_API APlayerCharacter : public ACharacter
{
GENERATED_BODY()
public:
// Hard Reference - ์๋ํฐ์์ ์ง์ ํ ๋น
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Weapon")
UStaticMesh* WeaponMesh;
// Hard Reference - ์๋ช
์ฃผ๊ธฐ๋ฅผ ํจ๊ป ๊ฐ์ ธ๊ฐ๋ ์ปดํฌ๋ํธ
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
UStaticMeshComponent* WeaponMeshComponent;
};
// PlayerCharacter.cpp
APlayerCharacter::APlayerCharacter()
{
WeaponMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WeaponMeshComponent"));
// Hard Reference - ์์ฑ์์์ ์ง์ ๋ก๋ (๊ฒ์ ์์์ ๋ฐ๋ก ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋๋จ)
static ConstructorHelpers::FObjectFinder<UStaticMesh> WeaponMeshAsset(
TEXT("/Game/Weapons/Sword_Mesh.Sword_Mesh"));
if (WeaponMeshAsset.Succeeded())
{
WeaponMesh = WeaponMeshAsset.Object;
WeaponMeshComponent->SetStaticMesh(WeaponMesh);
}
}
- ์ปดํ์ผ ํ์์ ์์กด์ฑ์ด ๊ฒฐ์ ๋๋ค
- ์ฐธ์กฐํ๋ ์ค๋ธ์ ํธ๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ํญ์ ๋ก๋๋์ด ์์ด์ผ ํ๋ค
- ์ด๋ก ์ธํด ์ด๋ฐ ๋ก๋ฉ ์๊ฐ์ด ๊ธธ์ด์ง๋ค
- ์์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋๋ ๋์ด๋๋ค
- ํด๋น ๋ฉ๋ชจ๋ฆฌ์ ๋น ๋ฅด๊ฒ ์ ๊ทผํ ์ ์๋ค
Soft Reference
// PlayerCharacter.h
#include "Engine/StreamableManager.h"
UCLASS()
class MYGAME_API APlayerCharacter : public ACharacter
{
GENERATED_BODY()
public:
APlayerCharacter();
// Soft Reference - ๊ฒฝ๋ก๋ง ์ ์ฅ, ์ค์ ์ค๋ธ์ ํธ๋ ๋ก๋๋์ง ์์
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Weapon")
TSoftObjectPtr<UStaticMesh> WeaponMeshSoft;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
UStaticMeshComponent* WeaponMeshComponent;
UFUNCTION(BlueprintCallable)
void LoadWeaponAsync();
UFUNCTION(BlueprintCallable)
void LoadWeaponSync();
private:
FStreamableManager StreamableManager;
};
// PlayerCharacter.cpp
APlayerCharacter::APlayerCharacter()
{
WeaponMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WeaponMeshComponent"));
// Soft Reference - ๊ฒฝ๋ก๋ง ์ค์ (๋ฉ๋ชจ๋ฆฌ์ ๋ก๋๋์ง ์์)
WeaponMeshSoft = TSoftObjectPtr<UStaticMesh>(FSoftObjectPath(TEXT("/Game/Weapons/Sword_Mesh.Sword_Mesh")));
}
void APlayerCharacter::LoadWeaponAsync()
{
// ๋น๋๊ธฐ ๋ก๋
StreamableManager.RequestAsyncLoad(
WeaponMeshSoft.ToSoftObjectPath(),
FStreamableDelegate::CreateLambda([this]()
{
if (UStaticMesh* LoadedMesh = WeaponMeshSoft.Get())
{
WeaponMeshComponent->SetStaticMesh(LoadedMesh);
}
})
);
}
void APlayerCharacter::LoadWeaponSync()
{
// ๋๊ธฐ ๋ก๋
if (UStaticMesh* LoadedMesh = WeaponMeshSoft.LoadSynchronous())
{
WeaponMeshComponent->SetStaticMesh(LoadedMesh);
}
}
- ํ์ ์์ ๋ก๋ํ ์ ์๋ค (๋น๋๊ธฐ ๋ก๋)
- ์ด๊ธฐ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ์ ๋ค
- ๋ก๋ ์ ์ฝ๊ฐ์ ์ง์ฐ์ด ๋ฐ์ํ ์ ์๋ค
- ๋์ฉ๋ ์์ ๊ด๋ฆฌ์ ํจ์จ์ ์ด๋ค
๋ฉ๋ชจ๋ฆฌ ์ํ ํ์ธ
void APlayerCharacter::CheckReferenceStatus()
{
// Hard Reference์ ๊ฒฝ์ฐ
bool bHardRefValid = (WeaponMesh != nullptr); // ํญ์ true (์ด๋ฏธ ๋ก๋๋จ)
// Soft Reference์ ๊ฒฝ์ฐ
bool bSoftRefLoaded = (WeaponMeshSoft.Get() != nullptr); // ๋ก๋ ํ์๋ง true
bool bSoftRefPathValid = WeaponMeshSoft.IsValid(); // ๊ฒฝ๋ก๊ฐ ์ ํจํ๋ฉด true
}
When to use
Hard Reference
- ์๋ช
์ฃผ๊ธฐ ๊ด๋ฆฌ
- ๋ฉค๋ฒ ๋ณ์ uojbect์์ ๊ด๊ณ๊ฐ ๋ถ๋ชจ ์์ ๊ด๊ณ๋ก์, ๋ถ๋ชจ์๊ฒ Ownership์ ๋ถ์ฌํ๊ณ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๋์ผํ๊ฒ ๊ฐ์ ธ๊ฐ์ผ ํ ๋
- ํญ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋๋์ด ์์ด์ผ ํ ๋
Soft Reference
- ์ง์ฐ ๋ก๋ฉ์ด ํ์ํ ๊ฒฝ์ฐ
- ๊ฒ์์ ์งํ์ ๋ง์ง ์์ผ๋ฉด์ ๋ก๋ฉํด๋ ๋๋ ๊ฒฝ์ฐ
- ์ํ ์ฐธ์กฐ ๋ฐฉ์ง
UCLASS()
class APlayerController : public AController
{
// ํ๋ ์ด์ด๊ฐ ํ์ฌ ์ํธ์์ฉํ๋ ์ค๋ธ์ ํธ (์์ ์๋ ์์)
UPROPERTY()
TWeakObjectPtr<class AInteractableActor> CurrentInteractTarget;
// ํ์ฌ ์ฅ์ฐฉํ ๋ฌด๊ธฐ (๋งจ์์ผ ์๋ ์์)
UPROPERTY()
TWeakObjectPtr<class AWeapon> CurrentWeapon;
};
- ์ต์
๋ํ ์ฐธ์กฐ
- ์์ด๋ ๊ทธ๋ง, ์์ด๋ ๊ทธ๋ง์ธ ์ฐธ์กฐ
์ถ์ฒ
- https://docs.unrealengine.com/4.26/ko/ProgrammingAndScripting/ProgrammingWithCPP/Assets/ReferencingAssets/
- https://hyo-ue4study.tistory.com/435
- https://docs.unrealengine.com/4.27/ko/ProductionPipelines/Redirectors/
- https://forums.unrealengine.com/t/can-someone-explain-soft-variable-references/444524/2