kingBook

导航

Unity Animator

播放控制

Animator animator;

animator.speed=0;//停止播放
animator.speed=-1;//倒放

animator.Play("stateName",0,0);//播放指定状态(stateName是Animator窗口里各个状态的名称)

跳到指定帧,并停止

Animator animator;

animator.speed=0;//停止播放

AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
AnimatorClipInfo clipInfo = animator.GetCurrentAnimatorClipInfo(0)[0]; // 注意:'动画剪辑' 与 '状态(stateName是Animator窗口里各个状态的名称)' 对应

//AnimatorOverrideController overrideController = new AnimatorOverrideController(animator.runtimeAnimatorController);
// 通过子符串获取AnimationClip,注意并不是Animator窗口里各个状态的名称,而是在Animator窗口中选择的状态在Inspector面板的motion属性显示的名称
//AnimationClip clip = overrideController["motionName"];

//float stateSpeed = stateInfo.speed;

float clipLength = clipInfo.clip.length;
float frameRate = clipInfo.clip.frameRate;

float normalizedTime = 5f / frameRate / clipLength; // 跳到第5帧
animator.Play("stateName", 0, normalizedTime); // 播放指定状态(stateName是Animator窗口里各个状态的名称)

/*
float totalFrames = clipInfo.clip.length * clipInfo.clip.frameRate; // 动画剪辑的总帧数

void Update(){
	float currentNormalizedTime = stateInfo.normalizedTime; // 播放头的所在的单位化时间位置
	float currentTime = stateInfo.normalizedTime * clipInfo.clip.length; // 播放头的所在的时间位置
	float currentFrameNO = stateInfo.normalizedTime * totalFrames; // 播放头所在的帧
	
	Debug.Log($"currentNormalizedTime:{currentNormalizedTime}, currentTime:{currentTime}, currentFrameNO:{currentFrameNO}");
}
*/

动画播放到指定时间做某事
方法1: 在动画剪辑指定的时间里,添加事件函数
注意:

  • 函数所在的脚本和Animator 组件必须绑定到同一个GameObject
  • 在Animator里如果两个动画存在过渡,请注意动画的过渡时间,如果某个时间处于过渡时间内将不会收到事件,根据下图的调整 attack 动画才能收到播放完成事件,使用代码添加事件时请不要添加到时间的最末尾,否则在不同设备上依旧会出现末尾时间处的事件不触发的问题。
using UnityEngine;
using System.Collections;

public class TestAnimationEvent : MonoBehaviour {

    private void Awake () {
        Animator animator = GetComponent<Animator>();//Animator组件和此脚本必须绑定到同一个GameObject

        AnimatorOverrideController overrideController = new AnimatorOverrideController(animator.runtimeAnimatorController);
        //通过子符串获取AnimationClip,注意并不是Animator窗口里各个状态的名称,而是在Animator窗口中选择的状态在Inspector面板的motion属性显示的名称
        AnimationClip clip = overrideController["CINEMA_4D___"];

        //在动画指定的时间,添加事件
        AnimationEvent onCompleteEvent = new AnimationEvent();
        onCompleteEvent.objectReferenceParameter = this;
        onCompleteEvent.functionName = nameof(OnAnimationClipComplete);
        onCompleteEvent.time = clip.length;//clip.length动画长度,单位为秒。这里表示在结束时添加事件
        clip.AddEvent(onCompleteEvent);
    }

    //注意:参数类型是UnityEngine.Object不是object
    private void OnAnimationClipComplete (UnityEngine.Object objectReference) {
        //注意:当内存中拥有多个当前类的实例时,将会调用多次此函数,使用objectReferenceParameter属性传递this区分
        if (objectReference != this) return;

        Debug.Log("onShakeAnimComplete;");
    }
}

方法2: 通过AnimatorStateInfo.normalizedTime判断播放到的时间

using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour {

    public Animator animator;

    private void Awake () {
        animator.Play("attack");
        InvokeRepeating(nameof(CheckStateComplete), 0.02f, 0.02f);
    }

    private void CheckStateComplete () {
        AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
        if (stateInfo.IsName("attack")) {
            //normalizedTime:表示动画的标准化时间,区间:[0,1]
            if (stateInfo.normalizedTime >= 1.0f) {
                OnStateComplete();
                CancelInvoke(nameof(CheckStateComplete));
            }
        }
    }

    private void OnStateComplete () {
        Debug.Log("OnStateComplete");
    }

    private void OnDestroy () {
        CancelInvoke("checkStateComplete");
    }
}

posted on 2019-08-30 16:08  kingBook  阅读(1570)  评论(0编辑  收藏  举报