CreateSP, CreateRaw, CreateUObject에 대한 내용

https://forums.unrealengine.com/t/delegate-createsp-createraw-createuobject-when-to-use-them/23822/4

 

 

  • 전역 C++ 함수 : BindStatic API를 사용해 등록
  • 전역 C++ 람다 함수 : BindLambda API를 사용해 등록
  • C++클래스 멤버 함수 : BindRaw  API를 사용해 등록
  • 공유포인터 클래스의 멤버 함수 (쓰레드 미지원) : BindSP API를 사용해 등록 
  • 공유포인터 클래스의 멤버 함수 (쓰레드 지원) : BindThreadSafeSP API를 사용해 등록
  • UFUNCTION 멤버 함수 : BindUFunction API를 사용해 등록
  • 언리얼 오브젝트의 멤버함수 : BindUObject API를 사용해 등록

'언리얼 엔진 > 정보' 카테고리의 다른 글

Mixamo의 루트모션 애니메이션 사용  (0) 2022.10.12
커스텀 CharacterMovement  (0) 2022.10.12
ApplyDamage, TakeDamage  (0) 2022.10.11
Actor, Pawn, Character  (0) 2022.10.04
[UE5] 포스트 프로세싱  (0) 2022.10.01
float UGameplayStatics::ApplyDamage(
    AActor* DamagedActor, // 피해를 입은 대상
    float BaseDamage, // 피해량
    AController* EventInstigator, // 피해를 입힌 대상
    AActor* DamageCauser, // 피해를 준 액터 (수류탄, 칼 등등)
    TSubclassOf<UDamageType> DamageTypeClass) // 피해의 종류 (범위공격, 헤드샷 등)

 

ApplyDamage 호출 시, DamagedActor의 TakeDamage가 호출이 된다.

 

 

ApplyDamage 호출 시 OnTakeAnyDamage에 등록된 메소드가 호출된다.

 

TakeDamage 함수는 오버라이딩이 가능하므로 여러가지 커스텀 대미지 이벤트를 사용할 수 있을것이다.

 

Any, Point, Radial 3가지 타입이 있는데 3브랜치가 아닌 Point, Radial 브랜치를 수행해서 데미지를 계산한 다음 Any를 처리하는 방식이다.

예를 들어 Point 타입인 경우 헤드샷이면 데미지의 배율을 2배로 늘리고 Any를 수행한다거나 Radial 타입인 경우 범위 거리에 따른 데미지 편차를 계산 후 Any를 수행하는 방식이다.

 

 

http://egloos.zum.com/ldw9981/v/4163717

https://3dmpengines.tistory.com/1579

https://www.unrealengine.com/ko/blog/damage-in-ue4

 

'언리얼 엔진 > 정보' 카테고리의 다른 글

커스텀 CharacterMovement  (0) 2022.10.12
FTimerDelegate에 관련된 내용  (0) 2022.10.11
Actor, Pawn, Character  (0) 2022.10.04
[UE5] 포스트 프로세싱  (0) 2022.10.01
[UE5] 루멘  (0) 2022.09.29

[개요]

  • 이동 가능한 탱크 생성
  • WASD 이동과 마우스 클릭 액션
  • 적 포탑 생성
  • 발사체 생성
  • 체력, 대미지, 파괴
  • 이펙트 추가
  • 승/패 UI 출력

 

[프로젝트 설정]

  • 프로젝트를 다운로드 받아서 맞는 버전으로 포팅

 

[126. Using the Mouse Cursor]

 

if (PlayerControllerRef)
{
    FHitResult HitResult;
    // Line tracing과 충돌이 검출될 채널, 추적 복잡성 여부, 충돌체
    PlayerControllerRef->GetHitResultUnderCursor(ECollisionChannel::ECC_Visibility, false, HitResult);
    DrawDebugSphere(GetWorld(), HitResult.ImpactPoint, 25.f, 12, FColor::Red, false);
}

 

마우스 커서가 위치한곳에 Line tracing을 해서 최초로 충돌하는 오브젝트의 정보를 레퍼런스로 반환받는다.

2번째 인자인 bTraceComplex는 메시의 단순 콜리전, 복합 콜리전과 관계가 있는 것으로 보인다.

아주 정교한 위치가 필요한 경우가 아니라면 false를 사용해 주는 것이 연산량이 적을 것이다.

 

[127. Rotating the Turret]

 

