반응형

 

 

 

 

VRM을 언리얼로 Import하면 리타게터가 자동으로 생성되지만 데이터가 일부 손실된다.

그렇기 때문에 언리얼 Third person template의 애니메이션이 정상적으로 리타게팅 되지 않는다.

 

위와 같이 리타게터 파일을 열어서 애니메이션을 실행해보면 하반신이 마비된것을 확인할 수 있다.

이 현상은 단순히 IK Rig 파일에 해당 체인이 존재하지 않아서 발생하는 문제이다.

 

 

 

 

해결방법

VRM을 언리얼로 임포트하면 같이 생성되는 IK Rig 파일이 있을건데 열어서 체인을 생성해주면 된다.

기본적으로 Mannequin 모델의 애니메이션을 리타게팅할 것이므로, Mannequin의 IK Rig파일의 체인 목록과 비교한 뒤, 없는 부분을 추가해서 Start boneEnd bone을 설정해주면 된다.

 

1. 체인 생성

IK Rig파일을 열어서 Add New Chain버튼을 눌러서 체인을 생성해준다.

필자의 기준으로는 다리가 없었으므로 RightLeg와 LeftLeg 체인을 생성해서 본을 설정해줬다.

 

2. 본 설정

이 부분은 아마 VRM 모델마다 다를거기 때문에 각자 모델을 확인한 뒤, 다리 시작부 부터 발 까지 설정해준뒤 저장하자.

 

3. 리타게터에서 소스체인 설정해주기

리타게터를 보면 위와 같이 타겟 체인이 생겨있고 소스 체인에는 None으로 표시되어 있다.

소스 체인의 드롭다운 메뉴를 열어서 각자 위치에 맞는 체인을 설정해준 뒤 저장, 애니메이션을 확인해보자.

 

 

 

결과

 

 

 

 

 

반응형
반응형

 

 

 

유니티에서 Export한 VRM을 언리얼로 Import 했을 때, BlendShape가 비정상적으로 작동하는 에러가 있었다.

BlendShape를 조절하면 모델에 변화는 일어나는데 해당 키에 해당하는 Vertex가 앞뒤로만 움직이는 기현상이 발생했다.

위 사진과 같이 오작동이 일어난다. VertCount 수가 잡히는거 보면 데이터도 잡혀있기 때문에 혹시 몰라 Mesh를 확인해봤지만..

 

Mesh역시 이상없이 잡혀있다.

UniVRM의 다른 최신버전을 구해서 Export하면 정상적으로 움직이긴했지만, 언리얼로 Import하면 쉐이더가 맛이 가버려서 다른방법을 찾아봤다.

 

 

 

 

- 해결방법

방법은 최신버전을 버리는 것.

VRM을 처음다뤄봐서 일단 최신버전만 구성해서 데이터를 Export했더니 최신버전에서 문제가 있는모양이다.

유니티 버전 : 2019.4 LTS

UniVRM : 0.99 이하

위 버전으로 맞춘 뒤, VRM Export한 데이터를 언리얼로 Import하여 BlendShape를 조절하면 정상적으로 작동한다.

 

 

UniVRM v0.99 Github : Releases · vrm-c/UniVRM (github.com)

 

Release v0.99.0 · vrm-c/UniVRM

Unity-2019.4 の最終版です。 次から、最低バージョンを Unity-2020.3 に上げる予定です。 リリース前の動作チェックが Unity-2020.3 になります。 Download for Unity-2019.4.LTS or later UniVRM-0.99.0_f9ee.unitypackage

github.com

 

 

 

 

 

반응형
반응형

 

 

※ 명령패턴 설명

 

명령 패턴 (Command pattern)

1. 명령패턴 (Command pattern) 명령(이동, 점프 등)에 대한 함수를 클래스로 래핑하여 해당 클래스를 객체화 한 것이다. 사용자(캐릭터)를 명령에 대한 매개변수로 만들어 요청을 대기시키거나 로깅

srdeveloper.tistory.com


 

 

 

 

1. 실행 취소 기능

