공부/Unreal

24.07.22

월러비 2024. 7. 26. 13:09
  • 나중에 ‘커스텀 에디터’나 ‘데이터 에셋’같은것은 찾아서 습득해라
    • 데이터 에셋 : 데이터들을 다루기 쉽게 모아놓고 사용하는 에셋을 직접 만들 수 있다.
    • DoActionData 같은거다.
    • 이날 데이터 에셋이 뭔지 보여주셨다.
  • VTable 오류로 언리얼 에디터가 터진다면 무시하고 다시 열면 된다.

검 및 플레이어 관련 예제

콤보 공격

  • 메뉴얼에 기본값 쓰라고 적어놔도 잘 안보고, 실행하다가 터지는 경우가 상당히 많다.
    • 귀찮더라도 기본값은 꼭 넣어놓고 작업해라
  • 무브먼트 컴포넌트 헤더 파일 - ‘움직임’ 함수와 ‘정지’ 함수 선언 - 무브먼트 컴포넌트 cpp 파일 - ‘움직임’ 함수 정의 - ‘움직임 가능 확인’ 변수 true - ‘정지’ 함수 정의 - ‘움직임 가능 확인’ 변수 false - 헤더 파일 - 애님 몽타주 배열 생성 - ‘공격 중 확인’ 변수 선언 - ‘콤보 수’ 변수 선언 - ‘콤보 허용 구간’ 변수 선언 - ‘콤보 존재함’ 변수 선언 - cpp 파일 - 몽타주 배열에 공격 동작 하나씩 ‘에셋 가져오기’ - ‘공격’ 액션 맵 및 액션 함수 연결 - ‘공격’ 함수 정의 - ‘콤보 허용 구간’이라면 콤보 관련 코드를 실행하고, 아니라면 일반 공격을 실행한다. - ‘무기 장착 확인’ false 체크 - ‘공격 중 확인’ true 체크 - ‘공격 중 확인’ 변수 true - ‘무브먼트 컴포넌트’의 ‘정지’ 함수 호출 - ‘애님 몽타주 실행’ 함수를 ‘콤보 수’의 순번으로 호출한다. - ‘콤보 허용 구간’ 정의 - ‘콤보 허용 구간’ false - ‘콤보 존재’ true - ‘공격 중 확인’ 변수 true
//무브먼트 컴포넌트 header
public:
	void Move();
	void Stop();
	
//무브먼트 컴포넌트 cpp
void UCMovementComponent::Move()
{
	bCanMove = true;
}

void UCMovementComponent::Stop()
{
	bCanMove = false;
}

//header
UPROPERTY(EditAnywhere, Category = "Sword")
		class UAnimMontage* ComboMontages[3]; //검 공격 애니메이션 3개
		
private:
	bool bAttacking; //공격 중인지 확인

private:
	int32 index; //현재 콤보 수
	bool bEnable; //콤보 구간 허용
	bool bExist; //콤보가 존재하는지 확인

//cpp
//장착 애니메이션 기본값 넣기
CHelpers::GetAsset<UAnimMontage>(&EquipMontage, "AnimMontage'/Game/Characters/Montages/DrawSwordMontage.DrawSwordMontage'");
CHelpers::GetAsset<UAnimMontage>(&ComboMontages[0], "AnimMontage'/Game/Characters/Montages/Sword_Attack_1_Montage.Sword_Attack_1_Montage'");
CHelpers::GetAsset<UAnimMontage>(&ComboMontages[1], "AnimMontage'/Game/Characters/Montages/Sword_Attack_2_Montage.Sword_Attack_2_Montage'");
CHelpers::GetAsset<UAnimMontage>(&ComboMontages[2], "AnimMontage'/Game/Characters/Montages/Sword_Attack_3_Montage.Sword_Attack_3_Montage'");

PlayerInputComponent->BindAction("Action", EInputEvent::IE_Pressed, this, &ACPlayer::OnAction);

if (bEnable)
	{
		bEnable = false;
		bExist = true;

		return;
	}

	CheckFalse(bEquipped);
	CheckTrue(bAttacking);

	bAttacking = true;

	Movement->Stop();
	PlayAnimMontage(ComboMontages[index]);