FVector를 FRotator로 변환시킬 수 있다.

 

FVector ToTarget = LookAtTarget - TurretMesh->GetComponentLocation();
FRotator LookAtRotation = FRotator(0.f, ToTarget.Rotation().Yaw, 0.f);
TurretMesh->SetWorldRotation(LookAtRotation);

 

회전보간을 통해서 한번에 스냅되는게 아닌 조금 더 자연스러운 포탑 회전을 만들 수 있다.

void ABasePawn::RotateTurret(FVector LookAtTarget)
{
    FVector ToTarget = LookAtTarget - TurretMesh->GetComponentLocation();
    FRotator LookAtRotation = FRotator(0.f, ToTarget.Rotation().Yaw, 0.f);
        TurretMesh->SetWorldRotation(
            FMath::RInterpTo(TurretMesh->GetComponentRotation(),
            LookAtRotation, 
            UGameplayStatics::GetWorldDeltaSeconds(this),
        	25.f)
    );
}

 

[130. Timer]

 

타이머 핸들에 함수를 바인딩 시켜서 일정 시간 뒤에 실행시키거나 일정 시간마다 반복 실행 시킬 수 있다.

 

[132. Spawning The Projectile]

 

SpawnActor는 새로운 액터를 월드에 생성시켜준다. 템플릿에는 어떤 클래스를 만들어 줄 것인지를 지정하고 첫 번째 인자인 UClass에는 블루프린트도 들어갈 수 있기때문에 의미가 다르다.

 

예를 들어 C++ 클래스를 블루프린트로 파생시켜서 만들고 코드상에서는 스태틱 메시를 따로 지정하지 않는다면 C++ 클래스를 SpawnActor 하게될 시 보이지 않는 액터가 생성이 될 것이다. 하지만 스태틱 메시를 포함한 다른 값들이 지정된 블루프린트를 SpawnActor 한다면 정상적으로 잘 보일것이다.

 

[133. Projectile Movement Component]

 

발사체를 이동시키는 방법은 크게 3가지가 있다.

  • 매 틱마다 Transform을 변화시키는 것 (Set Location & Rotation)
  • 물리를 적용시켜서 운동량을 변화시키는 것 (Add Impulse)
  • 발사체 전용 Movement Component 사용

 

언리얼에는 발사체를 위한 Movement 컴포넌트가 따로 존재한다.

발사체에 컴포넌트를 붙여주고 속도 설정만 해주면 된다.

 

[134. Hit Events]

 

어떤 Primitive Component와 충돌 이벤트(Hit, OnOverlap)가 발생했을 때 바인딩 시킨 메소드들을 호출할 수 있다.

 

ProjectileMesh->OnComponentHit.AddDynamic(this, &AProjectile::OnHit);


void AProjectile::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
    // do something
}

 

매개변수 형식이 미리 지정되어 있으므로 반드시 위의 매개변수 형식을 지켜야 한다.

이벤트 발생시 자동으로 호출해준다.

 

만약 코드 작성 직후 작동하지 않는다면 에디터를 끄고 IDE에서 빌드를 다시 해주고 실행하면 된다.

 

[135. Health Component]

 

체력이나 그외 공통적인 부분은 액터 컴포넌트로 따로 만들어서 관리하는 것이 재사용성에도 좋고 코드가 길어지지 않아서 가독성에도 좋다.

 

[136. Applying Damage]

 

투사체를 생성할 때 단순히 생성만으로 끝나면 누구의 투사체가 데미지를 주었는지를 알 수가 없다.

SpawnActor의 반환값은 AActor이므로 소유자를 설정해서 처리해야한다.

 

auto Projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileClass, Transform);
Projectile->SetOwner(this);

 

ApplyDamage의 매개변수중에 데미지를 입힌 주체의 Controller를 요구하는데 이때 Owner가 필요하다.

 

ApplyDamage & TakeDamage 추가 정보 : https://erikanes.tistory.com/352

 

[137. The Game Mode Class]

 

게임 모드는 게임의 규칙이나 승리 조건을 처리할 수 있다.

GameMode는 GameModeBase를 상속하고 멀티플레이에 관한 기능 등 좀더 다양한 기능이 있다.

 

[138. Handling Pawn Death]

 

죽음에 대한 처리는 게임모드에 의해 처리되도록 한다.

 

