Unity3d 运行时获取 exitTime等状态机过度的参数

文章目录

问题

想获取状态过渡时的一些参数设置,可以使用 AnimatorController 类。因为 AnimatorController 在编辑器类 UnityEditor.Animations 的命令空间下,运行时不能引用,怎么处理?
在这里插入图片描述

解决

因为状态机的这些过渡参数,运行之后基本不会改变,unity也只提供了很有限的 api 修改,因此可以打包前,使用 AnimatorController 将需要的参数读取,并写入文件,供运行时使用。

比如,获取下面从 Part1 -> Part2 的运行时间:

在这里插入图片描述

using UnityEditor;
using UnityEditor.Animations;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;

public class MeteorHammerSkillStateProcessor: Editor, IPreprocessBuildWithReport
{
    
    
    public int callbackOrder {
    
     get; }
    
    [MenuItem("AnimatorUtil/OutputMeteorSkillTime")]
    public static void WriteSkillClipTime()
    {
    
    
        var controller = AssetDatabase.LoadAssetAtPath<AnimatorController>("Assets/#C2_Animations/Play/Configure/Robot.controller");
        
        var _meteorSkillAnimatorStatePart1 = GetAnimationState(controller, "MeteorHammerSkill_Part1");
        var _meteorSkillAnimatorStatePart2 = GetAnimationState(controller, "MeteorHammerSkill_Part2");
        var _meteorSkillAnimatorStatePart3 = GetAnimationState(controller, "MeteorHammerSkill_Part3");
        var _meteorSkillAnimatorStatePart4 = GetAnimationState(controller, "MeteorHammerSkill_Part4");
        
        float time = 0f;
        
        if (_meteorSkillAnimatorStatePart1.speed <= 0
            || _meteorSkillAnimatorStatePart2.speed <= 0
            || _meteorSkillAnimatorStatePart3.speed <= 0
            || _meteorSkillAnimatorStatePart4.speed <= 0)
        {
    
    
            return;
        }
        
        // TODO : 这里未考虑到 animator.speed 的值(默认 state的speed 运行时也不改变),如果运行时,animator.speed != 1, 需要将
        // 获取的 clipTime 再除以 animator.speed    
        float clip1Time = GetClip("MeteorHammerSkill_Part1", controller).length / _meteorSkillAnimatorStatePart1.speed 
                          * (_meteorSkillAnimatorStatePart1.transitions[0].exitTime - 0);
        float clip2Time = GetClip("MeteorHammerSkill_Part2", controller).length / _meteorSkillAnimatorStatePart2.speed
                         * (_meteorSkillAnimatorStatePart2.transitions[0].exitTime - _meteorSkillAnimatorStatePart1.transitions[0].offset);
        float clip3Time = GetClip("MeteorHammerSkill_Part3", controller).length / _meteorSkillAnimatorStatePart3.speed
                         * (_meteorSkillAnimatorStatePart3.transitions[0].exitTime - _meteorSkillAnimatorStatePart2.transitions[0].offset);
        float clip4Time = GetClip("MeteorHammerSkill_Part4", controller).length / _meteorSkillAnimatorStatePart4.speed
                         * (_meteorSkillAnimatorStatePart4.transitions[0].exitTime - _meteorSkillAnimatorStatePart3.transitions[0].offset);
        
        Debug.Log($"{
      
      clip1Time}, {
      
      clip2Time}, {
      
      clip3Time}, {
      
      clip4Time}, total {
      
      clip1Time + clip2Time + clip3Time + clip4Time}");
    }
    
    public void OnPreprocessBuild(BuildReport report)
    {
    
    
        // AnimatorController 在运行时不可引用。可以在打包前,将需要的参数写入 ScriptableObject 中,在运行时读取。
#if WRITE_METEOR_SKILL_TIME
        WriteSkillClipTime();
#endif
    }
    
    public static AnimationClip GetClip(string clip, AnimatorController controller)
    {
    
    
        AnimationClip[] tAnimationClips = controller.animationClips;
        if (null == tAnimationClips || tAnimationClips.Length <= 0) return null;
        AnimationClip tAnimationClip;
        for (int tCounter = 0, tLen = tAnimationClips.Length; tCounter < tLen; tCounter++)
        {
    
    
            tAnimationClip = controller.animationClips[tCounter];
            if (null != tAnimationClip && tAnimationClip.name == clip)
                return tAnimationClip;
        }
        return null;
    }

    public static AnimatorState FindAnimatorState(AnimatorStateMachine stateMachine, string stateName)
    {
    
    
        for (int i = 0; i < stateMachine.states.Length; i++)
        {
    
    
            if (stateMachine.states[i].state.name.Equals(stateName))
            {
    
    
                return stateMachine.states[i].state;
            }
        }
    
        for (int i = 0; i < stateMachine.stateMachines.Length; i++)
        {
    
    
            var child = stateMachine.stateMachines[i];
            var state = FindAnimatorState(child.stateMachine, stateName);
    
            if (state)
            {
    
    
                return state;
            }
        }
    
        return null;
    }
    
    public static AnimatorState GetAnimationState(AnimatorController controller, string stateName)
    {
    
    
        AnimatorStateMachine stateMachine = controller.layers[0].stateMachine;
        
        return FindAnimatorState(stateMachine, stateName);
    }
}

猜你喜欢

转载自blog.csdn.net/WGYHAPPY/article/details/129820071