Get it on Google Play


Wm뮤 :: 유니티 애니메이터 관련

블로그 이미지
가끔 그림그리거나 3D모델링하거나
취미로 로봇만드는
퇴직한 전자과 게임프로그래머
2020.3.48f1 , 2022.3.6f1 주로 사용
모카쨩
@Ahzkwid

Recent Comment

Archive


2021. 2. 5. 13:53 Unity

끄면 애니메이션 전환(트랜지션)이 즉시 이루어진다

 

 

다음 트랜지션에 의해 해당 트랜지션이 강종될수있다

 

 

 

OR트랜지션

 

 

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

 

 

아무런 조건없는데 무한루프돌때

 

 

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

update보다 조금 늦게 호출

 

 

 

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

Sync예제

표정등을 혼합할때 사용한다

 

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

파라미터로 애니메이션 속도 조정

이동속도같은걸 맞출때 좋음

 

 

 

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

체크를 해제하면 애니메이션을 리셋후 적용시키지 않고 현재상태에서 덧씌운다

 

 

 

코드들

 

 

 

애니메이션 변경시 호출

using UnityEngine;

public class ChangeStateChecker : StateMachineBehaviour
{
    override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        Debug.Log("On State Enter");
    }

    override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        Debug.Log("On State Exit");
    }

    override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        Debug.Log("On State Update");
    }

    override public void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        Debug.Log("On State Move");
    }

    override public void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        Debug.Log("On State IK");
    }
}

 

애니메이션 정지 (신형)//아마도

한번도 쓸일이 없었다

Animator animator;
AnimationState animationState;
animator.StopPlayback(); //정지(아마도)

 

 

애니메이터 조작 세가지

가급적 파라미터 조작만 쓰자

GetComponent<Animator>().Play("StateName"); //State이동(실행)

animator.Play("StateName",-1,0); //재생취소후 재생

characterSpine.GetComponent<Animator>().SetBool("ParameterName", boolValue); //파라미터 bool 설정

 

 

 

애니메이션 재생 (구형)

Animation animation;
AnimationClip animationClip;
animation.Play(animationClip.name);

 

특정시간부터 재생

var animator = coordinator.animator;
var layer = animator.GetLayerIndex("Base Layer");
var animatorStateInfo = animator.GetCurrentAnimatorStateInfo(layer);
var time = 1.2f;
var normalizedTime = time / animatorStateInfo.length;
animator.Play(animatorStateInfo.shortNameHash, layer, normalizedTime);

 

 


적용예제

void JumpAnimation(float jumpTime)
{
    var layer = animator.GetLayerIndex("Base Layer");
    var animatorStateInfo = animator.GetCurrentAnimatorStateInfo(layer);
    animator.Play(animatorStateInfo.shortNameHash, layer, jumpTime / animatorStateInfo.length);
}

 

 

애니메이터 현재 재생시간


var layer = animator.GetLayerIndex("Base Layer");
var animatorStateInfo = animator.GetCurrentAnimatorStateInfo(layer);
float time = animatorStateInfo.length * animatorStateInfo.normalizedTime;//(애니메이션 길이) * (0~1시간)

 

 

애니메이터 구간 점프

void Update()
{

    var layer = animator.GetLayerIndex("Base Layer");
    var animatorStateInfo = animator.GetCurrentAnimatorStateInfo(layer);
    float time = animatorStateInfo.length * animatorStateInfo.normalizedTime;//(애니메이션 길이) * (0~1시간)

    float jumpStartTime = 5;
    float jumpEndTime = 10;
    if ((time > jumpStartTime) && (time < jumpEndTime))
    {
        animator.Play(animatorStateInfo.shortNameHash, layer, jumpEndTime / animatorStateInfo.length);
    }
}

 

 

 

현재 트랜지션이 지정값과 맞는지 불러옴

animator.GetCurrentAnimatorStateInfo(layerIndex:0).IsName("스테이트이름")

 

 

레이어 혼합강도 설정

var weight = 1f;
var lerpSpeed = 1f;
var layer = animator.GetLayerIndex("Base Layer") ;
animator.SetLayerWeight(layer, Mathf.Lerp(animator.GetLayerWeight(layer), weight, lerpSpeed));

 

 

 

애니메이터 보호장치, 근데 이딴거 쓰지말고 아래 이미지를 써라