Tank->DisableInput(TankPlayerController); // 입력 비활성화
TankPlayerController->bShowMouseCursor = false; // 마우스 커서 표시 비활성화

 

[139. Custom Player Controller]

 

임의의 플레이어 컨트롤러를 만들어서 게임모드에 오버라이딩 시킬 수 있다.

 

[140. Starting The Game]

 

TimerManager의 SetTimer 매개변수중에 FTimerDelegate 라는 것이 있다.

https://erikanes.tistory.com/353

위의 글을 참고하면 된다.

 

[143. Displaying Countdown Time]

 

UI 구성요소를 변수화 시켜서 그래프에 노출시킬 수 있다. 

 

 

타이머가 0초 미만으로 내려가면 더 이상 필요없는 위젯이므로 제거해준다.

 

[144. Winning And Losing]

 

TArray<AActor*> Towers;
UGameplayStatics::GetAllActorsOfClass(this, ATower::StaticClass(), Towers);

 

월드에 존재하는 특정 액터들을 TArray에 반환받을 수 있다.

태그, 클래스+태그, 인터페이스까지 총 4가지의 함수가 있다.

 

[145. Game Over HUD]

 

위젯은 AddToViewport를 통해서 화면에 출력될 수 있다.

 

 

위젯의 구성요소들은 변수로 변환이 되고 외부에서 접근이 가능하다.

 

[147. Smoke Trail]

 

UParticleSystem은 파티클 애셋, UParticleSystemComponent는 UParticleSystem을 관리하는 컴포넌트이다. 둘의 차이가 있다.

UParticleSystem은 UGamePlaystatics::SpawnEmitterAtLocation을 통해 월드에 스폰되거나 UParticleSystemComponent를 통해 제어될 수 있다.

 

[150. Camera Shake]

 

언리얼은 카메라 흔들림에 대한 클래스가 이미 만들어져있다.

여기서는 마티네 카메라 셰이크에서 파생된 블루프린트 클래스를 사용한다.

 

 

블루프린트에서 속성을 지정해주고 C++ 코드에서 해당 카메라 셰이크를 재생시 설정된 값으로 흔들린다.

카메라 셰이크를 C++ 코드로 만들어줄수도 있지만 단순히 값만 지정하는거라서 블루프린트로 만들고 관리하는것이 편해보인다.

 

if (HitCameraShakeClass)
{
    APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
    PlayerController->ClientPlayCameraShake(HitCameraShakeClass);
}

 

마티네 카메라 셰이크에는 카메라를 어떻게 흔들지에 대한 정보가 담길뿐이고 실제로 카메라를 흔드는것은 플레이어 컨트롤러이다. 

 

// 특정 플레이어의 카메라 흔들기
APlayerController::ClientPlayCameraShake

// 범위 내 거리에 따른 카메라 흔들기
UGameplayStatics::PlayWorldCameraShake

 

[151. Polish And Wrap-Up]

 

몇 가지 문제를 수정하고 마무리 한다.

 

1. 카메라 무빙

SpringArm의 CameraLag, CameraRotationLag을 활성화 시켜주면 포탑의 회전이 보간되어서 자연스러워진 것처럼 약간의 딜레이가 생기기 때문에 카메라의 움직임이 부드러워진다. 값을 낮출수록 딜레이가 더 길어진다.

 

 

2. 플레이어가 죽은뒤에도 계속 공격하는 타워

 

void ATank::HandleDestruction()
{
    Super::HandleDestruction();
    SetActorHiddenInGame(true);
    SetActorTickEnabled(false);
}

 

단순히 액터를 숨긴다고 실제로 월드에서 비활성화 되는것은 아니다. 눈에 안보일뿐이지 타워는 계속 플레이어를 인지한다.

추가로 콜리전까지 꺼주면 콜리전 이벤트에서 검출되지 않을것이다.

 

다만 이 실습에서는 콜리전 이벤트를 통한 공격이 이루어지는것이 아닌 타겟(플레이어)를 처음부터 설정해놓고 매 틱마다 추적하는 방식이기때문에 플레이어에게 생존여부를 알수있는 bool값을 추가해서 죽은 상태라면 타워가 플레이어를 추적하거나 발사하지 않는 방식을 사용해야한다.

 

OnComponentBeginOverlap같은 이벤트라면 콜리전을 없애는것 만으로도 해결이 될 것이라고 생각된다. 

'언리얼 엔진 > UE5 C++' 카테고리의 다른 글

