먼저 사용할 예제를 불러온다.
그리고 내가 사용했던 캐릭터 스켈레탈에서 rSocket(오른쪽 손 소켓) 에 무기를 넣어줍니다.
이런식으로 자연스럽게 만들어준다.
이런식으로 애니메이션도 테스트해볼수 있다.
캐릭터 선언부에
추가 해줍니다.
구현부에는 이렇게 추가 해주면 자동으로 위치를 찾아준다.
짜잔. 뭔가 게임같고 멋있따..
일단 무기액터를 만들어보자,
ABWeapon.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "Arenabattle/ArenaBattle.h"
#include "GameFramework/Actor.h"
#include "ABWeapon.generated.h"
UCLASS()
class ARENABATTLE_API AABWeapon : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AABWeapon();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
UPROPERTY(VisibleAnywhere, Category = Weapon)
USkeletalMeshComponent* Weapon;
};
ABWeapon.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "ABWeapon.h"
// Sets default values
AABWeapon::AABWeapon()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = false;
Weapon = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("WEAPON"));
RootComponent = Weapon;
static ConstructorHelpers::FObjectFinder<USkeletalMesh> SK_WEAPON(TEXT("/Game/InfinityBladeWeapons/Weapons/Blade/Swords/Blade_BlackKnight/SK_Blade_BlackKnight.SK_Blade_BlackKnight"));
if (SK_WEAPON.Succeeded())
{
Weapon->SetSkeletalMesh(SK_WEAPON.Object);
}
Weapon->SetCollisionProfileName(TEXT("NoCollision"));
}
// Called when the game starts or when spawned
void AABWeapon::BeginPlay()
{
Super::BeginPlay();
}
캐릭터 구현부에
추가 해준다.
새로운 C++ 클래스를 또 만들어준다음,
애셋에 들어가줍니다.
그리고 빌드 세팅을 1.5배로 합니다.
(스크립트는 마지막에)
그리고 전과 같이 콜리전 채널을 만듭니다.
프로파일도 만들어준다.
캐릭터도 바꿔준ㄴ다.
ABWeapon를 상속받는 블루프린트를 한개 만들어줍니다.
스칼레테 메시 에셋을 도끼로 바꿉니다.
그리고 설치해둔 박스의 컴포넌트를 방금 만든 블루프린트로 변경 해줍니다.
그러면 상자를 획득할때 도끼가 쥐어진다.
ABItemBox.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "ArenaBattle/ArenaBattle.h"
#include "GameFramework/Actor.h"
#include "ABItemBox.generated.h"
UCLASS()
class ARENABATTLE_API AABItemBox : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AABItemBox();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
virtual void PostInitializeComponents() override;
public:
UPROPERTY(VisibleAnywhere, Category = Box)
UBoxComponent* Trigger;
UPROPERTY(VisibleAnywhere, Category = Box)
UStaticMeshComponent* Box;
UPROPERTY(VisibleAnywhere, Category = Effect)
UParticleSystemComponent* Effect;
UPROPERTY(EditInstanceOnly, Category = Box)
TSubclassOf<class AABWeapon> WeaponItemClass;
private:
UFUNCTION()
void OnCharacterOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
UFUNCTION()
void OnEffectFinished(class UParticleSystemComponent* pSystem);
};
ABItemBox.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "ABItemBox.h"
#include "ABWeapon.h"
#include "ABCharacter.h"
// Sets default values
AABItemBox::AABItemBox()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = false;
Trigger = CreateDefaultSubobject<UBoxComponent>(TEXT("TRIGGER"));
Box = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BOX"));
Effect = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("EFFECT"));
RootComponent = Trigger;
Box->SetupAttachment(RootComponent);
Effect->SetupAttachment(RootComponent);
Trigger->SetBoxExtent(FVector(40.0f, 42.0f, 30.f));
static ConstructorHelpers::FObjectFinder<UStaticMesh> SM_BOX(TEXT("/Game/InfinityBladeGrassLands/Environments/Breakables/StaticMesh/Box/SM_Env_Breakables_Box1.SM_Env_Breakables_Box1"));
if (SM_BOX.Succeeded()) {
Box->SetStaticMesh(SM_BOX.Object);
}
static ConstructorHelpers::FObjectFinder<UParticleSystem> P_CHESTOPEN(TEXT("/Game/InfinityBladeGrassLands/Effects/FX_Treasure/Chest/P_TreasureChest_Open_Mesh.P_TreasureChest_Open_Mesh"));
if (P_CHESTOPEN.Succeeded()) {
Effect->SetTemplate(P_CHESTOPEN.Object);
Effect->bAutoActivate = false;
}
Box->SetRelativeLocation(FVector(0.0f, -3.5f, -30.0f));
Trigger->SetCollisionProfileName(TEXT("ItemBox"));
Box->SetCollisionProfileName(TEXT("NoCollision:"));
WeaponItemClass = AABWeapon::StaticClass();
}
// Called when the game starts or when spawned
void AABItemBox::BeginPlay()
{
Super::BeginPlay();
}
void AABItemBox::PostInitializeComponents() {
Super::PostInitializeComponents();
Trigger->OnComponentBeginOverlap.AddDynamic(this, &AABItemBox::OnCharacterOverlap);
}
void AABItemBox::OnCharacterOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) {
ABLOG_S(Warning);
auto ABCharacter = Cast<AABCharacter>(OtherActor);
ABCHECK(nullptr != ABCharacter);
if (nullptr != ABCharacter && nullptr != WeaponItemClass)
{
if (ABCharacter->CanSetWeapon())
{
auto NewWeapon = GetWorld()->SpawnActor<AABWeapon>(WeaponItemClass, FVector::ZeroVector, FRotator::ZeroRotator);
ABCharacter->SetWeapon(NewWeapon);
Effect->Activate(true);
Box->SetHiddenInGame(true, true);
SetActorEnableCollision(false);
Effect->OnSystemFinished.AddDynamic(this, &AABItemBox::OnEffectFinished);
}
else {
ABLOG(Warning, TEXT("%s can't equip weapon currently."), *ABCharacter->GetName());
}
}
}
void AABItemBox::OnEffectFinished(UParticleSystemComponent* PSystem) {
Destroy();
}
ABWeapon.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "Arenabattle/ArenaBattle.h"
#include "GameFramework/Actor.h"
#include "ABWeapon.generated.h"
UCLASS()
class ARENABATTLE_API AABWeapon : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AABWeapon();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
UPROPERTY(VisibleAnywhere, Category = Weapon)
USkeletalMeshComponent* Weapon;
};
AbWeapon.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "ABWeapon.h"
// Sets default values
AABWeapon::AABWeapon()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = false;
Weapon = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("WEAPON"));
RootComponent = Weapon;
static ConstructorHelpers::FObjectFinder<USkeletalMesh> SK_WEAPON(TEXT("/Game/InfinityBladeWeapons/Weapons/Blade/Swords/Blade_BlackKnight/SK_Blade_BlackKnight.SK_Blade_BlackKnight"));
if (SK_WEAPON.Succeeded())
{
Weapon->SetSkeletalMesh(SK_WEAPON.Object);
}
Weapon->SetCollisionProfileName(TEXT("NoCollision"));
}
// Called when the game starts or when spawned
void AABWeapon::BeginPlay()
{
Super::BeginPlay();
}