a15714ab041eb360be3335625683746f0153452ed6a7eb89d63667f7991ccd6e161175db883d1ce39d629419f231


이것은 내가 Sketchfab을 통해 우주갓겜 브롤스타즈에서 긴빠이쳐온 악어소녀 알리다.






7dec9e74b5826ef739ec8efb479f2e2d51697e5ba056c84422b7a150


오늘 나는 이 존나 커여운 알리의 머리카락에 엘라스틴을 존나 때려 부어서





2193fb00b1d71af55be9ecb011ff0f0c7173a0e6d41ba30954064fc25143bbd5574ead1cc70f8b0b3efeebca21888d6c55d897aba2a773f1486a21b0bedd2b1acae643b4a3c93bacc96e9cde61ca281c8bb253a1513cade8c3d4b2198dd0756c57ea7922f4aa041eef377595f21701d3765624ea33ed85cc22a58eb8ec7b3ce7777f44fd5989caed8d2f58f2a61db0046e23c926dce10e38e2e6c00ebac417062845f6037613


이렇게 만들어 볼 것이다.










a15714ab041eb360be3335625683746f0153452ed6a7eb89d63667f69d11cd6ea211165a0c8602f180a04a7cba5d70


당연한 말이지만 우린 Unity에서 제공하는 Hair System 같은 걸 쓰는 게 아니고

그냥 모델에 박혀있는 머리카락을 움직이는 것이기에 툼레이더 마냥 만드는 것은 불가능하다.


그럼 뭐 어떻게 만들거냐고?








a15714ab041eb360be3335625683746f0153452ed6a7eb89d63167f89d11cd6eeee2925bc6d773c93914e11a8115


래그돌 생성 - Unity 매뉴얼



8


뭐 잘은 모르겠지만 Unity에서는 Ragdoll이라는 기능을 제공하니 그걸 갖다 쓰면 되지 않을까?


캐릭터의 머리카락에 래그돌을 박아 넣는 것은 아주 간단하다.





a15714ab041eb360be3335625683746f0153452ed6a7eb89d63160f6981ccd6e49da004699ed80ecb835f1d344b6


1. 알리를 들어서








a15714ab041eb360be3335625683746f0153452ed6a7eb89d63161f29f13cd6ef076e502d73433b8ee0a326d42fc


a15714ab041eb360be3335625683746f0153452ed6a7eb89d63161f59c15cd6e39454bd4d9f8d5fb72c5f4fea373


개지랄하지말고 각 머리카락 본에 한땀한땀 Rigidboy와 Collider, Character Joint를 박아넣어면 된다.

Ragdoll Builder 백날 써도 머리카락 같은 데 있는 본에는 안 붙으니까 그냥 노가다해라.


Character Joint에서 Connected Body 제대로 붙이는 거 잊지 말고, 저거 제대로 안 붙이면 Ragdoll 되자마자 똑 떨어져 나간다.






아무튼 잘 붙였으니 이대로 플레이 해보면???



5


애1미 시2발 ^^



모델이 구린건지, 아니면 animator가 붙어 있는 곳에 ragdoll을 붙이면 대참사가 열리는 건지,

정확한 이유는 모르겠으나 우리가 원하는 형태의 동작을 하질 않는다.



그렇다면 우리는 이걸 어떻게 처리해야 우리가 원하는 동작을 하게 만들 수 있을까?







3eacc527f6da16b57aadd3a115d96a3a8e9dada217a6357a99bfea5463d7d0


이럴 때 도움이 되는 것이 UnityJigglePhysics 에셋이다.

GitHub - naelstrof/UnityJigglePhysics: A unity addon for adding stretchy bouncy physics to bones and meshes. 



우리는 Ragdoll를 쓰는 대신 적절한 외부 에셋을 활용해서 문제를 해결회피하도록 할 것이다






a15714ab041eb360be3335625683746f0153452ed6a7eb89d63161f99c1ccd6ef92e7a7828707f4d8c3f7ccb364c


a15714ab041eb360be3335625683746f0153452ed6a7eb89d63161f99d13cd6e71a2f75f98baacba2679921eb2


아까의 알리 모델로 돌아와서 JiggleRigBuilder 스크립트를 적당한 데에 넣어주고

