1. 걷기 애니메이션 추가
캐릭터가 움직이기만 하고 모션은 그대로다.
그러니까 애니메이션도 적용시키자.
일단 지금부터 할 짓은 Animation Blueprint 를 만들고 그걸 전에 만든 Blueprint Class 에 적용시키는 것이다.
위처럼 만들자.
그럼 왼쪽에 EventGraph, Animation Graph 가 있다.
제일 많이 손대는 2가지 중 하나로, 전자는 내외부에서 주는 호출인 이벤트,
후자는 현재 상태에 따른 애니메이션 상태를 조절한다.
우선 이벤트먼저 처리하자.
변수 추가하고
위의 화살표는 처리 순서이고 아래는 값이 움직인다.
여기서 처리가능한건 모두 코드로 가능하다.
애니메이션 그래프에선 우선 위처럼 New State Machine 을 추가하자.
연결하고 State Machine 을 더블클릭하자.
마우스 오른쪽 키를 누르면 Add State 가 나온다.
위처럼 만들어주자.
State 에서는 애니메이션을 지정하고,
화살표에 있는 둥근 아이콘을 누르면 State 를 변경하는 조건을 설정할 수 있다.
근데 Idle/Run 애니메이션이 없어서 만들러가자.
Idle/Run 이 말하는건 보통 Idle, Run 애니메이션이 따로 있는데, 이동속도에 맞춰서 블렌딩하면 더 있어보이기 때문에 그걸 합쳐서 만드는 것이다.
이때 필요한건 MovementVelocity 이고 비슷한걸 전에 계산하도록 마쳤다.
Idle / Run 을 블렌딩하는건 위에 있다.
ID 는 쉬우니까 튜토리얼에서 많이 사용한다.
실행하면 Skeleton 설정하는데, 지금까지 지정한거와 같이 하자.
Asset Browser 에서 옆에 드래그하라는 창에 드래그하자.
특정 변수에 따라서 블렌딩 해준다.
초록점을 드래그하면 어떻게 블렌딩 되는지 보여준다.
양 끝에 Idle, Run 을 넣고, 확인하고 저장.
위에서 설정한 Idle/Run State 를 더블클릭해서 위처럼 해주자.
블렌딩을 한 애니메이션을 사용하는 것.
근데 Idle/Run State 에서 위에서처럼 바로 함수를 호출해서 할 수도 있다.
그리고 Blueprint Class 의 mesh 에서 Animation 을 우리가 방금 만든 Animation Blueprint 에 적용시키자.
그리고 실행하면 캐릭터가 움직인다. ^오^
2. 점프 애니메이션 추가
State Machine 의 Jump Start, Jump Idle, Jump End State 에 위처럼 애니메이션을 추가하자.
Idle/Run 과 Jump Start 사이의 조건을 더블클릭해 위처럼 만들자.
떠있으면 일로 간다는 것이다.
컴파일 & 저장 하고 실행해보자.
그럼 점프 시 애니메이션이 바뀌는데 다시 안돌아 오는걸 알 수 있다.
State 의 처음부터 계속 실행하는게 아니라 현재 State 가 있어서 tick 마다 이어서 진행되는 걸 알 수 있다.
그러므로 Jump Start -> Loop -> End 의 루프를 완성시키자.
위는 Jump Start -> Loop 때 이다.
플래이 중인 애니메이션이 0.01 미만이면, 즉 거의 끝나면 다음꺼로 바꾸잔 말.
안되면 0.1로도 해보자.
위는 Jump Loop -> Jump End 때 이다.
땅에 안닿았을 때까진 계속 돌겠단 말이다.
그런데 애니메이션이 계속 반복된다는걸 어떻게 알 수 있을까?
Jump Loop State 에 있는 애니메이션을 클릭하면 위처럼 Setting 이 있다.
Loop Animation 이 체크 되어있으면 별일 없으면 계속 반복한다.
Jump End -> Idle/Run 때 이다.
체크 해주면 한번 재생되고 바로 간다.
그리고 실행시켜보자.
점프도 잘 된다.
3. 무기 장착
우리가 만든 클래스의 Skeleton 에 들어간다.
소켓 추가.
무기를 끼울 소켓, 즉 좌표를 지정해야한다.
소켓은 좌표 변수로 보면 된다.
생성한 소켓에 Add Preview Asset 을 추가하면 미리보기를 알 수 있다.
이제 그걸 통해서 좌표를 수정하면 된다. 이용도로 사용하는거임.
그리고 무기 클래스를 만들어야 한다.
이번엔 가징 기초 클래스인 AActor 로 만들자.
1 2 3 4 5 6 | public: UPROPERTY(VisibleAnywhere, Category = Weapon) class UCapsuleComponent* SwordCollision; UPROPERTY(VisibleDefaultsOnly, Category = Weapon) class USkeletalMeshComponent* SwordMesh; | cs |
1 2 3 4 5 6 7 8 9 10 11 12 | SwordMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("SwordMesh")); RootComponent = SwordMesh; static ConstructorHelpers::FObjectFinder<USkeletalMesh> SK_Blade_Glimmer(TEXT("SkeletalMesh'/Game/InfinityBladeWeapons/Weapons/Blade/Swords/Blade_DragonSword/SK_Blade_DragonSword.SK_Blade_DragonSword'")); //ConstructorHelpers 로 오브젝트를 들고올 땐 static 으로 공유할 수 있게 하는게 일반적 //ConstructorHelpers 엔 ClassFinder 랑 ObjectFinder 가 있는데 에셋의 형 정보가 전자, 에셋의 내용이 후자 //ConstructorHelpers 는 엔진 초기에 사용할 에셋이 확실히 존재하는지 확인함. 그래서 생성자에서만 가능함 SwordMesh->SetSkeletalMesh(SK_Blade_Glimmer.Object); SwordCollision = CreateDefaultSubobject<UCapsuleComponent>(TEXT("SwordCollision")); SwordCollision->InitCapsuleSize(30.0f, 50.0f); SwordCollision->AttachToComponent(SwordMesh, FAttachmentTransformRules::KeepRelativeTransform, "CapsuleSocket"); | cs |
기본 충돌체와 스켈레톤 메시를 생성하자.
아래 구현부를 생성자에 넣자.
위에선 이미 있는 메시를 생성한 스켈레톤 메시에 연결까지 한다.
1 2 | UPROPERTY(EditDefaultsOnly, Category = Weapon) TSubclassOf<class AMySword> SwordClass; | cs |
1 2 3 4 5 6 7 8 | void AMartin::SpawnDefaultWeapon() { FActorSpawnParameters SpawnInfo; SwordClass = AMySword::StaticClass(); AMySword* DefaultWeapon = GetWorld()->SpawnActor<AMySword>(SwordClass, SpawnInfo); DefaultWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform, "Weapon_Socket"); } | cs |
그리고 위 함수를 생성해서 우리의 주인공 클래스에 무기를 주자.
위 함수는 생성자가 아니라 BeginPlay() 에서 호출해야한다.
다른 클래스가 준비되어 있지 않을 수도 있고 그렇기 때문이다.
이렇게 하고 실행해보면 무기를 들고 있는걸 알 수 있다.
때리는 동작도 해보자.
1 2 3 4 5 6 7 8 9 | UFUNCTION(BlueprintCallable, Category = "Player Actions") void OnAttack(); UFUNCTION(BlueprintCallable, Category = "Player Actions") void OnPostAttack(); //is the player attacking right now UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Player Attributes") bool IsAttacking; | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 | void AMartin::OnAttack() { if (IsControlable) { //BluePrint 에서 써먹을 변수임 IsAttacking = true; } } void AMartin::OnPostAttack() { IsAttacking = false; } | cs |
어택 부분을 추가하자.
그리고 애니메이션 블루프린트로 돌아와서
is Attacking 변수를 추가하고, 함수를 위처럼 만들고, 이벤트 그래프 맨 마지막에 추가해주자.
그럼 is Attacking 변수는 계속 업데이트 될 것이다.
그것에 맞추어 애니메이션 그래프도 수정하면 됨.
아, 그리고 하기전에 Attack Input 도 이동이나 점프처럼 매핑해주자.