[Unreal_C++_DarkSoul]#7_문제 해결, Magic Projectile

2022. 12. 17. 15:03· 개인프로젝트
목차
  1.  
  2. [Unreal_C++_DarkSoul]#7_Magic Projectile

 

 

[Unreal_C++_DarkSoul]#7_Magic Projectile

 

Player의 "Wizard" 공격 모드에서 활용하는 마법 발사체 개발 내용입니다.

포트폴리오 진행 사항을 기록하기 위한 포스팅입니다.

 


 

Overview

 

  1. 문제점
  2. 문제 해결
  3. 문제 해결 후 결과 코드

 

문제점

1. AMagic::SpawnMagicBall()

void AMagic::SpawnMagicBall(const FName& InSocketName)
{

	// Transform
	AActor* OwnerActor = GetOwner();
	CheckNull(OwnerActor);

	APlayerCharacter* Player = Cast<APlayerCharacter>(OwnerActor);
	CheckNull(Player);

	FVector SpawnLocation = Player->GetMesh()->GetSocketLocation(InSocketName);
	FRotator SpawnRotation = Player->GetActorRotation();
	FTransform SpawnTransform = FTransform(SpawnRotation, SpawnLocation);

	// Spawn
	switch (MagicProjectileType)
	{
	case EMagicProjectileType::E_MagicBall:
		CheckNull(ProjectileSpawner);
		ProjectileSpawner->SpawnProjectile((int32)EMagicProjectileType::E_MagicBall, InSocketName);
		break;
	case EMagicProjectileType::E_SkullBall:
		CheckNull(MagicProjectileClass[(int32)EMagicProjectileType::E_SkullBall]);
		MagicProjectile = GetWorld()->SpawnActor<AProjectile_MagicSkullBall>(MagicProjectileClass[(int32)EMagicProjectileType::E_SkullBall], SpawnTransform);
		MagicProjectile->SetOwner(this);
		break;
	case EMagicProjectileType::E_Ray:
		CheckNull(MagicProjectileClass[(int32)EMagicProjectileType::E_Ray]);
		SpawnTransform = FTransform(SpawnRotation, SpawnLocation);
		MagicProjectile = GetWorld()->SpawnActor<AProjectile_MagicRay>(MagicProjectileClass[(int32)EMagicProjectileType::E_Ray], SpawnTransform);
		MagicProjectile->SetOwner(this);
		break;
	case EMagicProjectileType::E_Tornado:
		CheckNull(MagicProjectileClass[(int32)EMagicProjectileType::E_Tornado]);
		SpawnTransform = FTransform(SpawnRotation, SpawnLocation);
		MagicProjectile = GetWorld()->SpawnActor<AProjectile_MagicTornado>(MagicProjectileClass[(int32)EMagicProjectileType::E_Tornado], SpawnTransform);
		MagicProjectile->SetOwner(this);
		break;
	}

}

 

Problems

  • 코드 중복 : 기본 공격 포함 3개의 스킬이 모두 다른 Proejctile을 던지는 바람에 미친 코드 중복이 발생합니다.
  • 커플링 : 마법 발사체 클래스와 마법 클래스의 강한 커플링

Solutions

  1. 컴포넌트 패턴 : Player의 "마법" 공격 모드의 마법 발사체만을 관리하는 "컴포넌트" 구현
  2. 다형성 : 마법 발사체들 상위에 공통의 상위 클래스를 하나 선언하여, C++가 제공하는 다형성의 이점 활용
  3. 캡슐화 : 공통의 상위 클래스를 통해 하위 클래스들의 세부 기능들을 숨길 수 있습니다. 

 

문제 해결

1. Projectile_Magic.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"

#include "Projectile_Magic.generated.h"

