본문 바로가기

게임프로그래밍

(141)
[언리얼 강의] 71. 모션워핑을 통해 적이 공격할 때 플레이어 바라보게 하기 목차Motion Warping이벤트 설정하기공격 시작 중 플레이어에게 맞아도 바로 공격하는 문제 수정하기1. Motion Warping 현재 에너미는 캐릭터의 위치와는 상관없이 전방 방향으로만 공격한다. 이부분을 고쳐 에너미가 플레이어를 향하게 해볼 것이고 루트 모션 애니메이션과 모션 워핑을 활용해 이를 구현할 것이다.  모션 워핑을 사용하기 위해서는 플러그인을 사용해야 한다. 플러그인을 적용하려면 에디터를 껐다 켜야하니 저장을 잘 해놓자. 이제 에너미의 블루프린트 클래스로 들어간다.  모션 워핑 컴포넌트를 추가해주자. 그다음 공격 몽타주로 들어가자.   노티파이 스테이트에서 모션 워핑을 추가해준다.  노티파이의 길이를 조절할 수 있는데 저 길이 동안 모션 워핑을 진행하게 된다. 모션 워핑을 작동하는 법..
[언리얼 실습] 70. 방향성 히트 리액션 수정하기 목차타격자 기준으로 히트 방향 설정하기버그 수정하기1. 타격자 기준으로 히트 방향 설정하기 현재 방향성 히트를 구현하고 있는데 피격 지점을 기준으로 방향을 설정한다. 이것의 문제점은 회전 공격 같이 측면을 때리는 경우 정면에서 공격을 해도 측면에 피격이 일어나 일반적으로 생각하는 반응이 나오지 않는다. 그렇기에 이를 피격지점이 아닌 타격자와 피격자의 위치를 기준으로 계산하게 바꿔보자 현재 방향성 타격은 다음과 같이 구하고 있다.void ABaseCharacter::DirectionalHitReact(const FVector& ImpactPoint){ // Forward = U const FVector Forward = GetActorForwardVector(); // ImpactPoint의 Z축을 에너미..
[언리얼 실습] 69. 플레이어 히트 구현하기 목차GetHit 함수 오버라이드 하기히트 애니메이션 재생 중 공격 방지 및 공격 중 맞으면 굳는 현상 수정죽은 적의 검에 맞는 현상 수정 및 순찰타이머 정지시키기1. GetHit 함수 오버라이드 하기 함수를 오버라이드 해서 사용할 것이다. 포스팅은 안했지만 강의를 진행하면서 베이스 캐릭터라는 상위 클래스를 만들었는데 이곳에서 구현한 함수를 상속받아 사용할 것이다. UCLASS()class PRACTICE_API ABaseCharacter : public ACharacter, public IHitInterface{protected:virtual void GetHit_Implementation(const FVector& ImpactPoint) override;//생략}void ABaseCharacter::G..
[언리얼 실습] 68. 플레이어 캐릭터 히트 구현 목차GetHit 함수 구현하기캐릭터 매시 콜리전 설정 바꾸기에너미 무기 콜리전 활성화 하기에너미가 자기 자신 때리는 것 수정하기1. GetHit 함수 구현하기 플레이어도 타격을 받으면 GetHit 함수를 호출하게 할 것이다. GetHit 함수는 인터페이스에 있으니 이것을 오버라이드 하자. UCLASS()class PRACTICE_API AKnight : public ABaseCharacter{ GENERATED_BODY()public: AKnight(); virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; virtual void GetHit_Implementation(const FVecto..
[언리얼 실습] 67. 에너미 Engage 상태로 만들기 목차에너미 상태 바꾸기1. 에너미 상태 바꾸기 현재 에너미 상태 열거형에 Engaged가 있지만 실제 Engaged 상태로 들어가지는 않는다. 이 때문에 적이 공격을 한번 하면 다시는 하지 않는다. 이 부분을 고치자. void AEnemy::Attack(){ EnemyState = EEnemyState::EES_Engaged; Super::Attack(); PlayAttackMontage();} 공격 함수에서 상태를 바꿔주자. bool AEnemy::CanAttack(){ bool bCanAttack = IsInSideAttackRadius() && !IsAttacking() && !IsEngaged() && !IsDead(); return bCanAttack;} 공격이 가능한지 알아보는 함수에서..
[언리얼] 66. 에너미 공격 반복하기 목차에너미 상태 추가하기에너미 공격 반복하기1. 에너미 상태 추가하기 UENUM(BlueprintType)enum class EEnemyState : uint8{ EES_Patrolling UMETA(DisplayName = "Patrolling"), EES_Chasing UMETA(DisplayName = "Chasing"), EES_Attacking UMETA(DisplayName = "Attacking")}; 현재 에너미의 상태이다. 순찰, 추격, 공격으로 나누어져 있는데 공격 쪽을 좀 더 분화할 것이다. 공격을 하고있는 순간과 쿨다운 중이라 공격을 하지는 않지만 공격사거리 안에 있기 때문에 추격도 하지 않는 상태로 나눌 필요가 있다. UENUM(BlueprintType)enum class EEne..
[언리얼 실습] 65. 에너미 어택 몽타주 재생하기 목차몽타주 재생하기1. 몽타주 재생하기 에너미의 공격을 구현하기 위해서 몽타주를 재생해보려고 한다. 에너미의 헤더파일로 들어가자. virtual void Attack() override;virtual void PlayAttackMontage() override; Attack()함수와 이 Attack() 함수에서 실행할 PlayAttackMontage() 함수를 선언한다. 이제 이 두 함수를 정의하자. Attack() 함수의 경우 추후 기능을 만들겠지만 지금은 단순히 공격 몽타주를 재생하는 역할만 한다.void AEnemy::Attack(){ Super::Attack(); PlayAttackMontage();}  PlayAttackMontage() 함수는 플레이어 캐릭터에 있는 내용 그대로 복사해 붙여 놓..
[언리얼 실습] 64. 에너미에게 무기 쥐어주기 목차에너미에게 무기 쥐어주기충돌 없애기에너미 사망시 무기 없애기1. 에너미에게 무기 쥐어주기 캐릭터에 무기를 쥐어주는 것도 방패를 쥘때랑 비슷하다. 소켓을 만들고 그것에 무기를 달아주면 된다. 다만 한가지 다른 점은 무기는 방패와 달리 실제 상호작용을 할 것이고 그렇기 때문에 단순한 스태틱매시가 아닌 블루프린트 클래스를 부착해주어야 한다. 에너미 헤더파일로 들어가자 UPROPERTY(EditAnywhere)TSubclassOf WeaponClass; 헤더 파일에 선언을 한뒤 이걸 어디서 생성하고 어떻게 부착시켜야 할까? 방패와 달리 무기는 월드에 생성을 한 뒤 부착을 시도할 것이고 월드에 생성을 하기 위해서는 게임이 시작되어야 할 것이다. BeginPlay()에서 생성하고 부착해보자. UWorld* Wo..
[언리얼 실습] 63. 자식 에너미 클래스 만들기 목차자식 에너미 클래스 만들기에너미에게 방패 쥐어주기1. 자식 에너미 클래스 만들기 에너미는 현재 팔라딘 하나만 있지만 추후 더 다양한 에너미가 나올 수 있고 각각의 매시나 애니메이션등은 다를 것이기 때문에 자식 클래스로 만들어 관리하면 편할 것이다.  자식 블루프린트 클래스를 만들자. 이제 자식 클래스도 만들었으니 무기랑 방패를 주어 에너미를 꾸며보자.2. 에너미에게 무기 쥐어주기 무기 종류는 특정 에너미에게 특정 무기를 주어야 할 것이다. 즉 클래스마다 구분이 필요하다. 자식 클래스로 들어가서 매시를 추가해주자.  그리고 매시를 추가하면 된다. 이제 이 방패를 에너미가 들고 있게 해야한다. 그렇게 하기 위해서는 플레이어 캐릭터에게 했던 것처럼 소켓을 추가하고 그곳에 부착해야 할 것이다. 스켈레톤으로 ..
[언리얼 실습] 62. 에너미가 타격을 받으면 플레이어를 추격하기 목차에너미가 피해를 입으면 반응하기1. 에너미가 피해를 입으면 반응하기 에너미가 피해를 입었을때 플레이어가 추격 사거리 안에 있으면 플레이어를 쫒아가게 할 것이다. 에너미의 상태 열거형이 존재하고 이에 따른 반응도 구현하였기 때문에 이를 구현하는 것은 매우 간단한 작업이 될 것이다. float AEnemy::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser){ if (Attributes && HealthBarWidget) { Attributes->ReceiveDamage(DamageAmount); HealthBarWidget->SetHealthPe..