명령 패턴으로 실행 단위를 객체로 만들어두면 손쉽게 실행취소 기능을 구현할 수 있다.

위와 같이 Command 객체에 대한 List를 만들고 추가 명령이 생성되면 List의 맨 끝에 추가한 뒤, 현재 명령으로 기억하면 된다. Undo의 기능만 넣게되면 현재명령은 지워주고 현재 명령을 이전 명령으로 위치를 잡아주면 되고, Redo 기능을 같이 추가하게되면 실행 취소 전의 명령은 그대로 살려주면 될것이다.

 

 

 

2. 예시 코드

2-1) Command(추상 클래스)

public abstract class Command
{
    protected int direction;
    protected Actor actor;

    public abstract void Execute(Actor actor);
    public abstract void ExecuteAxis(Actor actor);
    public abstract void Undo();
}

 

2-2) VerticalCommand(Command 상속)

using UnityEngine;

public class VerticalCommand : Command
{
    public VerticalCommand(Actor actor, int direction)
    {
        this.actor = actor;
        this.direction = direction;
    }
    public override void Execute(Actor actor)
    {
        
    }

    public override void ExecuteAxis(Actor actor)
    {
        actor.MoveTo(new Vector2(0, direction));
    }

    public override void Undo()
    {
        actor.MoveTo(new Vector2(0, -direction));
    }
}

 

2-3) HorizontalCommand(Command 상속)

using UnityEngine;

public class HorizontalCommand : Command
{
    public HorizontalCommand(Actor actor, int direction)
    {
        this.actor = actor;
        this.direction = direction;
    }
    public override void Execute(Actor actor)
    {
        
    }

    public override void ExecuteAxis(Actor actor)
    {
        actor.MoveTo(new Vector2(direction, 0));
    }

    public override void Undo()
    {
        actor.MoveTo(new Vector2(-direction, 0));
    }
}

 

2-4) Actor

using UnityEngine;

public class Actor : MonoBehaviour
{
    private Rigidbody2D rb;

    private void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    public void MoveTo(Vector2 pos)
    {
        rb.MovePosition(rb.position + pos);
    }
}

 

2-5) InputHandler

using System.Collections.Generic;
using UnityEngine;

public class InputHandler : MonoBehaviour
{
    [SerializeField]
    private Actor targetActor;

    private List<Command> commands = new List<Command>();
    private int executionIndex = -1;

    private void Update()
    {
        Command targetCommand = HandleInput();
        if(targetCommand != null && targetActor != null)
        {
            commands.Add(targetCommand);
            executionIndex++;

            targetCommand.ExecuteAxis(targetActor);
        }
    }

    private Command HandleInput()
    {
        if (Input.GetKeyDown(KeyCode.W))
        {
            return new VerticalCommand(targetActor, 1);
        }
        else if (Input.GetKeyDown(KeyCode.S))
        {
            return new VerticalCommand(targetActor, - 1);
        }
        else if (Input.GetKeyDown(KeyCode.A))
        {
            return new HorizontalCommand(targetActor, - 1);
        }
        else if (Input.GetKeyDown(KeyCode.D))
        {
            return new HorizontalCommand(targetActor,1);
        }
        else if(executionIndex >= 0 && Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.X))
        {
            commands[executionIndex].Undo();
            commands.RemoveAt(executionIndex);
            executionIndex--;
        }

        return null;
    }
}

 

※ 위 코드는 Undo의 기능만 구현해서 짠 코드이다.

※ 생성자에 Actor를 인자로 받는 이유는 플레이어만이 아닌 다른 캐릭터에 대한 실행취소도 포함하기 위함이다.

※ 앞선 커맨트 패턴의 게시글의 코드를 재활용해서 짠 코드이므로 Actor에 붙어있는 Rigidbody의 GravityScale의 값을 0으로 설정해야 정상적으로 작동 된다.

 

 

 

3. 실행 확인

 

반응형

'Stack > DesignPattern' 카테고리의 다른 글

명령 패턴 (Command pattern)  (0) 2024.02.23

+ Recent posts