/******************************************************************************************************************

	[Remark]	:	Magic Weapon < - > Projectile_Magic 간 충돌 과정에서 발생하는 상호작용
	
	시간 :
		22-12-01(목) [03:34]
	목적 :
		Magic Projectile의 충돌을 통해 Magic Weapon이 Damage를 전달
	설명 :
		1. FMagicProjectileBeginOverlap 커스텀 Delegate 선언
		2. Magic Weapon은 BindUFunction을 통해 바인딩을 수행
		3. Magic Projectile의 충돌 컴포넌트의 충돌 발생 시 IsBound() + Execute()를 통해 Magic Weapon의 데미지 전달을 구현

********************************************************************************************************************/

DECLARE_DELEGATE_OneParam(FMagicProjectileBeginOverlap, AActor*);

UCLASS()
class DARKSOUL_API AProjectile_Magic : public AActor
{
	GENERATED_BODY()
	
public:	
	AProjectile_Magic();

protected:
	virtual void BeginPlay() override;

//	******************************************************************************************
	//	Method
//	******************************************************************************************

protected:
	UFUNCTION()
		virtual void OnCollision();
	UFUNCTION()
		virtual void OffCollision();

protected:
	UFUNCTION()
		virtual void StartLaunched();
	UFUNCTION()
		virtual void EndLaunched(class AActor* OtherActor);

protected:
	UFUNCTION()
		virtual void OnCapsuleBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

public:
	FMagicProjectileBeginOverlap OnMagicProjectileBeginOverlap;


// *******************************************************************************************
	// Data Member
// *******************************************************************************************

protected:

	UPROPERTY(EditDefaultsOnly, Category = "Components")
		class USceneComponent* Scene;

	UPROPERTY(EditDefaultsOnly, Category = "Components")
		class UNiagaraComponent* ProjectileEffect;

	UPROPERTY(EditDefaultsOnly, Category = "Components")
		class UNiagaraComponent* MuzzleEffect;

	UPROPERTY(EditDefaultsOnly, Category = "Components")
		class UNiagaraComponent* HitEffect;

protected:

	UPROPERTY(VisibleAnywhere, Category = "Effects")
		FTimerHandle TimerHandler;
	UPROPERTY(VisibleAnywhere, Category = "Effects")
		float WaitTime = 0.15f;

};

 

Details

  1. "마법" 공격 모드에서 던질 마법 발사체의 가장 상위 클래스 선언
  2. Custom Delegate(FMagicProjectileBeginOverlap) 선언, "충돌" 정보를 "Magic" 클래스에게 전달하기 위함.
  3. 그밖에 하위 클래스들에게 공통적으로 필요한 데이터 멤버들

 

Projectile Spawner 컴포넌트

1. C_ProjectileSpawnerComponent.h

UPROPERTY(EditDefaultsOnly, Category = "Proejectile")
	TArray<TSubclassOf<class AProjectile_Magic>> ProjectileClass;

UPROPERTY(VisibleAnywhere, Category = "Projectile")
	class AProjectile_Magic* Projectile;

 

2. C_ProjectileSpawnerComponent::SpawnProjectile()

void UC_ProjectileSpawnerComponent::SpawnProjectile(int32 InNum, const FName& InName)
{

	AActor* OwnerWeapon = GetOwner();
	CheckNull(OwnerWeapon);

	APlayerCharacter* Player = Cast<APlayerCharacter>(OwnerWeapon->GetOwner());
	CheckNull(Player);

	// TODO	:	Spawn Location 설정
	FVector SpawnLocation = Player->GetMesh()->GetSocketLocation(InName);
	FRotator SpawnRotation = Player->GetActorRotation();
	FTransform SpawnTransform = FTransform(SpawnRotation, SpawnLocation);

	// TODO	:	Spawn Actor의 클래스 설정 여부
	CheckNull(ProjectileClass.IsValidIndex(InNum));
	Projectile = GetWorld()->SpawnActor<AProjectile_Magic>(ProjectileClass[InNum], SpawnTransform);
	Projectile->SetOwner(this->GetOwner());

}

 