공격 노티파이(이벤트) 설정

  • 상속을 처음쓰는 파일들은 부모에 어떤 함수가 있는지 ‘반드시’ 확인해야한다.
    • 뭐가 있는지 알아야 쓰지..
  • 검 헤더 파일 - ‘충돌 활성화’ 및 ‘충돌 비활성화’ 함수 선언 - 검 cpp 파일 - ‘충돌 활성화’ 함수 정의 - 캡슐 컴포넌트의 ‘충돌 활성화’함수를 충돌 설정을 넣어 호출한다. - 헤더 파일 - ‘콤보 허용 시작’ 및 ‘콤보 허용 종료’ 함수 선언 - ‘충돌 시작’ 및 ‘충돌 종료’ 함수 선언 - ‘공격 시작’ 및 ‘공격 종료’ 함수 선언 - cpp 파일 - ‘콤보 허용 시작 종료’ 함수 정의 - 콤보 허용을 시작할때 ‘콤보 허용 확인’ 변수 true, 콤보 허용을 종료시 ‘콤보 허용 확인’ 변수 false - ‘충돌 시작 종료’ 함수 정의 - 충돌을 시작하면 ‘무기 : 검’의 ‘충돌 활성’ 함수를 호출하고, 종료시 ‘무기 : 검’의 ‘충돌 비활성’ 함수를 호출한다. - ‘공격 시작 종료’ 함수 정의 - ‘콤보 존재’ 확인 - 콤보가 있다면 다시 없애고 콤보를 실행한다. - 콤보수 증가 - 콤보 수의 ‘몽타주 실행’ 함수 호출 - ‘공격 종료’ 시에는 ‘공격 중 확인’ 변수를 끄고, 콤보 수 초기화 하고, ‘무브먼트 컴포넌트’를 다시 움직일 수 있게 한다.
//검 header
public:
	void OnCollision();
	void OffCollision();
	
//검 cpp
void ACSword::OnCollision()
{
	//충돌체 활성화시키기 
	Capsule->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
}

void ACSword::OffCollision()
{
	//충돌체 비 활성화시키기 
	Capsule->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}

//header
public:
	void Begin_Enable();
	void End_Enable();

	void Begin_Collision();
	void End_Collision();

	void Begin_Action();
	void End_Action();
	
//cpp
void ACPlayer::Begin_Enable()
{
	bEnable = true;
}

void ACPlayer::End_Enable()
{
	bEnable = false;
}

void ACPlayer::Begin_Collision()
{
	Sword->OnCollision();
}

void ACPlayer::End_Collision()
{
	Sword->OffCollision();
}

void ACPlayer::Begin_Action()
{
	CheckFalse(bExist);

	bExist = false;

	index++;

	PlayAnimMontage(ComboMontages[index]);
}

void ACPlayer::End_Action()
{
	bAttacking = false;
	index = 0;

	Movement->Move();
}
  • 콤보와 충돌은 ‘NotifyState’ 파일로 생성하고, Combo 와 Collision에 맞는 이름들로 바꾼다.
    • NotifyState는 Begin과 End를 ‘반드시’ 정의해줘야한다.
    • 메쉬 체크 - 메쉬의 오너 체크 - 오너를 ‘플레이어’로 형변환하고 저장 - 플레이어 체크 - 플레이어에서 이벤트로 실행할 함수 호출 ⇒ 이때, Begin과 End를 각각 정의하고 함수 연결도 각각 정의해서 연결해야한다.
  • 공격 시작과 종료는 ‘Notify’ 파일로 생성하고, 이름과 ‘Notify’를 정의한다.
    • Notify는 NotifyState와 달리 Notify 하나만 정의하면 된다.
    • 메쉬 체크 - 메쉬의 오너 체크 - 오너를 플레이어로 형변환 - 플레이어 체크 - 이벤트로 실행할 함수 연결
  • 함수의 정의가 끝나면 이벤트를 넣을 몽타주에 노티파이들을 추가한다.
    • 애니메이션 몽타주 파일 우측 상단에 ‘캐릭터 아이콘’ 오른쪽의 ‘세로 점 3개’ 버튼을 누르면 다른 몽타주로 쉽게 넘어갈 수 있다.

