본문 바로가기

프로젝트/Pollute

플레이어 블렌드 스페이스 변경 & 속도 동기화 - 스테미나

블렌드 스페이스

사람 캐릭터의 움직임을 좀 더 자연스럽게 바꾸기 위해 블렌드 스페이스를 추가하였다.

1인칭 게임을 제작 중이기 때문에 Strafe 형식으로 만들었다.

 

@ . 리플리케이트를 이용한 동기화라면 Server 에서 변수나 객체를 바꾸어주어야한다.

@ . 액터의 RPC 호출에 가장 중요한 것은 Owner 이다. 그리고 소유권을 가질 수 있냐이다.

 

속도 동기화

속도 동기화 시 설계가 다른 방법이 충분히 있을 것 같긴한데 일단 구현한대로 두어야할듯.

 

Replicated : << 를 이용한 동기화를 원한다면 서버에서 값 변경을 시켜줘야 관찰중인 모든 클라에 동기화 되어진다.

 

RPC << 사용 시 현재 호출하는 객체가 어떤 클라/서버의 객체인지 확실히 이해해야한다.

 

구현된 속도 동기화 : MaxWalkSpeed 를 조절하고 모든 서버/클라가 이를 동기화한다.

기본 움직임에는 WalkSpeed 값으로 설정되지만 Shift 를 누르면 RunSpeed 로 설정 되어야 한다.

 

기본적으로 MaxWalkSpeed 가 Replicated 되어 있지 않다.

따라서 이 값의 변경은 따로 ServerRPC 로 진행하고 NetMulticast 로 모든 클라에게 동기화하는 방식을 사용했다.

 

-------------------------------------------------------------------------------------------------------

Shift 를 이용한 달리기 방식을 바꾸었다.

-------------------------------------------------------------------------------------------------------

다음에는 Toggle 에 미리 WalkSpeed 를 바꾸고 방향에 따른 계산은 따로 처리하는 방식을 이용해봐야겠다. 뭔가 프레임별로 ServerRPC_SetRunning 호출하니 별로이다.

 

구현

 

이전 방식 : Shift 를 이용한 토글 형식의 달리기. ShiftOn - 달리기 , Off - 걷기

 

바꾼 방식 : Shift 를 누를때 달리기 때면 다시 걷기

 

달리기 bool 변수 값을 설정한다. 변수는 Replicated 되어 있어 동기화된다.

 

이제 움직일 때 변수가 true 라면 달리기 속도가 적용되면서 동시에 스테미나 줄어든다.

void ALCU_PlayerCharacter::Move(const FInputActionValue& Value)
{
    // input is a Vector2D
    FVector2D MovementVector = Value.Get<FVector2D>();
    
    if (Controller != nullptr)
    {
        // 입력 방향 벡터 가져오기
        const float MoveForwardValue = MovementVector.Y;
        const float MoveRightValue = MovementVector.X;

        // 달리기 중 스테미나가 전부 달면 특정 시간이 지날동안 달리기가 적용되지 않는다.
        if(IsLocallyControlled())
        {
            if (MoveForwardValue > 0 && bIsRunning)
            {
                if(CurrentStemina > 0)
                {
                    CurrentStemina -= GetWorld()->GetDeltaSeconds() * 3.2f;
                    if(CurrentStemina <= 0 )
                    {
                        CurrentStemina = 0;
                        bCanRecoverStamina = false;
                        FTimerHandle StaminaTimerHandle;
                        GetWorld()->GetTimerManager().SetTimer(StaminaTimerHandle,this, &ALCU_PlayerCharacter::SetCanRecoverStemina,3.f);
                        ServerRPC_SetRunning(false);
                    }
                }
            }

             // RPC 를 이용해 모든 클라에서 해당 객체의 이동 속도를 조절해준다.
            ServerRPC_UpdateSpeed(MoveForwardValue, MoveRightValue);
        }
        
        // 방향 벡터 계산
        const FRotator Rotation = Controller->GetControlRotation();
        const FRotator YawRotation(0, Rotation.Yaw, 0);

        const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
        const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

        // 입력 벡터를 기반으로 이동 적용
        AddMovementInput(ForwardDirection, MoveForwardValue);
        AddMovementInput(RightDirection, MoveRightValue);
    }
}