Jiggle Rigs를 하나 추가, Root Transform으로 머리카락 본의 시작점을 지정해주고 마지막 Setting 값을 적당히 만져주면???????









1


머리카락이 꽤나 그럴싸하게 움직이기 시작한다.


머리카락이 다소 중력을 거스르고 위로 솟구쳐진 느낌이 있긴 하지만 이건 원본 모델링이 이 모양이라 어쩔 수 없는 부분이니 패스









다만 이럴 경우 문제가 하나 있는데 animator를 꺼서 Ragdoll이 되었을 때


머리카락이 자연스럽게 떨어지지 않고 공중부양을 시전한다는 문제가 생긴다.







using System.Collections.Generic;
using JigglePhysics;
using UnityEngine;
using UnityEngine.InputSystem;

public class AnimatorRagdollController : MonoBehaviour
{
    [SerializeField] private Animator animator;
    [SerializeField] private JiggleRigBuilder[] jiggleRigBuilder;
    public List<Rigidbody> detectedRigidbodies;

    [Space(10f)]
    [SerializeField] private bool isRagdollMode;

    private bool lastRagdollMode;

    #region Initialize
    private void Awake()
    {
        detectedRigidbodies = new List<Rigidbody>();

        RecursionFindAllRigidbody(transform);
    }

    private void Start()
    {
        SetRagdollMode(isRagdollMode);
    }

    private void RecursionFindAllRigidbody(Transform tf)
    {
        // 현재 트랜스폼에서 Rigidbody 컴포넌트를 찾아 등록
        if (tf.TryGetComponent(out Rigidbody rigidbody))
        {
            detectedRigidbodies.Add(rigidbody);
        }

        // 신나는 재귀
        int childCount = tf.childCount > 0 ? tf.childCount : 0;

        for (int i = 0; i < childCount; i++)
        {
            RecursionFindAllRigidbody(tf.GetChild(i));
        }
    }
    #endregion

    private void Update()
    {
        if (isRagdollMode != lastRagdollMode)
        {
            SetRagdollMode(isRagdollMode);
        }
    }

    public void SetRagdollMode(bool set)
    {
        animator.enabled = !set;

        foreach (var jr in jiggleRigBuilder)
        {
            jr.enabled = !set;
        }

        foreach (var rd in detectedRigidbodies)
        {
            rd.isKinematic = !set;
        }

        lastRagdollMode = set;
    }

    #region InputSystem
    public void OnRagdoll(InputValue input)
    {
        isRagdollMode = !isRagdollMode;
    }
    #endregion
}


이것을 해결하기 위해 스크립트를 날림으로 작성해보았다.


아주 간단한 동작을 하는 스크립트인데

한 줄 요약으로 Ragdoll 모드로 돌입함과 동시에 JiggleBoneBuilder를 꺼주고 Rigidbody를 활성화(?) 시키는 스크립트다.





요 스크립트를 오브젝트에 넣어주고 animator와 JiggleBoneBuilder를 등록해주면


요렇게 Ragdoll 모드에 들어가는 것과 동시에 JiggleBoneBuilder가 꺼지면서 머리카락이 ?연스럽게 움직이는 것을 볼 수 있다.


머리카락이 자연스럽게 움직이는 게 아니라 ?연스럽게 움직이고 있는데 이걸 해결하는 방법은 아주 간단하다.





a15714ab041eb360be3335625683746f0153452ed6a7eb89d63166f39e1dcd6e6ab2dab39f00f4ae0fe4706471


각 머리카락 본에 부착된 CharacterJoint 컴포넌트에 가서 Enable Projection을 활성화시키면 된다.


저게 무슨 기능이냐고? 실제 물리 연산을 좆까고 모델의 움직임을 무조건 설정된 한계치 밑으로 고정시켜버리는 기능이다.


최후의 최후에만 써야 하는 기능이라고 하는데 내 경우에는 Limit Spring을 백날 만져봐야 1도 영향이 없어서 그냥 썼다.









25


아무튼 이 기능까지 활성화시켜주면 Animator를 통해 움직이는 것은 물론 Ragdoll이 되었을 때도 완벽하게 자연스러운 머리카락의 움직임을 구현할 수 있다.