마우스의 휠을 이용하면 화면의 Zoom In과 Out을 구현했다. 'DeltaTime' (전 프레임과 현재 프레임 사이의 시간 차이)와 'InterpSpeed' (보간 속도)를 사용하여 'TargetArmLength'를 부드럽게 변경했다. 마우스 휠의 변경 값을 'InValue'로 넣고 'Speed'를 곱한 값을 'CurrentValue'에 더하고, 이 값을 'Range.X'와 'Range.Y' 사이의 값으로 제한하여 사용하였다.

 

 

목차

     

     


     

     

     

     
    Plugins
     
      Weapon
     
        Resource
     
          Icon128.png
    weapon_thumbnail_icon.png
     
        Source
     
          Weapon  
          SWeaponCheckBoxes.h .cpp
    SWeaponDetailsView.h .cpp

    SWeaponDoActionData.h .cpp
    SWeaponEquipmentData.h .cpp
    SWeaponHitData.h .cpp

    SWeaponLeftArea.h .cpp
    Weapon.Build.cs
    WeaponAssetEditor.h .cpp
    WeaponAssetFactory.h .cpp
    WeaponCommand.h .cpp 
    WeaponContextMenu.h .cpp
    WeaponModule.h .cpp
    WeaponStyle.h .cpp 
     
       

     

     
    Source
      U2212_06
        Characters
        CAnimInstance.h .cpp
    CEnemy.h .cpp 
    CPlayer.h .cpp
    ICharacter.h .cpp
        Components
        CAIBehaviorComponent.h .cpp 생성
    CFeetComponent.h .cpp

    CMontagesComponent.h .cpp 
    CMovementComponent.h .cpp 
    CStateComponent.h .cpp
    CStatusComponent.h .cpp  
    CWeaponComponent.h .cpp 
    CZoomComponent.h .cpp 생성
        Notifies
        CAnimNotifyState_BeginAction.h .cpp
    CAnimNotifyState_BowString.h .cpp
    CAnimNotify_CameraShake.h .cpp 
    CAnimNotify_End_Parkour
    CAnimNotifyState_EndAction.h .cpp
    CAnimNotify_EndState.h .cpp
    CAnimNotifyState.h .cpp
    CAnimNotifyState_CameraAnim.h .cpp
    CAnimNotifyState_Collision.h .cpp 
    CAnimNotifyState_Combo.h .cpp
    CAnimNotifyState_Equip.h .cpp
    CAnimNotifyState_SubAction.h .cpp
        Parkour
        CParkourComponent.h .cpp
        Utilities
        CHelper.h
    CLog.h .cpp
        Weapons
        CArrow.h .cpp
    CAura.h .cpp
    CCamerModifier.h .cpp
    CGhostTrail.h .cpp
    CRotate_Object.h .cpp
    CThornObject.h .cpp
    CAnimInstance_Bow.h .cpp
    CAttachment_Bow.h .cpp
    CDoAction_Around.h .cpp
    CDoAction_Bow.h .cpp
    CDoAction_Combo.h .cpp
    CDoAction_Warp.h .cpp
    CSubAction_Around.h .cpp
    CSubAction_Bow.h .cpp
    CSubAction_Fist.h .cpp
    CSubAction_Hammer.h .cpp
    CSubAction_Sword.h .cpp
    CDoAction_Warp.h .cpp

    CAttachment.h .cpp
    CDoAction.h .cpp
    CEquipment.h .cpp
    CSubAction.h .cpp
    CWeaponAsset.h .cpp
    CWeaponStructures.h .cpp
        Global.h
    CGameMode.h .cpp
    U2212_06.Build.cs
        U2212_06.uproject
     

     

     

     

     

     

    Feet IK 구현하기

     


     

    CAnimInstance

     

     

    CAnimInstance.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "Animation/AnimInstance.h"
    #include "Components/CWeaponComponent.h"
    #include "Components/CFeetComponent.h"
    #include "CAnimInstance.generated.h"
    
    UCLASS()
    class U2212_06_API UCAnimInstance : public UAnimInstance
    {
    	GENERATED_BODY()
    
    protected:
        UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Animation")
            float Speed;
    
        UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Animation")
            float Pitch;
    
        UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Animation")
            float Direction;
    
        UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Animation")
            bool bFalling;//추락중 여부
    
        UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Animation")
            bool bBow_Aiming;
    
        //Feet IK
        UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "InverseKinemetics")
            bool bFeet;
    
        UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "InverseKinemetics")
            FFeetData FeetData;
    
    protected:
        UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Animation")
            EWeaponType WeaponType = EWeaponType::Max;
    
    public:
        void NativeBeginPlay() override;
        void NativeUpdateAnimation(float DeltaSeconds) override;
    
    private:
        UFUNCTION()
            void OnWeaponTypeChanged(EWeaponType InPrevType, EWeaponType InNewType);
    
    private:
        class ACharacter* OwnerCharacter;
        class UCWeaponComponent* Weapon;
    
    private:
        FRotator PrevRotation;
    };

    변수 추가

    • UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Animation")
      bool bFalling;
      • 추락중 여부를 체크하는 bool 변수

     

     

     

    CAnimInstance.cpp

    더보기
    #include "Characters/CAnimInstance.h"
    #include "Global.h"
    #include "GameFramework/Character.h"
    #include "GameFramework/CharacterMovementComponent.h"
    #include "Weapons/CSubAction.h"
    #include "Parkour/CParkourComponent.h"
    #include "Components/CFeetComponent.h"
    
    void UCAnimInstance::NativeBeginPlay()
    {
    	Super::NativeBeginPlay();
    
    	OwnerCharacter = Cast<ACharacter>(TryGetPawnOwner());
    	CheckNull(OwnerCharacter);
    
    	Weapon = CHelpers::GetComponent<UCWeaponComponent>(OwnerCharacter);
    	if (!!Weapon)
    		Weapon->OnWeaponTypeChange.AddDynamic(this, &UCAnimInstance::OnWeaponTypeChanged);
    }
    
    void UCAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
    {
    	Super::NativeUpdateAnimation(DeltaSeconds);
    	CheckNull(OwnerCharacter);
    
    	Speed = OwnerCharacter->GetVelocity().Size2D();
    
    	FRotator rotator = OwnerCharacter->GetVelocity().ToOrientationRotator();
    	FRotator rotator2 = OwnerCharacter->GetControlRotation();
    	FRotator delta = UKismetMathLibrary::NormalizedDeltaRotator(rotator, rotator2);
    	PrevRotation = UKismetMathLibrary::RInterpTo(PrevRotation, delta, DeltaSeconds, 25);
    	Direction = PrevRotation.Yaw;
    
    	Pitch = UKismetMathLibrary::FInterpTo(Pitch, OwnerCharacter->GetBaseAimRotation().Pitch, DeltaSeconds, 25);
    	bFalling = OwnerCharacter->GetCharacterMovement()->IsFalling();
    
    
    	CheckNull(Weapon);//무기가 있는지 확인
    
    	/** 파쿠르*/
    	UCParkourComponent* parkour = CHelpers::GetComponent<UCParkourComponent>(OwnerCharacter);
    	UCFeetComponent* feet = CHelpers::GetComponent<UCFeetComponent>(OwnerCharacter);
    
    	bFeet = false;
    	
    	if(Weapon->IsUnarmedMode())
    	{
    		if (!!parkour && !!feet)
    		{
    			bFeet = parkour->IsExecuting() == false;//EParkourType::Max라면 false==false가 되어 bFeet은 true, EParkourType::Max가 아닌 상황이라면 true==false가 되어 bFeet은 false.
    			FeetData = feet->GetData();//FFeetData를 넣어준다.
    		}
    		else if (!!feet)
    		{
    			bFeet = true;
    			FeetData = feet->GetData();
    		}
    	}	
    	/** 파쿠르*/
    	
    	/** 활*/
    	if (!!Weapon->GetSubAction())
    	{
    		bBow_Aiming = true;
    		bBow_Aiming &= WeaponType == EWeaponType::Bow;
    		bBow_Aiming &= Weapon->GetSubAction()->GetInAction();		
    	}
    	/** 활*/
    }
    
    void UCAnimInstance::OnWeaponTypeChanged(EWeaponType InPrevType, EWeaponType InNewType)
    {
    	WeaponType = InNewType;
    }

    헤더 추가

    • #include "GameFramework/CharacterMovementComponent.h"

     

    void UCAnimInstance::NativeUpdateAnimation(float DeltaSeconds)

    • bFalling = OwnerCharacter->GetCharacterMovement()->IsFalling();

     


     

     

    ABP_Character

     

    FeetLayer 애니메이션 레이어 생성

     

     

    AnimGraph

     


     

    실행화면

     


     

     

     

     

     

     

    Zoom In & Out 구현하기

     


     

     

    CZoomComponent 생성

     

    새 C++ 클래스 - ActorComponent - CZoomComponent 생성

     

     

    CZoomComponent.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "Components/ActorComponent.h"
    #include "CZoomComponent.generated.h"
    
    UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
    class U2212_06_API UCZoomComponent : public UActorComponent
    {
    	GENERATED_BODY()
    
    private:
    	UPROPERTY(EditAnywhere, Category = "Zooming")
    		float Speed = 20;
    
    	UPROPERTY(EditAnywhere, Category = "Zooming")
    		float InterpSpeed = 5;
    
    	UPROPERTY(EditAnywhere, Category = "Zooming")
    		FVector2D Range = FVector2D(100, 500);
    
    public:	
    	UCZoomComponent();
    
    	void SetZoomValue(float InValue);
    
    protected:
    	virtual void BeginPlay() override;
    
    public:	
    	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
    
    private:
    	class USpringArmComponent* SpringArm;
    
    	float CurrentValue;
    		
    };

     

     

     

     

    CZoomComponent.cpp

    더보기
    #include "Components/CZoomComponent.h"
    #include "Global.h"
    #include "GameFramework/SpringArmComponent.h"
    
    UCZoomComponent::UCZoomComponent()
    {
    	PrimaryComponentTick.bCanEverTick = true;
    }
    
    void UCZoomComponent::BeginPlay()
    {
    	Super::BeginPlay();
    
    	SpringArm = CHelpers::GetComponent<USpringArmComponent>(GetOwner());
    	CheckNull(SpringArm);
    
    	CurrentValue = SpringArm->TargetArmLength;
    }
    
    void UCZoomComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
    {
    	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
    
    	CheckNull(SpringArm);
    
    	CheckTrue(UKismetMathLibrary::NearlyEqual_FloatFloat(SpringArm->TargetArmLength, CurrentValue));
    	SpringArm->TargetArmLength = UKismetMathLibrary::FInterpTo(SpringArm->TargetArmLength, CurrentValue, DeltaTime, InterpSpeed);
    }
    
    void UCZoomComponent::SetZoomValue(float InValue)
    {
    	CurrentValue += (Speed * InValue);
    	CurrentValue = FMath::Clamp(CurrentValue, Range.X, Range.Y);
    }

     

     


     

     

    CPlayer

     

     

    CPlayer.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "GameFramework/Character.h"
    #include "Components/CStateComponent.h"
    #include "Characters/ICharacter.h"
    #include "Parkour/CParkourComponent.h"
    #include "CPlayer.generated.h"
    
    UCLASS()
    class U2212_06_API ACPlayer
    	: public ACharacter, public IICharacter //다중상속
    {
    	GENERATED_BODY()
    
    private:
    	UPROPERTY(VisibleAnywhere)
    		class USpringArmComponent* SpringArm;
    
    	UPROPERTY(VisibleAnywhere)
    		class UCameraComponent* Camera;
    
    private:
    	UPROPERTY(VisibleAnywhere)
    		class UCWeaponComponent* Weapon;
    
    	UPROPERTY(VisibleAnywhere)
    		class UCMontagesComponent* Montages;
    
    	UPROPERTY(VisibleAnywhere)
    		class UCMovementComponent* Movement;
    
    	UPROPERTY(VisibleAnywhere)
    		class UCStateComponent* State;
    
    /** 파쿠르 */
    private:
    	UPROPERTY(VisibleDefaultsOnly)
    		class USceneComponent* ArrowGroup;//파쿠르를 위한 ArrowGroup
    
    	UPROPERTY(VisibleDefaultsOnly)
    		class UArrowComponent* Arrows[(int32)EParkourArrowType::Max];
    
    	UPROPERTY(VisibleDefaultsOnly)
    		class UCParkourComponent* Parkour;
    /** 파쿠르 */
    
    	UPROPERTY(VisibleDefaultsOnly)
    		class UCZoomComponent* Zoom;
    
    public:
    	ACPlayer();
    
    protected:
    	virtual void BeginPlay() override;
    
    public:	
    	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    
    private:
    	UFUNCTION()
    		void OnStateTypeChanged(EStateType InPrevType, EStateType InNewType);
    
    private:
    	void OnAvoid();
    
    private:
    	void BackStep();
    
    public:
    	void End_BackStep() override;//ICharacter의 함수 오버라이드
    
    public:
    	void Click_RightButton();
    
    public:
    	void Landed(const FHitResult& Hit) override;//BP의 OnLanded C++버젼.
    
    private:
    	void SetZooming(float InValue);
    };

    변수 추가

    • UPROPERTY(VisibleDefaultsOnly)
      class UCZoomComponent* Zoom;

     

    함수 추가

    • void SetZooming(float InValue);

     

     

     

    CPlayer.cpp

    더보기
    #include "Characters/CPlayer.h"
    #include "Global.h"
    #include "CAnimInstance.h"
    #include "GameFramework/SpringArmComponent.h"
    #include "GameFramework/CharacterMovementComponent.h"
    #include "Camera/CameraComponent.h"
    #include "Components/SkeletalMeshComponent.h"
    #include "Components/InputComponent.h"
    #include "Components/CMontagesComponent.h"
    #include "Components/CMovementComponent.h"
    #include "Components/CWeaponComponent.h"
    #include "Components/CZoomComponent.h"
    #include "Components/ArrowComponent.h"
    
    ACPlayer::ACPlayer()
    {
    	CHelpers::CreateComponent<USpringArmComponent>(this, &SpringArm, "SpringArm", GetMesh());
    	CHelpers::CreateComponent<UCameraComponent>(this, &Camera, "Camera", SpringArm);
    
    	CHelpers::CreateActorComponent<UCWeaponComponent>(this, &Weapon, "Weapon");
    	CHelpers::CreateActorComponent<UCMontagesComponent>(this, &Montages, "Montages");
    	CHelpers::CreateActorComponent<UCMovementComponent>(this, &Movement, "Movement");
    	CHelpers::CreateActorComponent<UCStateComponent>(this, &State, "State");
    	CHelpers::CreateActorComponent<UCParkourComponent>(this, &Parkour, "Parkour");
    	CHelpers::CreateActorComponent<UCZoomComponent>(this, &Zoom, "Zoom");
    
    	GetMesh()->SetRelativeLocation(FVector(0, 0, -90));
    	GetMesh()->SetRelativeRotation(FRotator(0, -90, 0));
    
    	USkeletalMesh* mesh;
    	CHelpers::GetAsset<USkeletalMesh>(&mesh, "SkeletalMesh'/Game/Character/Mesh/SK_Mannequin.SK_Mannequin'");
    	GetMesh()->SetSkeletalMesh(mesh);
    
    	TSubclassOf<UCAnimInstance> animInstance;
    	CHelpers::GetClass<UCAnimInstance>(&animInstance, "AnimBlueprint'/Game/ABP_Character.ABP_Character_C'");
    	GetMesh()->SetAnimClass(animInstance);
    
    	SpringArm->SetRelativeLocation(FVector(0, 0, 140));
    	SpringArm->SetRelativeRotation(FRotator(0, 90, 0));
    	SpringArm->TargetArmLength = 200;
    	SpringArm->bDoCollisionTest = false;
    	SpringArm->bUsePawnControlRotation = true;
    	SpringArm->bEnableCameraLag = true;
    
    	GetCharacterMovement()->RotationRate = FRotator(0, 720, 0);
    
    	CHelpers::CreateComponent<USceneComponent>(this, &ArrowGroup, "ArrowGroup", GetCapsuleComponent());//ArrowGroup을 생성하고 GetCapsuleComponent 아래로 붙여준다.
    	//파쿠르에 활용한 Arrows들을 생성한다. 
    	for (int32 i = 0; i < (int32)EParkourArrowType::Max; i++)
    	{
    		FString name = StaticEnum<EParkourArrowType>()->GetNameStringByIndex(i);
    		CHelpers::CreateComponent<UArrowComponent>(this, &Arrows[i], FName(name), ArrowGroup);
    
    		switch ((EParkourArrowType)i)
    		{
    		case EParkourArrowType::Center:
    			Arrows[i]->ArrowColor = FColor::Red;
    			break;
    
    		case EParkourArrowType::Ceil:
    			Arrows[i]->ArrowColor = FColor::Green;
    			Arrows[i]->SetRelativeLocation(FVector(0, 0, 100));
    			break;
    
    		case EParkourArrowType::Floor:
    			Arrows[i]->ArrowColor = FColor::Blue;
    			Arrows[i]->SetRelativeLocation(FVector(0, 0, -80));
    			break;
    
    		case EParkourArrowType::Left:
    			Arrows[i]->ArrowColor = FColor::Magenta;
    			Arrows[i]->SetRelativeLocation(FVector(0, -30, 0));
    			break;
    
    		case EParkourArrowType::Right:
    			Arrows[i]->ArrowColor = FColor::Magenta;
    			Arrows[i]->SetRelativeLocation(FVector(0, 30, 0));
    			break;
    
    		case EParkourArrowType::Land:
    			Arrows[i]->ArrowColor = FColor::Yellow;
    			Arrows[i]->SetRelativeLocation(FVector(200, 0, 100));
    			Arrows[i]->SetRelativeRotation(FRotator(-90, 0, 0));
    			break;
    		}
    	}
    
    }
    
    void ACPlayer::BeginPlay()
    {
    	Super::BeginPlay();
    
    	Movement->OnRun(); //Movement의 기본을 Run으로 설정
    	Movement->DisableControlRotation();//Movement의 기본을 DisableControlRotation으로 설정
    
    	State->OnStateTypeChanged.AddDynamic(this, &ACPlayer::OnStateTypeChanged);
    }
    
    void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
    {
    	Super::SetupPlayerInputComponent(PlayerInputComponent);
    
    	PlayerInputComponent->BindAxis("MoveForward", Movement, &UCMovementComponent::OnMoveForward);
    	PlayerInputComponent->BindAxis("MoveRight", Movement, &UCMovementComponent::OnMoveRight);
    	PlayerInputComponent->BindAxis("VerticalLook", Movement, &UCMovementComponent::OnVerticalLook);
    	PlayerInputComponent->BindAxis("HorizontalLook", Movement, &UCMovementComponent::OnHorizontalLook);
    
    	PlayerInputComponent->BindAction("Sprint", EInputEvent::IE_Pressed, Movement, &UCMovementComponent::OnSprint);
    	PlayerInputComponent->BindAction("Sprint", EInputEvent::IE_Released, Movement, &UCMovementComponent::OnRun);
    
    	PlayerInputComponent->BindAction("Avoid", EInputEvent::IE_Pressed, this, &ACPlayer::OnAvoid);
    
    	//PlayerInputComponent->BindAxis("Zoom", Zoom, &UCZoomComponent::SetZoomValue);//Value로 연동되게하면 Bow 모드 시 문제가 될 수 있다.
    	PlayerInputComponent->BindAxis("Zoom", this, &ACPlayer::SetZooming);//Bow 모드가 아닐 때만 사용하려고 SetZooming으로 설정하여 만들었다.
    
    	PlayerInputComponent->BindAction("Fist", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetFistMode);
    	PlayerInputComponent->BindAction("Sword", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetSwordMode);
    	PlayerInputComponent->BindAction("Hammer", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetHammerMode);
    	PlayerInputComponent->BindAction("Warp", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetWarpMode);
    	PlayerInputComponent->BindAction("Around", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetAroundMode);
    	PlayerInputComponent->BindAction("Bow", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetBowMode);
    
    	PlayerInputComponent->BindAction("Action", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::DoAction);
    
    	//PlayerInputComponent->BindAction("SubAction", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SubAction_Pressed);
    	PlayerInputComponent->BindAction("SubAction", EInputEvent::IE_Pressed, this, &ACPlayer::Click_RightButton);
    	PlayerInputComponent->BindAction("SubAction", EInputEvent::IE_Released, Weapon, &UCWeaponComponent::SubAction_Released);
    }
    
    void ACPlayer::OnStateTypeChanged(EStateType InPrevType, EStateType InNewType)
    {
    	switch (InNewType)
    	{
    		case EStateType::BackStep: BackStep(); break;
    	}
    }
    
    void ACPlayer::OnAvoid()
    {
    	CheckFalse(State->IsIdleMode());
    	CheckFalse(Movement->CanMove());
    
    	CheckTrue(InputComponent->GetAxisValue("MoveForward") >= 0.0f);//뒷방향을 입력했다면
    
    	State->SetBackStepMode();//State을 BackStepMode로 변경한다.
    }
    
    void ACPlayer::BackStep()
    {
    	Movement->EnableControlRotation();//정면을 바라본 상태로 뒤로 뛰어야하기 때문에 EnableControlRotation으로 만들어준다.
    
    	Montages->PlayBackStepMode();//PlayBackStepMode()를 통해 몽타주 재생.
    }
    
    void ACPlayer::End_BackStep()
    {
    	Movement->DisableControlRotation();//Backstep이 끝나면 원래대로 돌려준다.
    
    	State->SetIdleMode();//Idle상태로 돌려줌.
    }
    
    void ACPlayer::Click_RightButton()
    {
    	if (Weapon->IsUnarmedMode())
    	{
    		Parkour->DoParkour();
    
    		return;
    	}
    
    	Weapon->SubAction_Pressed();
    }
    
    void ACPlayer::Landed(const FHitResult& Hit)
    {
    	Parkour->DoParkour(true);
    }
    
    void ACPlayer::SetZooming(float InValue)
    {
    	CheckTrue(Weapon->IsBowMode());//BowMode이면 바로 리턴
    
    	Zoom->SetZoomValue(InValue);//BowMode가 아닌 경우 Zoom In&Out 가능.
    }

     

    헤더 추가

    • #include "Components/CZoomComponent.h"

     

    ACPlayer::ACPlayer()

    • CHelpers::CreateActorComponent<UCZoomComponent>(this, &Zoom, "Zoom");

     

    void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)

    • PlayerInputComponent->BindAxis("Zoom", this, &ACPlayer::SetZooming);
      • Bow 모드가 아닐 때만 사용하려고 SetZooming으로 설정하여 만들었다.

     

    void ACPlayer::SetZooming(float InValue)

    • CheckTrue(Weapon->IsBowMode());
    • Zoom->SetZoomValue(InValue);

     


     

     

    실행화면

     

     

     


     

     

     

     

    Enemy AI

     

     


     

     

    Build.cs

     

     

     

    더보기
    using UnrealBuildTool;
    
    public class U2212_06 : ModuleRules
    {
    	public U2212_06(ReadOnlyTargetRules Target) : base(Target)
    	{
            PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
    
    		PublicIncludePaths.Add(ModuleDirectory);
    
    
            PublicDependencyModuleNames.Add("Core");
    
            PrivateDependencyModuleNames.Add("CoreUObject");
            PrivateDependencyModuleNames.Add("Engine");
            PrivateDependencyModuleNames.Add("InputCore");
    
            PublicDependencyModuleNames.Add("Niagara");
    
            PublicDependencyModuleNames.Add("AIModule");
        }
    }

    모듈 추가

    • PublicDependencyModuleNames.Add("AIModule");

     


     

     

    CEnemy_AI 생성

     

    새 C++ 클래스 - CEnemy - CEnemy_AI 생성

     

     

    CEnemy_AI.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "Characters/CEnemy.h"
    #include "CEnemy_AI.generated.h"
    
    UCLASS()
    class U2212_06_API ACEnemy_AI : public ACEnemy
    {
    	GENERATED_BODY()
    
    private:
    	UPROPERTY(EditDefaultsOnly, Category = "AI")
    		class UBehaviorTree* BehaviorTree;
    
    private:
    	UPROPERTY(EditDefaultsOnly, Category = "Label")
    		float LabelViewAmount = 3000.0f;
    
    #if WITH_EDITOR
    private:
    	UPROPERTY(VisibleDefaultsOnly)
    		class UWidgetComponent* LabelWidget;
    #endif
    	
    private:
    	UPROPERTY(VisibleDefaultsOnly)
    		class UCWeaponComponent* Weapon;
    
    	UPROPERTY(VisibleDefaultsOnly)
    		class UCAIBehaviorComponent* Behavior;
    
    public:
    	ACEnemy_AI();
    
    protected:
    	virtual void BeginPlay() override;
    
    public:
    	virtual void Tick(float DeltaTime) override;
    
    private:
    	void UpdateLabelRenderScale();
    };

     

     

     

     

     

    CEnemy_AI.cpp

    더보기
    #include "Characters/CEnemy_AI.h"
    #include "Global.h"
    #include "Components/CWeaponComponent.h"
    #include "Components/CAIBehaviorComponent.h"
    #include "Components/WidgetComponent.h"
    #include "Components/CStatusComponent.h"
    #include "Widgets/CUserWidget_Label.h"
    
    ACEnemy_AI::ACEnemy_AI()
    {
    	PrimaryActorTick.bCanEverTick = true;
    
    	CHelpers::CreateComponent<UWidgetComponent>(this, &LabelWidget, "Label", GetMesh());
    
    	CHelpers::CreateActorComponent<UCWeaponComponent>(this, &Weapon, "Weapon");
    	CHelpers::CreateActorComponent<UCAIBehaviorComponent>(this, &Behavior, "Behavior");
    
    
    	TSubclassOf<UCUserWidget_Label> labelClass;
    	CHelpers::GetClass<UCUserWidget_Label>(&labelClass, "WidgetBlueprint'/Game/Widgets/WB_Label.WB_Label_C'");
    	LabelWidget->SetWidgetClass(labelClass);
    	LabelWidget->SetRelativeLocation(FVector(0, 0, 220));
    	LabelWidget->SetDrawSize(FVector2D(120, 0));
    	LabelWidget->SetWidgetSpace(EWidgetSpace::Screen);
    }
    
    void ACEnemy_AI::BeginPlay()
    {
    	Super::BeginPlay();
    
    	LabelWidget->InitWidget();
    
    	UCUserWidget_Label* label = Cast<UCUserWidget_Label>(LabelWidget->GetUserWidgetObject());
    	label->UpdateHealth(Status->GetHealth(), Status->GetMaxHealth());
    	label->UpdateName(GetName());
    	label->UpdateControllerName(GetController()->GetName());
    }
    
    void ACEnemy_AI::Tick(float DeltaTime)
    {
    	Super::Tick(DeltaTime);
    
    	UCUserWidget_Label* label = Cast<UCUserWidget_Label>(LabelWidget->GetUserWidgetObject());
    
    	if (!!label)
    	{
    		label->UpdateHealth(Status->GetHealth(), Status->GetMaxHealth());
    
    		UpdateLabelRenderScale();
    	}
    }
    
    void ACEnemy_AI::UpdateLabelRenderScale()
    {
    	UCUserWidget_Label* label = Cast<UCUserWidget_Label>(LabelWidget->GetUserWidgetObject());
    	CheckNull(label);
    
    
    	APlayerCameraManager* cameraManager = UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0);
    
    	FVector cameraLocation = cameraManager->GetCameraLocation();
    	FVector targetLocation = GetController()->GetTargetLocation();
    
    	float distance = FVector::Distance(cameraLocation, targetLocation);
    	float sizeRate = 1.0f - (distance / LabelViewAmount);
    
    	if (distance > LabelViewAmount)
    	{
    		label->SetVisibility(ESlateVisibility::Collapsed);
    
    		return;
    	}
    
    	label->SetVisibility(ESlateVisibility::Visible);
    	label->SetRenderScale(FVector2D(sizeRate, sizeRate));
    }

     

     

     

     

    BP_CEnemy_Melee 생성

    CEnemy_AI 기반 블루프린트 생성 -  BP_CEnemy_Melee 생성

     


     

     

    CAIBehaviorComponent 생성

     

    새 C++ 클래스 - Actor Component - CAIBehavioComponent 생성

     

     

    CAIBehavioComponent .h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "Components/ActorComponent.h"
    #include "CAIBehaviorComponent.generated.h"
    
    UENUM(BlueprintType)
    enum class EAIStateType : uint8
    {
    	Wait = 0, Approach, Action, Patrol, Hitted, Avoid, Dead, Max,
    };
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FAIStateTypeChanged, EAIStateType, InPrevType, EAIStateType, InNewType);
    
    UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
    class U2212_06_API UCAIBehaviorComponent : public UActorComponent
    {
    	GENERATED_BODY()
    
    private:
    	UPROPERTY(EditAnywhere, Category = "Key")
    		FName AIStateTypeKey = "AIState";
    
    	UPROPERTY(EditAnywhere, Category = "Key")
    		FName TargetKey = "Target";
    	
    private:
    	EAIStateType GetType();
    
    public:
    	bool IsWaitMode();
    	bool IsApproachMode();
    	bool IsActionMode();
    	bool IsPatrolMode();
    	bool IsHittedMode();
    	bool IsAvoidMode();
    	bool IsDeadMode();
    
    public:	
    	UCAIBehaviorComponent();
    
    protected:
    	virtual void BeginPlay() override;
    
    public:
    	FORCEINLINE void SetBlackboard(class UBlackboardComponent* InBlackboard) { Blackboard = InBlackboard; }
    
    public:
    	class ACharacter* GetTarget();
    
    public:
    	void SetWaitMode();
    	void SetApproachMode();
    	void SetActionMode();
    	void SetPatrolMode();
    	void SetHittedMode();
    	void SetAvoidMode();
    	void SetDeadMode();
    
    private:
    	void ChangeType(EAIStateType InType);
    
    public:
    	FAIStateTypeChanged OnAIStateTypeChanged;
    
    private:
    	class UBlackboardComponent* Blackboard;
    };

     

     

     

     

    CAIBehavioComponent .cpp

    더보기
    #include "Components/CAIBehaviorComponent.h"
    #include "Global.h"
    #include "GameFramework/Character.h"
    #include "BehaviorTree/BlackboardComponent.h"
    
    UCAIBehaviorComponent::UCAIBehaviorComponent()
    {
    }
    
    void UCAIBehaviorComponent::BeginPlay()
    {
    	Super::BeginPlay();
    }
    
    EAIStateType UCAIBehaviorComponent::GetType()
    {
    	return (EAIStateType)Blackboard->GetValueAsEnum(AIStateTypeKey);
    }
    
    bool UCAIBehaviorComponent::IsWaitMode()
    {
    	return GetType() == EAIStateType::Wait;
    }
    
    bool UCAIBehaviorComponent::IsApproachMode()
    {
    	return GetType() == EAIStateType::Approach;
    }
    
    bool UCAIBehaviorComponent::IsActionMode()
    {
    	return GetType() == EAIStateType::Action;
    }
    
    bool UCAIBehaviorComponent::IsPatrolMode()
    {
    	return GetType() == EAIStateType::Patrol;
    }
    
    bool UCAIBehaviorComponent::IsHittedMode()
    {
    	return GetType() == EAIStateType::Hitted;
    }
    
    bool UCAIBehaviorComponent::IsAvoidMode()
    {
    	return GetType() == EAIStateType::Avoid;
    }
    
    bool UCAIBehaviorComponent::IsDeadMode()
    {
    	return GetType() == EAIStateType::Dead;
    }
    
    void UCAIBehaviorComponent::SetWaitMode()
    {
    	ChangeType(EAIStateType::Wait);
    }
    
    void UCAIBehaviorComponent::SetApproachMode()
    {
    	ChangeType(EAIStateType::Approach);
    }
    
    void UCAIBehaviorComponent::SetActionMode()
    {
    	ChangeType(EAIStateType::Action);
    }
    
    void UCAIBehaviorComponent::SetPatrolMode()
    {
    	ChangeType(EAIStateType::Patrol);
    }
    
    void UCAIBehaviorComponent::SetHittedMode()
    {
    	ChangeType(EAIStateType::Hitted);
    }
    
    void UCAIBehaviorComponent::SetAvoidMode()
    {
    	ChangeType(EAIStateType::Avoid);
    }
    
    void UCAIBehaviorComponent::SetDeadMode()
    {
    	ChangeType(EAIStateType::Dead);
    }
    
    void UCAIBehaviorComponent::ChangeType(EAIStateType InType)
    {
    	EAIStateType prevType = GetType();
    
    	Blackboard->SetValueAsEnum(AIStateTypeKey, (uint8)InType);
    
    	if (OnAIStateTypeChanged.IsBound())
    		OnAIStateTypeChanged.Broadcast(prevType, InType);
    }

     

     

     

     


     

    CUserWidet_Label 생성

     

    새 C++ 클래스 - UserWidget - CUserWidet_Label 생성

     

     

    CUserWidet_Label.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "Blueprint/UserWidget.h"
    #include "CUserWidget_Label.generated.h"
    
    UCLASS()
    class U2212_06_API UCUserWidget_Label : public UUserWidget
    {
    	GENERATED_BODY()
    
    public:
    	UFUNCTION(BlueprintImplementableEvent, Category = "Label")
    		void UpdateHealth(float InHealth, float InMaxHealth);
    
    	UFUNCTION(BlueprintImplementableEvent, Category = "Label")
    		void UpdateName(const FString& InName);
    
    	UFUNCTION(BlueprintImplementableEvent, Category = "Label")
    		void UpdateControllerName(const FString& InName);
    	
    };

     

     

     

     

    CUserWidet_Label.cpp

    더보기
    #include "Widgets/CUserWidget_Label.h"

     


     

     

     

    WB_Widget

     

    유저 인터페이스 - 위젯 블루프린트 - WB_Wdiget 생

     

     

    디자이너

    그래프


     

     

     

    실행화면

     

     

     


     

     

     

     

     

     

    Zoom In & Out 기능으로 활 조준 Zoom 튕기는 오류해결(by 미래에서 온 나)

     


     

     

    CPlayer

     

    FPS처럼 Zoom이 일어나는 경우, 1인칭 시점 카메라를 추가해서 만들고 Zoom 시에 카메라 전환을 하여 1인칭 전용 카메라를 사용해준다.

     

    CPlayer.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "GameFramework/Character.h"
    #include "Components/CStateComponent.h"
    #include "Characters/ICharacter.h"
    #include "Parkour/CParkourComponent.h"
    #include "GenericTeamAgentInterface.h"
    #include "CPlayer.generated.h"
    
    UCLASS()
    class U2212_06_API ACPlayer
    	: public ACharacter, public IICharacter, public IGenericTeamAgentInterface //다중상속
    {
    	GENERATED_BODY()
    
    private:
    	UPROPERTY(EditDefaultsOnly, Category = "Team")
    		uint8 TeamID = 1;
    
    private:
    	UPROPERTY(VisibleAnywhere)
    		class USpringArmComponent* SpringArm;
    
    	UPROPERTY(VisibleAnywhere)
    		class UCameraComponent* Camera;
    
    private:
    	UPROPERTY(VisibleAnywhere)
    		class UCWeaponComponent* Weapon;
    
    	UPROPERTY(VisibleAnywhere)
    		class UCMontagesComponent* Montages;
    
    	UPROPERTY(VisibleAnywhere)
    		class UCMovementComponent* Movement;
    
    	UPROPERTY(VisibleAnywhere)
    		class UCStateComponent* State;
    
    /** 파쿠르 */
    private:
    	UPROPERTY(VisibleDefaultsOnly)
    		class USceneComponent* ArrowGroup;//파쿠르를 위한 ArrowGroup
    
    	UPROPERTY(VisibleDefaultsOnly)
    		class UArrowComponent* Arrows[(int32)EParkourArrowType::Max];
    
    	UPROPERTY(VisibleDefaultsOnly)
    		class UCParkourComponent* Parkour;
    /** 파쿠르 */
    
    	UPROPERTY(VisibleDefaultsOnly)
    		class UCZoomComponent* Zoom;
    
    public:
    	ACPlayer();
    
    protected:
    	virtual void BeginPlay() override;
    
    public:	
    	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    	FGenericTeamId GetGenericTeamId() const override { return FGenericTeamId(TeamID); }
    
    private:
    	UFUNCTION()
    		void OnStateTypeChanged(EStateType InPrevType, EStateType InNewType);
    
    private:
    	void OnAvoid();
    
    private:
    	void BackStep();
    
    public:
    	void End_BackStep() override;//ICharacter의 함수 오버라이드
    
    public:
    	void OnRightButton();
    	void OffRightButton();
    
    public:
    	void Landed(const FHitResult& Hit) override;//BP의 OnLanded C++버젼.
    
    private:
    	void SetZooming(float InValue);
    };

    함수 수정 및 추가

    • 변경 전:
      • void Click_RightButton();
    • 변경 후:
      • void OnRightButton();
      • void OffRightButton();

     

     

     

    CPlayer.cpp

    더보기
    #include "Characters/CPlayer.h"
    #include "Global.h"
    #include "CAnimInstance.h"
    #include "GameFramework/SpringArmComponent.h"
    #include "GameFramework/CharacterMovementComponent.h"
    #include "Camera/CameraComponent.h"
    #include "Components/SkeletalMeshComponent.h"
    #include "Components/InputComponent.h"
    #include "Components/CMontagesComponent.h"
    #include "Components/CMovementComponent.h"
    #include "Components/CWeaponComponent.h"
    #include "Components/CZoomComponent.h"
    #include "Components/ArrowComponent.h"
    
    ACPlayer::ACPlayer()
    {
    	CHelpers::CreateComponent<USpringArmComponent>(this, &SpringArm, "SpringArm", GetMesh());
    	CHelpers::CreateComponent<UCameraComponent>(this, &Camera, "Camera", SpringArm);
    
    	CHelpers::CreateActorComponent<UCWeaponComponent>(this, &Weapon, "Weapon");
    	CHelpers::CreateActorComponent<UCMontagesComponent>(this, &Montages, "Montages");
    	CHelpers::CreateActorComponent<UCMovementComponent>(this, &Movement, "Movement");
    	CHelpers::CreateActorComponent<UCStateComponent>(this, &State, "State");
    	CHelpers::CreateActorComponent<UCParkourComponent>(this, &Parkour, "Parkour");
    	CHelpers::CreateActorComponent<UCZoomComponent>(this, &Zoom, "Zoom");
    
    	GetMesh()->SetRelativeLocation(FVector(0, 0, -90));
    	GetMesh()->SetRelativeRotation(FRotator(0, -90, 0));
    
    	USkeletalMesh* mesh;
    	CHelpers::GetAsset<USkeletalMesh>(&mesh, "SkeletalMesh'/Game/Character/Mesh/SK_Mannequin.SK_Mannequin'");
    	GetMesh()->SetSkeletalMesh(mesh);
    
    	TSubclassOf<UCAnimInstance> animInstance;
    	CHelpers::GetClass<UCAnimInstance>(&animInstance, "AnimBlueprint'/Game/ABP_Character.ABP_Character_C'");
    	GetMesh()->SetAnimClass(animInstance);
    
    	SpringArm->SetRelativeLocation(FVector(0, 0, 140));
    	SpringArm->SetRelativeRotation(FRotator(0, 90, 0));
    	SpringArm->TargetArmLength = 200;
    	SpringArm->bDoCollisionTest = false;
    	SpringArm->bUsePawnControlRotation = true;
    	SpringArm->bEnableCameraLag = true;
    
    	GetCharacterMovement()->RotationRate = FRotator(0, 720, 0);
    
    	CHelpers::CreateComponent<USceneComponent>(this, &ArrowGroup, "ArrowGroup", GetCapsuleComponent());//ArrowGroup을 생성하고 GetCapsuleComponent 아래로 붙여준다.
    	//파쿠르에 활용한 Arrows들을 생성한다. 
    	for (int32 i = 0; i < (int32)EParkourArrowType::Max; i++)
    	{
    		FString name = StaticEnum<EParkourArrowType>()->GetNameStringByIndex(i);
    		CHelpers::CreateComponent<UArrowComponent>(this, &Arrows[i], FName(name), ArrowGroup);
    
    		switch ((EParkourArrowType)i)
    		{
    		case EParkourArrowType::Center:
    			Arrows[i]->ArrowColor = FColor::Red;
    			break;
    
    		case EParkourArrowType::Ceil:
    			Arrows[i]->ArrowColor = FColor::Green;
    			Arrows[i]->SetRelativeLocation(FVector(0, 0, 100));
    			break;
    
    		case EParkourArrowType::Floor:
    			Arrows[i]->ArrowColor = FColor::Blue;
    			Arrows[i]->SetRelativeLocation(FVector(0, 0, -80));
    			break;
    
    		case EParkourArrowType::Left:
    			Arrows[i]->ArrowColor = FColor::Magenta;
    			Arrows[i]->SetRelativeLocation(FVector(0, -30, 0));
    			break;
    
    		case EParkourArrowType::Right:
    			Arrows[i]->ArrowColor = FColor::Magenta;
    			Arrows[i]->SetRelativeLocation(FVector(0, 30, 0));
    			break;
    
    		case EParkourArrowType::Land:
    			Arrows[i]->ArrowColor = FColor::Yellow;
    			Arrows[i]->SetRelativeLocation(FVector(200, 0, 100));
    			Arrows[i]->SetRelativeRotation(FRotator(-90, 0, 0));
    			break;
    		}
    	}
    
    }
    
    void ACPlayer::BeginPlay()
    {
    	Super::BeginPlay();
    
    	Movement->OnRun(); //Movement의 기본을 Run으로 설정
    	Movement->DisableControlRotation();//Movement의 기본을 DisableControlRotation으로 설정
    
    	State->OnStateTypeChanged.AddDynamic(this, &ACPlayer::OnStateTypeChanged);
    }
    
    void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
    {
    	Super::SetupPlayerInputComponent(PlayerInputComponent);
    
    	PlayerInputComponent->BindAxis("MoveForward", Movement, &UCMovementComponent::OnMoveForward);
    	PlayerInputComponent->BindAxis("MoveRight", Movement, &UCMovementComponent::OnMoveRight);
    	PlayerInputComponent->BindAxis("VerticalLook", Movement, &UCMovementComponent::OnVerticalLook);
    	PlayerInputComponent->BindAxis("HorizontalLook", Movement, &UCMovementComponent::OnHorizontalLook);
    
    	PlayerInputComponent->BindAction("Sprint", EInputEvent::IE_Pressed, Movement, &UCMovementComponent::OnSprint);
    	PlayerInputComponent->BindAction("Sprint", EInputEvent::IE_Released, Movement, &UCMovementComponent::OnRun);
    
    	PlayerInputComponent->BindAction("Avoid", EInputEvent::IE_Pressed, this, &ACPlayer::OnAvoid);
    
    	//PlayerInputComponent->BindAxis("Zoom", Zoom, &UCZoomComponent::SetZoomValue);//Value로 연동되게하면 Bow 모드 시 문제가 될 수 있다.
    	PlayerInputComponent->BindAxis("Zoom", this, &ACPlayer::SetZooming);//Bow 모드가 아닐 때만 사용하려고 SetZooming으로 설정하여 만들었다.
    
    	PlayerInputComponent->BindAction("Fist", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetFistMode);
    	PlayerInputComponent->BindAction("Sword", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetSwordMode);
    	PlayerInputComponent->BindAction("Hammer", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetHammerMode);
    	PlayerInputComponent->BindAction("Warp", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetWarpMode);
    	PlayerInputComponent->BindAction("Around", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetAroundMode);
    	PlayerInputComponent->BindAction("Bow", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetBowMode);
    
    	PlayerInputComponent->BindAction("Action", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::DoAction);
    	
    	PlayerInputComponent->BindAction("SubAction", EInputEvent::IE_Pressed, this, &ACPlayer::OnRightButton);
    	PlayerInputComponent->BindAction("SubAction", EInputEvent::IE_Released, this, &ACPlayer::OffRightButton);
    }
    
    void ACPlayer::OnStateTypeChanged(EStateType InPrevType, EStateType InNewType)
    {
    	switch (InNewType)
    	{
    		case EStateType::BackStep: BackStep(); break;
    	}
    }
    
    void ACPlayer::OnAvoid()
    {
    	CheckFalse(State->IsIdleMode());
    	CheckFalse(Movement->CanMove());
    
    	CheckTrue(InputComponent->GetAxisValue("MoveForward") >= 0.0f);//뒷방향을 입력했다면
    
    	State->SetBackStepMode();//State을 BackStepMode로 변경한다.
    }
    
    void ACPlayer::BackStep()
    {
    	Movement->EnableControlRotation();//정면을 바라본 상태로 뒤로 뛰어야하기 때문에 EnableControlRotation으로 만들어준다.
    
    	Montages->PlayBackStepMode();//PlayBackStepMode()를 통해 몽타주 재생.
    }
    
    void ACPlayer::End_BackStep()
    {
    	Movement->DisableControlRotation();//Backstep이 끝나면 원래대로 돌려준다.
    
    	State->SetIdleMode();//Idle상태로 돌려줌.
    }
    
    void ACPlayer::OnRightButton()
    {
    	if (Weapon->IsUnarmedMode())
    	{
    		Parkour->DoParkour();
    
    		return;
    	}
    
    	if (Weapon->IsBowMode())
    	{
    		//BowMode(활 장착)일 때 우클릭을 누르고 있을때 Zoom기능을 꺼준다.
    		Zoom->SetComponentTickEnabled(false);
    	}
    
    	Weapon->SubAction_Pressed();
    }
    
    void ACPlayer::OffRightButton()
    {
    	if (Weapon->IsBowMode())
    	{
    		//BowMode(활 장착)일 때 우클릭을 떼면 Zoom기능을 꺼준다.
    		Zoom->SetComponentTickEnabled(true);
    	}
    
    	Weapon->SubAction_Released();
    }
    
    void ACPlayer::Landed(const FHitResult& Hit)
    {
    	Parkour->DoParkour(true);
    }
    
    void ACPlayer::SetZooming(float InValue)
    {
    	CheckTrue(Weapon->IsBowMode());//BowMode이면 바로 리턴
    
    	Zoom->SetZoomValue(InValue);//BowMode가 아닌 경우 Zoom In&Out 가능.
    }

    함수 수정 및 추가

    • void ACPlayer::OnRightButton()
      • if (Weapon->IsBowMode())  {  Zoom->SetComponentTickEnabled(false);  }
      • Weapon->SubAction_Pressed();
    • void ACPlayer::OffRightButton()
      • if (Weapon->IsBowMode())  {  Zoom->SetComponentTickEnabled(true);  }
      • Weapon->SubAction_Released();

     


     

     

    실행화면

     

     


     

    '⭐ Unreal Engine > UE RPG Skill' 카테고리의 다른 글

    [UE] 파쿠르, Feet IK  (0) 2023.07.20
    [UE] 파쿠르: 벽 오르기  (0) 2023.07.19
    [UE] 파쿠르 구현하기  (0) 2023.07.18
    [UE] 화살  (0) 2023.07.13
    [UE] 활 시위에 손 맞추기  (0) 2023.07.10