UE4 C++ 입력과 콜리전


Tags :


입력

CPlayer를 움직이자

프로젝트세팅 설정

프로젝트세팅 > 입력 : 이전 프로젝트에서 쓰던 입력값들 임포트해오기
21

플레이어 적용

CPlayer클래스에 적용된 입력값에 바인딩 될 함수 생성하기

  • 헤더
      public:
          // 인풋에 바인딩 된 함수 콜
      	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
            
      private:
          // 축 맵핑 이벤트 함수
          void OnMoveForward(float InAxisValue);
          void OnMoveRight(float InAxisValue);
          void OnHorizontalLook(float InAxisValue);
          void OnVerticalLook(float InAxisValue);
    
          // 액션 맵핑 이벤트 함수
      	void OnRun();
          void OffRun();
    
  • 소스
      void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
      {
          Super::SetupPlayerInputComponent(PlayerInputComponent);
    
          // 축 맵핑
          PlayerInputComponent->BindAxis("MoveForward", this, &ACPlayer::OnMoveForward);
          PlayerInputComponent->BindAxis("MoveRight", this, &ACPlayer::OnMoveRight);
          PlayerInputComponent->BindAxis("HorizontalLook", this, &ACPlayer::OnHorizontalLook);
          PlayerInputComponent->BindAxis("VerticalLook", this, &ACPlayer::OnVerticalLook);
    
          // 액션 맵핑
          PlayerInputComponent->BindAction("Run", EInputEvent::IE_Pressed, this, &ACPlayer::OnRun);
          PlayerInputComponent->BindAction("Run", EInputEvent::IE_Released, this, &ACPlayer::OffRun);
      }
    
      void ACPlayer::OnMoveForward(float InAxisValue)
      {
      	FRotator rotator = FRotator(0, GetControlRotation().Yaw, 0);
          FVector direction = FQuat(rotator).GetForwardVector().GetSafeNormal2D();
          AddMovementInput(direction, InAxisValue);
    
          // 디버그
          //CLog::Print("OnMoveForward", -1, 10, FColor::Magenta);
      }
    
      void ACPlayer::OnMoveRight(float InAxisValue)
      {
          FRotator rotator = FRotator(0, GetControlRotation().Yaw, 0);
          FVector direction = FQuat(rotator).GetRightVector().GetSafeNormal2D();
          AddMovementInput(direction, InAxisValue);
    
          // 디버그
          //CLog::Print("OnMoveRight", -1, 10, FColor::Magenta);
      }
    
      void ACPlayer::OnHorizontalLook(float InAxisValue)
      {
          AddControllerYawInput(InAxisValue);
      }
    
      void ACPlayer::OnVerticalLook(float InAxisValue)
      {
          AddControllerPitchInput(InAxisValue);
      }
    
      void ACPlayer::OnRun()
      {
          GetCharacterMovement()->MaxWalkSpeed = 600;
      }
    
      void ACPlayer::OffRun()
      {
          GetCharacterMovement()->MaxWalkSpeed = 400;
      }
    

델리게이트(Delegate) 함수 : 활성화 시 바인딩 된 함수를 실행 - 실행을 위임하다(Delegate)

GetSafeNormal2D() : 2D처럼 Z값이 0인 법선벡터 반환, 벡터의 길이가 너무 짧을 때 0을 반환하며 안전한 변환을 확보해준다

22
22_1


콜리전

충돌판정 시 상호작용을 확인해보자
C++클래스 디렉토리에 새폴더 \03_Collision 생성 후 각각 Overlap확인 할 충돌박스 액터 생성하기

액터 충돌