Details

  1. 마법 발사체 클래스 목록 관리
  2. 정수 인자를 받아서 스폰할 마법 발사체 종류를 결정 및 마침내 스폰합니다.

 

결과 코드

1. Magic.h

// ...

private:
	UPROPERTY(EditDefaultsOnly, Category = "Components")
		class UC_ProjectileSpawnerComponent* ProjectileSpawner;

//...

 

Details

  • Projectile Spawner 컴포넌트를 데이터 멤버로 선언합니다.

 

2. Magic::SpawnMagicBall()

/*********************************************************************************************************
	
[Remark]: Switch 문을 통해 EMagicProjectileType 별 Spawn할 Magic_Projectile 결정하는 코드 수정

목적:
	Component 패턴 적용
설명:
	1. Projectile Spawner 컴포넌트 클래스 생성 및 구현
	2. 현재 Projectile Type만 인자로 넘겨, Spawn할 Magic Projectile을 Projectile Spawner 컴포넌트가 결정합니다.

*********************************************************************************************************/
void AMagic::SpawnMagicBall(const FName& InSocketName)
{
	
	CheckNull(ProjectileSpawner);
	ProjectileSpawner->SpawnProjectile((int32)MagicProjectileType, InSocketName);

}

 

Details

  • 단순히 몇 가지 데이터들을 인자로 넘겨주어, Projectile Spawner 컴포넌트에게 마법 발사체의 스폰을 맡깁니다.

 

 

 

 

'개인프로젝트' 카테고리의 다른 글

[Unreal_C++_DarkSoul]#9_기능 구현, Status Effect 기능  (0) 2022.12.18
[Unreal_C++_DarkSoul]#8_문제 해결, Send Damage 방식 수정  (0) 2022.12.18
[Unreal_C++_DarkSoul]#6_기능 구현, Targeting 기능  (0) 2022.12.10
[Unreal_C++_DarkSoul]#5_기능 구현, Target Point, Enemy Spawn 위치  (0) 2022.12.10
[Unreal_C++_DarkSoul]#4_문제 해결, Data Table 로드 함수  (0) 2022.11.27
  1.  
  2. [Unreal_C++_DarkSoul]#7_Magic Projectile
'개인프로젝트' 카테고리의 다른 글
  • [Unreal_C++_DarkSoul]#9_기능 구현, Status Effect 기능
  • [Unreal_C++_DarkSoul]#8_문제 해결, Send Damage 방식 수정
  • [Unreal_C++_DarkSoul]#6_기능 구현, Targeting 기능
  • [Unreal_C++_DarkSoul]#5_기능 구현, Target Point, Enemy Spawn 위치
Hardii2
Hardii2
Hardii2
개발 블로그
Hardii2
전체
오늘
어제
  • 분류 전체보기
    • 알고리즘
    • 웹 개발
      • Node.js
      • React
    • 게임개발
      • DirectX12
      • 관련 지식
      • Unreal C++
      • Unreal 블루프린트
    • 언어
      • Effective C++
      • Basic C++
      • 디자인 패턴
      • 자료구조
      • 기술 질문
    • 문제 풀이
      • BOJ 문제 풀이
      • Programmers 문제 풀이
      • geeksForgeeks 문제 풀이
    • 수학
      • 확률과 통계
      • 게임수학
    • 개인프로젝트
    • 그룹프로젝트
      • PM
      • Dev
    • Github

블로그 메뉴

  • 홈
  • 글쓰기

공지사항

인기 글

태그

  • C++
  • BFS
  • BOJ
  • 그래프
  • Effective C++
  • dfs
  • 정렬
  • 디자인 패턴
  • DP
  • programmers
  • 트리
  • set
  • unreal
  • Unreal Blueprint
  • 알고리즘
  • 기술 질문
  • 최단 경로
  • 개발
  • stl
  • 우선순위 큐

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
Hardii2
[Unreal_C++_DarkSoul]#7_문제 해결, Magic Projectile
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.