브레이크 포인트 설명

  • F5 클릭 - 중단점 걸 코드에 F9 클릭 - 에디터 실행 ⇒ 중단점 건 자리에서 실행이 정지한다.
  • 이떄, F5를 누르는 순간 새로운 에디터가 열려서 그곳에서 중단점이 걸리게된다.
    • 다른 에디터에서 수정하고 저장하게 되면 에디터가 2개 뜬것으로 인식되어서 저장이 안되게 된다.

Enemy 생성

타격감 1 : 히트시 색 변경

  • 헤더 파일 - ‘기본 색’을 흰 색으로 변수를 선언한다. - ‘색 변경’ 함수 선언 : 상수의 LinearColor 자료형 주소를 매개변수로 받는다. - cpp 파일 - 필요한 컴포넌트 생성 : ‘무브먼트 컴포넌트’, 메쉬, ‘애님 인스턴스’, 회전 속도 설정 - 이동 설정을 ‘걷기’를 호출한다. - 메쉬의 메테리얼 갯수만큼 반복한다. - ‘메테리얼 인터페이스’ 자료형 변수를 선언하고, 메쉬의 메테리얼들을 순서대로 가져온다. - 메쉬의 ‘메테리얼 설정’ 함수를 ‘순서, 메테리얼 인스턴스 다이나믹 생성 함수에서 ‘메테리얼 인터페이스’ 변수와 현재 클래스를 넣어 호출한다.’ - ‘색 변경’ 함수 정의 - 메쉬의 메테리얼 갯수만큼 반복한다. - ‘메테리얼 인스턴스 다이나믹’ 자료형의 포인터 변수를 선언하고 ‘생성해서 설정한 메테리얼들을’ 현변환해서 저장한다. - 저장한 메테리얼이 비버있지 않다면 메테리얼 파일의 설정한 노드의 이름을 넣고 지정된 함수를 설정해서 색을 변경한다.
//header
private:
	UPROPERTY(EditAnywhere, Category = "Color")
		FLinearColor OriginColor = FLinearColor::White; //다시 돌아올 원래 색 저장

private:
	void Change_Color(const FLinearColor& InColor);
		
//cpp
//메테리얼 갯수만큼 반복
for (int i = 0; i < GetMesh()->GetMaterials().Num(); i++)
{
	//GetMaterials : 매테리얼의 배열이 반환된다.
	UMaterialInterface* material = GetMesh()->GetMaterials()[i];

	GetMesh()->SetMaterial(i, UMaterialInstanceDynamic::Create(material, this));
}

for (UMaterialInterface* material : GetMesh()->GetMaterials())
{
	UMaterialInstanceDynamic* instance = Cast<UMaterialInstanceDynamic>(material);

	if (!!instance)
	{
		instance->SetVectorParameterValue("Color", InColor);
	}
}

충돌 설정

  • TakeDamage 함수가 Actor에 있는 이유 : 돌이나 상자도 배치하고 데미지 받아 부숴지게 할 수 있게 하기 위해서이다.
    • 즉, APawn에 있는 TakeDamage는 virtual로 선언되어 있으니 재정의가 가능하다.
    • 일단 override만 작성해서 재정의하고 나중에 다른곳에서 재정의가 필요하게 된다면 virtual을 쓰면 된다.
  • 상속을 받은 TakeDamage는 호출된다면, 부모의 데미지 관련 처리가 다 끝나고 관련 데미지들을 받아서 호출된다.
    • 즉, 서버 데미지 처리, 부모 데미지 처리 가 다 끝나서 온 결과가 돌아오는 것이다.
    • 이때, 호출되는 부모의 데미지 함수 호출은 변수에 저장이 가능하다. (모든 상속 함수들도 같은듯)
    • Print 해보면 float을 반환하는 함수이니 ‘데미지 값’ 하나만 호출된다.
  • 검 cpp 파일 - ‘오버랩 시작’ 함수 정의 - ‘데미지 이벤트’ 자료형 변수 선언 - 매개변수로 받은 충돌 액터의 ‘데미지 가져오기’ 함수 호출 : 데미지 값, 데미지 이벤트, 검 든 주체의 컨트롤러를 가져온다. , 공격 객체는 검 - 적 헤더 파일 - ‘데미지 가져오기’ 함수 재정의 - ‘데미지 가져오기’ 함수 테스트