새 C++ 액터 클래스 C01_ActorOverlap 생성

  • 헤더
    #pragma once
    #include "CoreMinimal.h"
    #include "GameFramework/Actor.h"
    #include "C01_ActorOverlap.generated.h"
    
      UCLASS()
      class U03_BASIC_API AC01_ActorOverlap : public AActor
      {
          GENERATED_BODY()
    
      public:	
          AC01_ActorOverlap();
    
      protected:
          virtual void BeginPlay() override;
    
      private:
          UPROPERTY(VisibleAnywhere)
              class USceneComponent* Root;
    
          UPROPERTY(VisibleAnywhere)
              class UBoxComponent* Box;
    
          UPROPERTY(VisibleAnywhere)
              class UTextRenderComponent* Text;
      private:
          UFUNCTION()
              void BeginOverlap(AActor* OverlappedActor, AActor* OtherActor);
          UFUNCTION()
              void EndOverlap(AActor* OverlappedActor, AActor* OtherActor);
      };
    
  • 소스
    #include "03_Collision/C01_ActorOverlap.h"
    #include "Global.h"
    #include "Components/BoxComponent.h"
    #include "Components/TextRenderComponent.h"
    
      AC01_ActorOverlap::AC01_ActorOverlap()
      {
          // 컴포넌트들 생성
          CHelpers::CreateComponent<USceneComponent>(this, &Root, "Root");
          CHelpers::CreateComponent<UBoxComponent>(this, &Box, "Box", Root);
          CHelpers::CreateComponent<UTextRenderComponent>(this, &Text, "Text", Root);
    
          // 텍스트
          Text->SetRelativeLocation(FVector(0, 0, 100));
          Text->SetRelativeRotation(FRotator(0, 180, 0));
          Text->SetWorldScale3D(FVector(2));	// FVector()에 하나만 넣어주면 3축 동일 값 적용
          Text->TextRenderColor = FColor::Red;
          Text->HorizontalAlignment = EHorizTextAligment::EHTA_Center;	// 텍스트 정렬Enum
          Text->Text = FText::FromString(GetName().Replace(L"Default__", L""));	
          // GetName했을 때 나올 String에 Default__ 지우기
    
          // 박스
          Box->bHiddenInGame = false;
          Box->SetRelativeScale3D(FVector(3));
      }
    
      void AC01_ActorOverlap::BeginPlay()
      {
          Super::BeginPlay();
    
          // 블프에서 이벤트로 올라온 걸 CPP 함수에 바인딩
          OnActorBeginOverlap.AddDynamic(this, &AC01_ActorOverlap::BeginOverlap);
          OnActorEndOverlap.AddDynamic(this, &AC01_ActorOverlap::EndOverlap);
      }
    
      void AC01_ActorOverlap::BeginOverlap(AActor* OverlappedActor, AActor* OtherActor)
      {
          FString str = FString::Printf(L"Begin - Overlapped %s, Other : %s",
           *OverlappedActor->GetName(), *OtherActor->GetName());	// *로 받아야 스트링
    
          CLog::Print(str);
      }
    
      void AC01_ActorOverlap::EndOverlap(AActor* OverlappedActor, AActor* OtherActor)
      {
          FString str = FString::Printf(L"End - Overlapped %s, Other : %s",
           *OverlappedActor->GetName(), *OtherActor->GetName());	// *로 받아야 스트링
    
          CLog::Print(str, -1, 10, FColor::Red);
      }
    

    AddDynamic : The location of our AddDynamic is important to note; Adding them to the constructor means that what we are trying to bind to is not ensured to be ready yet and can often lead to crashes. We also do not need these binds whilst in the editor - it is strictly a runtime requirement. Because of this, you should place binds such as Overlaps, Hits and similar such delegate bindings on BeginPlay - which fires once the game has started and this object has been created.

23 24

컴포넌트 충돌