[UE5 C++] Simple Shooter -完-  (0) 2022.10.12
[UE5 C++] Crypt Raider  (0) 2022.09.29
[UE5 C++] Obstacle Assalult  (0) 2022.09.28
[UE5 C++] Warehouse Wreckage  (0) 2022.09.28

공부하며 적는 내용이기 때문에 정확하지 않을 수 있다.

 

 

언리얼은 Actor -> Pawn -> Character의 상속 구조를 가지고 있다.

Actor부터 월드에 배치될 수 있고 Pawn부터 제어가 가능해진다.

Actor를 상속받고 확장해서 제어할 수 있게 된것이 Pawn이라고 보면 될 것이다.

 

폰의 이동은 MovementComponent, 제어는 Controller에 의해 이뤄진다.

컨트롤러가 폰에 빙의해서 제어하는 방식이다.

플레이어가 폰을 제어할 때 PlayerController를 사용하고 AI가 폰을 제어할 때는 AIController를 사용하면 된다.

Controller는 따로 설정하지 않으면 게임모드에 의해 기본 컨트롤러(PlayerController)가 설정된다.

MovementComponent는 따로 추가해주지 않으면 컴포넌트가 붙지 않는다.

Pawn에서 MovementComponent를 반환받을 수 있는 GetMovementComponent가 구현되어 있지만 해당 컴포넌트를 폰에서 관리하고 있지 않기 때문에 AddMovementInput등의 기능이 작동하지 않는다.

 

만약 MovementComponent를 붙여준다면 MovementComponent::UpdatedComponent = RootComponent 를 반드시 추가해서 RootComponent에 접근할 수 있게 해야한다.

 

 

Character는 Pawn을 확장한것인데 조금 더 복잡한 행동이나 애니메이션을 처리하는것이 추가되었다.

CharacterMovementComponent가 기본적으로 포함되어있다.

 

// Character 코드 일부

TObjectPtr<UCharacterMovementComponent> CharacterMovement;

Character::Character()
{
    CharacterMovement = CreateDefaultSubobject<UCharacterMovementComponent>(ACharacter::CharacterMovementComponentName);
    if (CharacterMovement)
    {
        CharacterMovement->UpdatedComponent = CapsuleComponent;
    }
}

 

Pawn에는 없는 내용이 Character에는 기본적으로 포함이 되어 있는 것을 확인할 수 있다.

위에서 언급한대로 CharacterMovement가 CapsuleComponent(=RootComponent)를 관리하도록 설정한다.

 

걷기 최대속도, 가속도, 점프 등 이동에 관련된 다양한 내용과 애니메이션에 관한 내용들이 추가로 구현이 되어있다.

추가로 액터와 폰에는 기본적으로 메시가 존재하지 않지만 캐릭터는 스켈레탈 메시가 붙어있다.

'언리얼 엔진 > 정보' 카테고리의 다른 글

FTimerDelegate에 관련된 내용  (0) 2022.10.11
ApplyDamage, TakeDamage  (0) 2022.10.11
[UE5] 포스트 프로세싱  (0) 2022.10.01
[UE5] 루멘  (0) 2022.09.29
언리얼 베테랑의 100가지 팁과 트릭 정리  (0) 2022.09.29

루멘과 포스트 프로세스 볼륨에 대한 내용만 짧막하게 정리. 흥미로운 내용이 많기때문에 관련 내용은 계속 추가할 예정

 

포스트 프로세스 볼륨은 프로젝트 설정의 값들을 오버라이드 할 수 있다.

 

인간의 시각 적응(Exposure)이 적용되어 있기 때문에 어두운 곳에서 밝은곳을 바라보면 점차 밝아지게 된다.

Exposure의 값을 변경하면 오버라이딩 되기 때문에 특정 구역 또는 전체 구역의 시각 적응을 없애거나 보완할 수 있다.

 

https://docs.unrealengine.com/5.0/ko/post-process-effects-in-unreal-engine/

 

'언리얼 엔진 > 정보' 카테고리의 다른 글

ApplyDamage, TakeDamage  (0) 2022.10.11
Actor, Pawn, Character  (0) 2022.10.04
[UE5] 루멘  (0) 2022.09.29
언리얼 베테랑의 100가지 팁과 트릭 정리  (0) 2022.09.29
개발에 필요할 것 같은 정보들  (0) 2022.09.14

+ Recent posts