//검 cpp
FDamageEvent e;

//TakeDamage : 언리얼 데미지 처리 함수
OtherActor->TakeDamage(20, e, GetOwner()->GetInstigatorController(), this);

//header
float TakeDamage(float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override;

HP 관리 컴포넌트 생성

  • HP바 같은 UI도 이곳에서 생성시킨다.
  • TimerHandle : 식별자 라고 생각해라
    • 타이머 시작, 중지, 다시 시작 등을 구분하는 ID다.
  • 헤더 파일 - ‘최대 생명력’ 변수 선언 후 초기화 - ‘데미지’ 함수를 ‘데미지 양’을 받아서 선언한다. - ‘현재 생명력’ 변수 선언 - ‘사망 확인’ 함수를 선언 후 초기화한다. - cpp 파일 - 게임 시작 후 ‘현재 생명력’은 ‘최대 생명력’으로 놓는다. - ‘데미지’ 함수 정의 - ‘현재 생명력’에 ‘데미지값’에 -1을 곱하여 더해준다. - ‘현재 생명력’을 ‘값 제한’ 함수를 호출해서 저장한다. - 적 헤더 파일 - ‘생명력 컴포넌트’ 자료형 변수 선언 - ‘색 회복’ 함수 선언 - ‘타이머 핸들’ 자료형의 ‘색 변경 핸들’을 변수 선언한다. - 적 cpp 파일 - ‘생명력 컴포넌트’를 컴포넌트 생성 함수로 호출 - ‘데미지 받음’ 정의 - ‘현재 생명력’에서 ‘데미지’ 함수 호출 - ‘색 변경’ 함수 호출 : 색은 Red로 - ‘타이머 델리게이트’ 자료형 변수를 선언한다. - ‘타이머 델리게이트’와 ‘색 변경 함수’를 연결한다. - 월드의 ‘타이머 매니저 가져오기 의 ‘타이머 설정’ 함수 호출 : 타이머 핸들, 타이머 델리게이트, 최초 딜레이 시간 , 반복 여부 - ‘색 회복’ 함수 정의 - ‘색 변경’ 함수를 호출 : ‘원래 색’을 넣어 호출한다.
//header
private:
	UPROPERTY(EditAnywhere, Category = "Health")
		float MaxHealth = 100;

public:
	FORCEINLINE bool IsDead() { return Health <= 0.0f; }
	
public:
	void Damage(float InAmount);

private:
	float Health;
	
//cpp
//HP 기본값 설정
Health = MaxHealth;

//데미지 값에 음수 처리
Health += (InAmount * -1.0f); 

//값 제한
Health = FMath::Clamp(Health, 0.0f, MaxHealth);

//적 header
private:
	void Change_Color(const FLinearColor& InColor);

private:
	UFUNCTION()
		void RestoreColor();
		
private:
	FTimerHandle ChangeColor_TimerHandle;
	
//적 cpp
//Apply Damage
	{
		HealthPoint->Damage(Damage);
	}

	//Change Color
	{
		Change_Color(FLinearColor::Red);

		//델리게이트 자료형이 나오면 파라미터 몇개인지부터 확인한다.
		FTimerDelegate timerDelegate; //사실 이거 선언 안하고 '람다식'을 이용할 수 있다.
		timerDelegate.BindUFunction(this, "RestoreColor");

		GetWorld()->GetTimerManager().SetTimer(ChangeColor_TimerHandle, timerDelegate, 0.2f, false);
	}

	return Damage;
	
	Change_Color(OriginColor);

'공부 > Unreal' 카테고리의 다른 글

24.07.24  (0) 2024.07.29
24.07.23  (0) 2024.07.27
24.07.19  (0) 2024.07.26
24.07.18  (1) 2024.07.23
24.07.17  (1) 2024.07.23