본문 바로가기

언리얼C++게임개발/10. 아이템 상자와 무기 제작

무기 무기상자 뺏기 Weapon ItemBox SetOwner

교재는 무기를 ItemBox로 부터 획득하지만 실제 들고다니다 다른 Chracter로 부딪치면 무기를 빼긴다. 이후 다시는 무기를 획득하지 못한다. 이 부분을 고쳐봤다. 그리고 itemBox뿐이 아니라 Weapon을 직접 획득할수도 있게 만들었다.

일단 ItemBox Class는 Collider를 담당하는 부분과 모양을 담당하는 Box부분, 효과부분이 있다.

무기는 WeponItemclass로 레벨에서 지정하고 spawn할때 사용한다.

public:	

	UPROPERTY(EditInstanceOnly, Category = Box)
	TSubclassOf<class AABWeapon> WeaponItemClass;

	UPROPERTY(VisibleAnywhere, Category = Box)
	UBoxComponent* Trigger;

	UPROPERTY(VisibleAnywhere, Category = Box)
	UStaticMeshComponent* Box;

	UPROPERTY(EditInstanceOnly, Category = Box)
	UParticleSystemComponent* Effect;

플레이어가 상자를 건드리면 Bind된 OnCharacterOverlap이 실행되고

void AABItemBox::PostInitializeComponents()
{
    Super::PostInitializeComponents();
    Trigger->OnComponentBeginOverlap.AddDynamic(this, &AABItemBox::OnCharacterOverlap);
}

OnCharacterOverlap()에서 캐릭터를 체크하고 WeaponItemClass를 Spawn해주고 캐릭터의 SetWeapon()를 불러준다.

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)
    {
        TakeWeapon(ABCharacter);
    }
}
void AABItemBox::TakeWeapon(AABCharacter * ABCharacter)
{
    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);
}

AABCharacter의 SetWeapon에서 NewWeapon 클래스를 받아 hand_rSocket에 붙여준다. 이후 CurrentWepon에 저장해준다.

void AABCharacter::SetWeapon(AABWeapon* NewWeapon)
{
	ABCHECK(nullptr != NewWeapon && nullptr == CurrentWeapon);
	FName WeaponSocket(TEXT("hand_rSocket"));
	if (nullptr != NewWeapon)
	{
		if (CurrentWeapon) {
			CurrentWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, TEXT("spine_01Socket"));
			//ResetWeapon();
		}

		NewWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, WeaponSocket);
		NewWeapon->SetOwner(this);
		CurrentWeapon = NewWeapon;
	}
}

무기가 없을때 무기를 주우면

LogTemp: Warning: OnCharacterOverlap call TakeWeapon ABCharacter_0 BP_WeaponAxe11
LogTemp: Warning: TakeWeapon ABCharacter_0 BP_WeaponAxe11

 

무기를 갖고 다른 무기를 주우면

LogTemp: Warning: OnCharacterOverlap call TakeWeapon ABCharacter_0 BP_BlackSword1
LogTemp: Warning: TakeWeapon ABCharacter_0 BP_BlackSword1
LogTemp: Warning: ResetWeapon ABCharacter0 BP_WeaponAxe11

 

무기를 갖고 BP_ABCharacter와 부딪치면 양쪽에서 다 OverlapEvent가 발생한다.
LogTemp: Warning: OnCharacterOverlap BP_ABCharacter_C_1 BP_BlackSword1
LogTemp: Warning: ResetWeapon ABCharacter0 BP_BlackSword1
LogTemp: Warning: OnCharacterOverlap call TakeWeapon BP_ABCharacter_C_1 BP_BlackSword1
LogTemp: Warning: TakeWeapon BP_ABCharacter_C_1 BP_BlackSword1
LogTemp: Warning: OnCharacterOverlap call TakeWeapon BP_ABCharacter_C_1 BP_BlackSword1
LogTemp: Warning: TakeWeapon BP_ABCharacter_C_1 BP_BlackSword1
BP_ABCharacter에게 다시 뺏음.
LogTemp: Warning: OnCharacterOverlap ABCharacter_0 BP_BlackSword1
LogTemp: Warning: ResetWeapon BP_ABCharacter1 BP_BlackSword1
LogTemp: Warning: OnCharacterOverlap call TakeWeapon ABCharacter_0 BP_BlackSword1
LogTemp: Warning: TakeWeapon ABCharacter_0 BP_BlackSword1
LogTemp: Warning: OnCharacterOverlap call TakeWeapon ABCharacter_0 BP_BlackSword1
LogTemp: Warning: TakeWeapon ABCharacter_0 BP_BlackSword1