새 C++ 액터 클래스 C02_ComponentOverlap 생성
Root, Box, Text와 생성자는 C01_ActorOverlap과 동일(복붙)

  • 헤더
    #pragma once
    #include "CoreMinimal.h"
    #include "GameFramework/Actor.h"
    #include "C02_ComponentOverlap.generated.h"
    
      UCLASS()
      class U03_BASIC_API AC02_ComponentOverlap : public AActor
      {
          GENERATED_BODY()
        
      public:	
          AC02_ComponentOverlap();
    
      protected:
          virtual void BeginPlay() override;
    
      private:
          UPROPERTY(VisibleAnywhere)
              class USceneComponent* Root;
    
          UPROPERTY(VisibleAnywhere)
              class UBoxComponent* Box;
    
          UPROPERTY(VisibleAnywhere)
              class UTextRenderComponent* Text;
      private:
          UFUNCTION()
              void OnComponentBeginOverlap
              (UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, 
              int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);	// FHitResult : 구조체
          UFUNCTION()
              void OnComponentEndOverlap
              (UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp,
              int32 OtherBodyIndex);
      };
    
  • 소스
      void AC02_ComponentOverlap::BeginPlay()
      {
          Super::BeginPlay();
        
          // 박스로부터 충돌판정 시 함수 바인딩
          Box->OnComponentBeginOverlap.AddDynamic(this, &AC02_ComponentOverlap::OnComponentBeginOverlap);
          Box->OnComponentEndOverlap.AddDynamic(this, &AC02_ComponentOverlap::OnComponentEndOverlap);
      }
    
      void AC02_ComponentOverlap::OnComponentBeginOverlap
      (UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, 
      int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
      {
          FString str;
          str = "----Begin----";
          CLog::Log(str);
          str = FString::Printf(L"OverlappedComp %s", *OverlappedComp->GetName());
          CLog::Log(str);
          str = FString::Printf(L"OtherActor %s", *OtherActor->GetName());
          CLog::Log(str);
          str = FString::Printf(L"OtherComp %s", *OtherComp->GetName());
          CLog::Log(str);
      }
    
      void AC02_ComponentOverlap::OnComponentEndOverlap
      (UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, 
      int32 OtherBodyIndex)
      {
          FString str;
          str = "----End----";
          CLog::Log(str);
          str = FString::Printf(L"OverlappedComp %s", *OverlappedComp->GetName());
          CLog::Log(str);
          str = FString::Printf(L"OtherActor %s", *OtherActor->GetName());
          CLog::Log(str);
          str = FString::Printf(L"OtherComp %s", *OtherComp->GetName());
          CLog::Log(str);
      }
    

Sweep(훑다) = 충돌 : 훑었는지 안훑었는지 충돌여부를 확인한다는 의미로 봐야할 것 같다

25

히트 충돌

새 C++ 액터 클래스 C03_OverlapAndHit 생성
Root, Box, Text와 생성자는 C01_ActorOverlap과 동일(복붙)

  • 헤더
    #pragma once
    #include "CoreMinimal.h"
    #include "GameFramework/Actor.h"
    #include "C03_OverlapAndHit.generated.h"
    
      UCLASS()
      class U03_BASIC_API AC03_OverlapAndHit : public AActor
      {
          GENERATED_BODY()
        
      public:	
          AC03_OverlapAndHit();
    
      protected:
          virtual void BeginPlay() override;
    
      private:
          UPROPERTY(VisibleAnywhere)
              class USceneComponent* Root;
    
          UPROPERTY(VisibleAnywhere)
              class UBoxComponent* Box;
    
          UPROPERTY(VisibleAnywhere)
              class UTextRenderComponent* Text;
    
      private:
          UFUNCTION()
              void OnComponentBeginOverlap
              (UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, 
              int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
          UFUNCTION()
              void OnComponentEndOverlap
              (UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, 
              int32 OtherBodyIndex);
          UFUNCTION()
              void OnComponentHit
              (UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, 
              FVector NormalInpulse, const FHitResult& Hit);
      };
    
  • 소스
      void AC03_OverlapAndHit::BeginPlay()
      {
          Super::BeginPlay();
    	
          Box->OnComponentBeginOverlap.AddDynamic(this, &AC03_OverlapAndHit::OnComponentBeginOverlap);
          Box->OnComponentEndOverlap.AddDynamic(this, &AC03_OverlapAndHit::OnComponentEndOverlap);
    
          // Hit조건 
          // 1) 2개의 Physics가 있을 때 적어도 하나는 Simulation Generates Hit Event = True;
          // 2) 콜리전 프리셋 > PhysicsBody = Block;
          Box->OnComponentHit.AddDynamic(this, &AC03_OverlapAndHit::OnComponentHit);
      }
    
      void AC03_OverlapAndHit::OnComponentBeginOverlap
      (UPrimitiveComponent * OverlappedComp, AActor * OtherActor, UPrimitiveComponent * OtherComp, 
      int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
      {
          FString str;
    
          str = FString::Printf(L"Begin Overlap %s", *OtherComp->GetName());
          CLog::Log(str);
      }
    
      void AC03_OverlapAndHit::OnComponentEndOverlap
      (UPrimitiveComponent * OverlappedComp, AActor * OtherActor, UPrimitiveComponent * OtherComp, 
      int32 OtherBodyIndex)
      {
      	FString str;
    
      	str = FString::Printf(L"End Overlap %s", *OtherComp->GetName());
      	CLog::Log(str);
      }
    
      void AC03_OverlapAndHit::OnComponentHit
      (UPrimitiveComponent * HitComp, AActor * OtherActor, UPrimitiveComponent * OtherComp, 
      FVector NormalInpulse, const FHitResult & Hit)
      {
          FString str;
    
          str = FString::Printf(L"Hit %s", *OtherComp->GetName());
          CLog::Log(str);
      }
    

26

Hit조건 :

  1. 2개의 Physics가 있을 때 적어도 하나는 Simulation Generates Hit Event = True;
  2. 콜리전 프리셋 > PhysicsBody = Block;

27