public class AnimationStateProtector : MonoBehaviour
{
    Animator animator;

    int lastState = 0;
    int enableCount = 0;


    void Start()
    {
        animator = GetComponent<Animator>();
    }
    void Update()
    {
         var animatorStateInfo =  animator.GetCurrentAnimatorStateInfo(0);
        lastState = animatorStateInfo.shortNameHash;
    }
    void OnEnable()
    {
        if (enableCount!=0)
        {
            animator.Play(lastState);
        }
        enableCount++;
    }
}

 

디버그모드에서 켜면 보인다. 위와 동일한 기능임

 

 

 

 

 

 

애니메이터 스테이트 변동 체크

void OnEnable()
{
    StartCoroutine(CharacterAnimatorStateChengedChecker());
}

[System.Serializable]
public class AnimatorStateInfoEvent : UnityEngine.Events.UnityEvent<AnimatorStateInfo> { }


public AnimatorStateInfoEvent OnAnimatorStateChengedEvent;
public IEnumerator AnimatorStateChengedChecker()
{
    while (true)
    {
        var fullPathHashPrevious = GetComponent<Animator>().GetCurrentAnimatorStateInfo(layerIndex:0).fullPathHash;
        yield return new WaitUntil(() => GetComponent<Animator>().GetCurrentAnimatorStateInfo(layerIndex: 0).fullPathHash != fullPathHashPrevious);

        OnAnimatorStateChengedEvent.Invoke(GetComponent<Animator>().GetCurrentAnimatorStateInfo(layerIndex: 0));
    }
}

 

 

 

 

 

부위 가져오기

var transform=Animator.GetBoneTransform(HumanBodyBones.Hips);

 

 

 

 

BlendTree를 읽어서 인스펙터에 업데이트


    public List<Emote> emotes;
    public Animator animator;
    [System.Serializable]
    public class Emote
    {
        //public Animation animation;
        public AnimationClip animation;
        public Sprite icon;
        public float threshold;
    }
    public AnimationClip[] EmoteAnimations
    {
        get
        {
            return emotes.ConvertAll(x=>x.animation).ToArray();  
        }
    }
#if UNITY_EDITOR
    public UnityEditor.Animations.AnimatorController animatorController;
    [ContextMenu("ImportFromBlendTree")]
    public void ImportFromBlendTree()
    {
        var layerIndex = 0;
        var stateName = "Emote";
        {
            //var animatorController = animator.runtimeAnimatorController as UnityEditor.Animations.AnimatorController;
            var layer = animatorController.layers[layerIndex];
            var states = layer.stateMachine.states;
            var state = System.Array.Find(states, x => x.state.name == stateName);
            //var blendTrees = System.Array.ConvertAll(states, state => state.state.motion as UnityEditor.Animations.BlendTree);
            //blendTrees = System.Array.FindAll(blendTrees, blendTree => blendTree != null);
            var blendTree = state.state.motion as UnityEditor.Animations.BlendTree;
            var motions = System.Array.ConvertAll(blendTree.children, children => children.motion);

            for (int i = 0; i < motions.Length; i++)
            {
                var motion= motions[i];
                var animation = motion as AnimationClip;
                var emoteIndex = emotes.FindIndex(x => x.animation == animation);
                if (emoteIndex == -1)
                {
                    var emote = new Emote();
                    emote.animation = animation;
                    emoteIndex = emotes.Count;
                    emotes.Add(emote);
                }
                emotes[emoteIndex].threshold = (float)i/motions.Length;
            }
        }
        UnityEditor.EditorUtility.SetDirty(this);
    }
#endif

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

창 위치가 우주로 날아가서 개빡칠때

NullReferenceException: Object reference not set to an instance of an object
UnityEditor.Graphs.AnimationStateMachine.Graph.GenerateConnectionKey

뜨면서 안 되는데

걍 오류난거니 빠른 리셋이 답이다

 

 

 

 

 

 

 

 

 

 

 

'Unity' 카테고리의 다른 글

캐릭터 포즈 망가졌을때  (0) 2021.02.06
안드로이드 빌드관련  (0) 2021.02.03
디버그방법모음  (0) 2021.02.02
posted by 모카쨩

  • total
  • today
  • yesterday

Recent Post

저사양 유저용 블로그 진입