Choose your operating system:
Windows
macOS
Linux
캐릭터 구성을 마쳤으니, 이제 발사체 무기를 구현하여 발사하면 단순한 수류탄같은 발사체가 화면 중앙에서 발사되어 월드에 충돌할 때까지 날아가도록 만들겠습니다. 이번 단계에서는 프로젝타일에 쓸 입력을 추가하고 새 코드 클래스를 만들도록 하겠습니다.
발사 액션 매핑 추가
-
편집 메뉴에서, 프로젝트 세팅 에 클릭합니다.
-
프로젝트 세팅 탭 왼편의 엔진 제목줄 아래 입력 을 클릭합니다.
-
바인딩 아래, 액션 매핑 옆의 더하기 부호를 클릭합니다.
-
액션 매핑 왼쪽의 화살표를 클릭합니다.
-
뜨는 글상자에 Fire 라 입력하고, 글상자 왼쪽의 화살표를 클릭하여 액션 바인딩 옵션을 펼칩니다.
-
드롭다운 메뉴의 마우스 드롭다운 목록에서 왼쪽 마우스 버튼 을 선택합니다.
-
입력 세팅이 이제 다음과 같을 것입니다:
-
프로젝트 세팅 메뉴를 닫습니다.
프로젝타일 클래스 추가
-
파일 메뉴에서 새 C++ 클래스... 를 선택하고 새 부모 클래스를 선택합니다.
-
부모 클래스 선택 메뉴가 열립니다. 스크롤해 내려가, Acotr 를 부모 클래스로 선택하고 다음 을 클릭합니다.
-
새 클래스 이름을 "FPSProjectile" 이라 하고 생성 을 클릭합니다.
USphere Component 추가
-
Solution Explorer 에서
FPSProjectile.h
를 열고FPSProjectile
클래스 헤더를 찾습니다. -
FPSProjectile
인터페이스에USphereComponent
로의 레퍼런스를 추가합니다.// 구체 콜리전 컴포넌트 UPROPERTY(VisibleDefaultsOnly, Category = Projectile) USphereComponent* CollisionComponent;
-
FPSProjectile.h
는 이제 다음과 같을 것입니다:// 프로젝트 세팅의 설명 페이지에 저작권 문구를 채우세요. #pragma once #include "GameFramework/Actor.h" #include "FPSProjectile.generated.h" UCLASS() class FPSPROJECT_API AFPSProjectile : public AActor { GENERATED_BODY() public: // 이 액터 프로퍼티의 기본값을 설정합니다. AFPSProjectile(); protected: // 게임 시작 또는 스폰시 호출됩니다. virtual void BeginPlay() override; public: // 매 프레임 호출됩니다. virtual void Tick( float DeltaSeconds ) override; // 구체 콜리전 컴포넌트입니다. UPROPERTY(VisibleDefaultsOnly, Category = Projectile) USphereComponent* CollisionComponent; };
-
Solution Explorer 에서
FPSProjectile
클래스 CPP 파일을 찾아FPSProjectile.cpp
를 엽니다. -
FPSProjectile.cpp
의AFPSProjectile
생성자에 다음 코드를 추가합니다:// 구체를 단순 콜리전 표현으로 사용합니다. CollisionComponent = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent")); // 구체의 콜리전 반경을 설정합니다. CollisionComponent->InitSphereRadius(15.0f); // 루트 컴포넌트를 콜리전 컴포넌트로 설정합니다. RootComponent = CollisionComponent;
시뮬레이션으로 구동시켜줄 것이므로
CollisionComponent
를RootComponent
로 만듭니다. -
FPSProjectile.cpp
는 이제 다음과 같을 것입니다:// 프로젝트 세팅의 설명 페이지에 저작권 문구를 채우세요. #include "FPSProject.h" #include "FPSProjectile.h" // Sets default values AFPSProjectile::AFPSProjectile() { // 이 액터가 매 프레임 Tick() 을 호출하도록 설정합니다. 필요치 않은 경우 끄면 퍼포먼스가 향상됩니다. PrimaryActorTick.bCanEverTick = true; // 구체를 단순 콜리전 표현으로 사용합니다. CollisionComponent = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent")); // 구체의 콜리전 반경을 설정합니다. CollisionComponent->InitSphereRadius(15.0f); // 루트 컴포넌트를 콜리전 컴포넌트로 설정합니다. RootComponent = CollisionComponent; } // 게임 시작시 또는 스폰시 호출됩니다. void AFPSProjectile::BeginPlay() { Super::BeginPlay(); } // 매 프레임 호출됩니다. void AFPSProjectile::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); }
프로젝타일 무브먼트 컴포넌트 추가
-
Solution Explorer 에서
FPSProjectile
클래스 헤더 파일을 찾아FPSProjectile.h
를 엽니다. -
FPSProjectile.h
에 다음 코드를 추가합니다:// 프로젝타일 무브먼트 컴포넌트 UPROPERTY(VisibleAnywhere, Category = Movement) UProjectileMovementComponent* ProjectileMovementComponent;
-
FPSProjectile.h
는 이제 다음과 같을 것입니다:// 프로젝트 세팅의 설명 페이지에 저작권 문구를 채우세요. #pragma once #include "GameFramework/Actor.h" #include "FPSProjectile.generated.h" UCLASS() class FPSPROJECT_API AFPSProjectile : public AActor { GENERATED_BODY() public: // 이 액터 프로퍼티의 기본값을 설정합니다. AFPSProjectile(); protected: // 게임 시작 또는 스폰시 호출됩니다. virtual void BeginPlay() override; public: // 매 프레임 호출됩니다. virtual void Tick( float DeltaSeconds ) override; // 구체 콜리전 컴포넌트입니다. UPROPERTY(VisibleDefaultsOnly, Category = Projectile) USphereComponent* CollisionComponent; // 프로젝타일 무브먼트 컴포넌트 UPROPERTY(VisibleAnywhere, Category = Movement) UProjectileMovementComponent* ProjectileMovementComponent; };
-
Solution Explorer 에서
FPSProjectile
CPP 파일을 찾아FPSProjectile.cpp
파일을 엽니다. -
FPSProjectile.cpp
의FPSProjectile
생성자에 다음 코드 줄을 추가합니다:// ProjectileMovementComponent 를 사용하여 이 발사체의 운동을 관장합니다. ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovementComponent")); ProjectileMovementComponent->SetUpdatedComponent(CollisionComponent); ProjectileMovementComponent->InitialSpeed = 3000.0f; ProjectileMovementComponent->MaxSpeed = 3000.0f; ProjectileMovementComponent->bRotationFollowsVelocity = true; ProjectileMovementComponent->bShouldBounce = true; ProjectileMovementComponent->Bounciness = 0.3f;
-
FPSProjectile.cpp
는 이제 다음과 같을 것입니다:// 프로젝트 세팅의 설명 페이지에 저작권 문구를 채우세요. #include "FPSProject.h" #include "FPSProjectile.h" // Sets default values AFPSProjectile::AFPSProjectile() { // 이 액터가 매 프레임 Tick() 을 호출하도록 설정합니다. 필요치 않은 경우 끄면 퍼포먼스가 향상됩니다. PrimaryActorTick.bCanEverTick = true; // 구체를 단순 콜리전 표현으로 사용합니다. CollisionComponent = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent")); // 구체의 콜리전 반경을 설정합니다. CollisionComponent->InitSphereRadius(15.0f); // 루트 컴포넌트를 콜리전 컴포넌트로 설정합니다. RootComponent = CollisionComponent; // 이 컴포넌트를 사용하여 이 프로젝타일의 무브먼트를 구동시킵니다. ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovementComponent")); ProjectileMovementComponent->SetUpdatedComponent(CollisionComponent); ProjectileMovementComponent->InitialSpeed = 3000.0f; ProjectileMovementComponent->MaxSpeed = 3000.0f; ProjectileMovementComponent->bRotationFollowsVelocity = true; ProjectileMovementComponent->bShouldBounce = true; ProjectileMovementComponent->Bounciness = 0.3f; } // 게임 시작시 또는 스폰시 호출됩니다. void AFPSProjectile::BeginPlay() { Super::BeginPlay(); } // 매 프레임 호출됩니다. void AFPSProjectile::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); }
발사체 초기 속도 설정
-
Solution Explorer 에서
FPSProjectile
클래스 헤더 파일을 찾아FPSProjectile.h
를 엽니다. -
FPSProjectile.h
에 다음 함수 선언을 추가합니다:// 발사체의 속도를 발사 방향으로 초기화시킵니다. void FireInDirection(const FVector& ShootDirection);
이 함수가 발사체의 발사를 담당합니다.
-
FPSProjectile.h
는 이제 다음과 같은 모습일 것입니다:// 프로젝트 세팅의 설명 페이지에 저작권 문구를 채우세요. #pragma once #include "GameFramework/Actor.h" #include "FPSProjectile.generated.h" UCLASS() class FPSPROJECT_API AFPSProjectile : public AActor { GENERATED_BODY() public: // 이 액터 프로퍼티의 기본값을 설정합니다. AFPSProjectile(); protected: // 게임 시작 또는 스폰시 호출됩니다. virtual void BeginPlay() override; public: // 매 프레임 호출됩니다. virtual void Tick( float DeltaSeconds ) override; // 구체 콜리전 컴포넌트입니다. UPROPERTY(VisibleDefaultsOnly, Category = Projectile) USphereComponent* CollisionComponent; // 프로젝타일 무브먼트 컴포넌트입니다. UPROPERTY(VisibleAnywhere, Category = Movement) UProjectileMovementComponent* ProjectileMovementComponent; // 프로젝타일의 속도를 발사 방향으로 초기화시키는 함수입니다. void FireInDirection(const FVector& ShootDirection); };
-
Solution Explorer 에서
FPSProjectile
CPP 파일을 찾아FPSProjectile.cpp
를 엽니다. -
FPSProjectile.cpp
에 다음 함수 정의부를 추가합니다:// 프로젝타일의 속도를 발사 방향으로 초기화시키는 함수입니다. void AFPSProjectile::FireInDirection(const FVector& ShootDirection) { ProjectileMovementComponent->Velocity = ShootDirection * ProjectileMovementComponent->InitialSpeed; }
참고로 발사체의 속력은
ProjectileMovementComponent
에 의해 정의되므로 발사 방향만 제공해 주면 됩니다. -
FPSProjectile.cpp
는 이제 다음과 같을 것입니다:// 프로젝트 세팅의 설명 페이지에 저작권 문구를 채우세요. #include "FPSProject.h" #include "FPSProjectile.h" // Sets default values AFPSProjectile::AFPSProjectile() { // 이 액터가 매 프레임 Tick() 을 호출하도록 설정합니다. 필요치 않은 경우 끄면 퍼포먼스가 향상됩니다. PrimaryActorTick.bCanEverTick = true; // 구체를 단순 콜리전 표현으로 사용합니다. CollisionComponent = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent")); // 구체의 콜리전 반경을 설정합니다. CollisionComponent->InitSphereRadius(15.0f); // 루트 컴포넌트를 콜리전 컴포넌트로 설정합니다. RootComponent = CollisionComponent; // 이 컴포넌트를 사용하여 프로젝타일의 무브먼트를 구동시킵니다. ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovementComponent")); ProjectileMovementComponent->SetUpdatedComponent(CollisionComponent); ProjectileMovementComponent->InitialSpeed = 3000.0f; ProjectileMovementComponent->MaxSpeed = 3000.0f; ProjectileMovementComponent->bRotationFollowsVelocity = true; ProjectileMovementComponent->bShouldBounce = true; ProjectileMovementComponent->Bounciness = 0.3f; } // 게임 시작시 또는 스폰시 호출됩니다. void AFPSProjectile::BeginPlay() { Super::BeginPlay(); } // 매 프레임 호출됩니다. void AFPSProjectile::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); } // 프로젝타일의 속도를 발사 방향으로 초기화시키는 함수입니다. void AFPSProjectile::FireInDirection(const FVector& ShootDirection) { ProjectileMovementComponent->Velocity = ShootDirection * ProjectileMovementComponent->InitialSpeed; }
발사 입력 액션 바인딩
-
Solution Explorer 에서
FPSCharacter
클래스 헤더 파일을 찾아FPSCharacter.h
를 엽니다. -
FPSCharacter.h
에 다음 함수 선언을 추가합니다:// 발사 처리 UFUNCTION() void Fire();
-
FPSCharacter.h
는 이 제 다음과 비슷할 것입니다:// 프로젝트 세팅의 설명 페이지에 저작권 문구를 채우세요. #pragma once #include "GameFramework/Character.h" #include "FPSCharacter.generated.h" UCLASS() class FPSPROJECT_API AFPSCharacter : public ACharacter { GENERATED_BODY() public: // 이 캐릭터 프로퍼티에 대한 기본값을 설정합니다. AFPSCharacter(); protected: // 게임 시작 또는 스폰시 호출됩니다. virtual void BeginPlay() override; public: // 매 프레임 호출됩니다. virtual void Tick( float DeltaSeconds ) override; // 입력에 함수성을 바인딩하기 위해 호출됩니다. virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; // 전후 이동을 처리합니다. UFUNCTION() void MoveForward(float Value); // 좌우 이동을 처리합니다. UFUNCTION() void MoveRight(float Value); // 키를 누르면 점프 플래그를 설정합니다. UFUNCTION() void StartJump(); // 키를 떼면 점프 플래그를 지웁니다. UFUNCTION() void StopJump(); // 프로젝타일 발사를 처리하는 함수입니다. UFUNCTION() void Fire(); // FPS 카메라입니다. UPROPERTY(VisibleAnywhere) UCameraComponent* FPSCameraComponent; // 폰 메시: 일인칭 시점 (자신에게만 보이는 팔) UPROPERTY(VisibleDefaultsOnly, Category = Mesh) USkeletalMeshComponent* FPSMesh; };
-
Solution Explorer 에서
FPSCharacter
CPP 파일을 찾고FPSCharacter.cpp
를 엽니다. -
FPSCharacter.cpp
에서,OnFire
함수 바인딩을 위해SetupPlayerInputComponent
에 다음 코드를 추가합니다:PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AFPSCharacter::Fire);
-
이제,
FPSCharacter.cpp
에 다음 함수 정의부를 추가합니다:void AFPSCharacter::Fire() { }
-
FPSCharacter.cpp
는 이제 다음과 같아 보일 것입니다:// 프로젝트 세팅의 설명 페이지에 저작권 문구를 채우세요. #include "FPSProject.h" #include "FPSCharacter.h" // 기본값을 설정합니다. AFPSCharacter::AFPSCharacter() { // 이 캐릭터가 TIck() 을 매 프레임 호출하도록 설정합니다. 필요치 않은 경우 끄면 퍼포먼스가 향상됩니다. PrimaryActorTick.bCanEverTick = true; // 일인칭 카메라 컴포넌트를 생성합니다. FPSCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera")); // 카메라 컴포넌트를 캡슐 컴포넌트에 붙입니다. FPSCameraComponent->SetupAttachment(GetCapsuleComponent()); // 카메라 위치를 잡습니다. FPSCameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 50.0f + BaseEyeHeight)); // 폰의 제어를 가능케 합니다. FPSCameraComponent->bUsePawnControlRotation = true; // 일인칭 메시 컴포넌트를 생성합니다. FPSMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("FirstPersonMesh")); // 소유 플레이어에게만 이 메시가 보입니다. FPSMesh->SetOnlyOwnerSee(true); // FPS 메시를 FPS 카메라에 붙입니다. FPSMesh->SetupAttachment(FPSCameraComponent); // 일부 환경 그림자를 꺼서 하나의 메시로 보이는 것을 방지합니다. FPSMesh->bCastDynamicShadow = false; FPSMesh->CastShadow = false; // 자신을 제외한 모든 이는 일반 바디 메시를 볼 수 있습니다. GetMesh()->SetOwnerNoSee(true); } // 게임 시작시 또는 스폰시 호출됩니다. void AFPSCharacter::BeginPlay() { Super::BeginPlay(); if (GEngine) { // 5 초간 디버그 메시지를 표시합니다. (첫 인수인) -1 "Key" 값은 이 메시지를 업데이트 또는 새로고칠 필요가 없음을 나타냅니다. GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("We are using FPSCharacter.")); } } // 매 프레임 호출됩니다. void AFPSCharacter::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); } // 입력에 함수성을 바인딩하기 위해 호출됩니다. void AFPSCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); // 게임플레이 키 바인딩을 구성합니다. PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward); PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight); // 게임플레이 마우스 바인딩을 구성합니다. PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::AddControllerYawInput); PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::AddControllerPitchInput); // 점프 동작 바인딩을 구성합니다. PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::StartJump); PlayerInputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::StopJump); PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AFPSCharacter::Fire); } void AFPSCharacter::MoveForward(float Value) { // 어디가 전방인지 인지 알아내어, 플레이어가 그 방향으로 이동하고자 한다고 기록합니다. FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X); AddMovementInput(Direction, Value); } void AFPSCharacter::MoveRight(float Value) { // 어디가 오른쪽인지 인지 알아내어, 플레이어가 그 방향으로 이동하고자 한다고 기록합니다. FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y); AddMovementInput(Direction, Value); } void AFPSCharacter::StartJump() { bPressedJump = true; } void AFPSCharacter::StopJump() { bPressedJump = false; } void AFPSCharacter::Fire() { }
발사체의 스폰 위치 정의
-
FPSProjectile
액터 스폰시OnFire
함수 구현에 있어 두 가지 고려할 점이 있습니다. 이를테면:
-
발사체 스폰 위치
-
프로젝타일 클래스 (
FPSCharacter
와 그 파생 블루프린트가 스폰할 발사체를 알도록 하기 위함입니다).
카메라 스페이스 오프셋 벡터를 사용하여 프로젝타일의 스폰 위치를 결정하게 됩니다. 이 파라미터를 편집가능하게 만들어야 BP_FPSCharacter 블루프린트에서 설정 및 조정할 수 있습니다. 궁극적으로 이 데이터를 토대로 발사체에 대한 초기 위치를 계산할 수 있을 것입니다.
-
Solution Explorer 에서
FPSCharacter
클래스 헤더 파일을 찾고FPSCharacter.h
를 엽니다. -
FPSCharacter.h
에 다음 코드를 추가합니다:// 카메라 위치에서의 총구 오프셋 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay) FVector MuzzleOffset;
EditAnywhere 지정자를 통해 총구 오프셋 값을 블루프린트 에디터의 디폴트 모드나 캐릭터의 아무 인스턴스에 대한 디테일 탭에서 변경할 수 있습니다. BlueprintReadWrite 지정자를 통해서는 블루프린트 안에서 총구 오프셋의 값을 구하고 설정할 수 있습니다.
-
FPSCharacter.h
에 다음 코드를 추가합니다:// 스폰시킬 프로젝타일 클래스 UPROPERTY(EditDefaultsOnly, Category = Projectile) TSubclassOf<class AFPSProjectile> ProjectileClass;
EditDefaultsOnly 지정자는 프로젝타일 클래스를 블루프린트의 각 인스턴스 상에서가 아니라 블루프린트의 디폴트로만 설정할 수 있다는 뜻입니다.
-
FPSCharacter.h
의 모습은 다음과 같을 것입니다:// 프로젝트 세팅의 설명 페이지에 저작권 문구를 채우세요. #pragma once #include "GameFramework/Character.h" #include "FPSCharacter.generated.h" UCLASS() class FPSPROJECT_API AFPSCharacter : public ACharacter { GENERATED_BODY() public: // 이 캐릭터 프로퍼티에 대한 기본값을 설정합니다. AFPSCharacter(); protected: // 게임 시작 또는 스폰시 호출됩니다. virtual void BeginPlay() override; public: // 매 프레임 호출됩니다. virtual void Tick( float DeltaSeconds ) override; // 입력에 함수성을 바인딩하기 위해 호출됩니다. virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; // 전후 이동을 처리합니다. UFUNCTION() void MoveForward(float Value); // 좌우 이동을 처리합니다. UFUNCTION() void MoveRight(float Value); // 키를 누르면 점프 플래그를 설정합니다. UFUNCTION() void StartJump(); // 키를 떼면 점프 플래그를 지웁니다. UFUNCTION() void StopJump(); // 프로젝타일 발사를 처리하는 함수입니다. UFUNCTION() void Fire(); // FPS 카메라입니다. UPROPERTY(VisibleAnywhere) UCameraComponent* FPSCameraComponent; // 폰 메시: 일인칭 시점 (자신에게만 보이는 팔) UPROPERTY(VisibleDefaultsOnly, Category = Mesh) USkeletalMeshComponent* FPSMesh; // 카메라 위치에서의 총구 오프셋 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay) FVector MuzzleOffset; // 스폰시킬 프로젝타일 클래스 UPROPERTY(EditDefaultsOnly, Category = Projectile) TSubclassOf<class AFPSProjectile> ProjectileClass; };
코드 컴파일 및 검사
이제 새로 구현된 발사체 코드를 컴파일하고 검사할 차례입니다.
-
Visual Studio 에서 모든 헤더 및 구현 파일을 저장합니다.
-
Solution Explorer 에서 FPSProject 를 찾습니다.
-
FPSProject 에 우클릭한 다음 Build 를 선택하여 프로젝트를 컴파일합니다.
이 단계의 목적은 다음 단계로 넘어가기 전 빌드 오류를 잡아내기 위함입니다.