Animation 组件

Animation概述

Animation 组件,Animation类

Animation

//测试的结果是:
//1、特别注意 XXQueue 这样的函数,如果遇到循环播放的动画 WrapMode.Loop ,
因为默认情况 QueueMode.CompleteOthers,所以无法切换到其他动画
//2、如果将动画队列模式设为 QueueMode.PlayNow,那么即使是 循环播放的动画,它也会自身切换自身,从头开始播放
//3、文档中的 Animation.CrossFadeQueue

https://docs.unity3d.com/ScriptReference/Animation.CrossFadeQueued.html


PlayMode 用于动画的播放相关函数,影响其他动画的播放,可以停止同一层、所有层的其他动画

PlayMode.StopSameLayer —— 针对同一层的其他动画(停止、淡出)(这种其他层的动画还可以继续播放)
PlayMode.StopAll —— 针对所有其他动画(停止、淡出)

已经过时的 API 还有一个 AnimationPlayMode ,如今用 PlayMode 代替。
然而,AnimationPlayMode 枚举有三项: Mix、Queue、Stop


public class Animation : Behaviour{}

另外需要关注 —— AnimationState、AnimationClip、

动画系统基于权重,支持 动画混合(blending),添加动画(additive animations),动画融合(mixing),层,以及其他动画播放的控制。

AnimationState 用于切换动画的层,控制播放速度,以及对blending和mixing的直接控制。

Animation 支持枚举器,所以可以写代码如下

public class Example : MonoBehaviour
{
    public Animation anim;   //例子中也从没有出现 Animator、以及动画状态机的概念

    void Start()
    {
        anim = GetComponent<Animation>();
        foreach(AnimationState state in anim)  //看来这个 AnimationState 在旧版本就有了。。。
            state.speed = 0.5f;
    }
}

Animation 属性

Animation 属性名说明
animatePhysics如果设为true,那么动画将会在 FixedUpdate 中循环,这个只有和运动学刚体一起用才有效(bool)
clip默认的动画片段 (AnimationClip)
cullingType控制这个Animation组件的 (AnimationCullingType)
isPlaying这个组件是否正在播放动画,动画播放结束不动了,那也是false (注意还有个 anim.IsPlaying(“xx”))(bool)
localBoundsAABB of this Animation animation component in local space.(Bounds)???
playAutomatically默认的动画片段是否自动播放(bool)
this[string]返回某个名称的动画状态,例如 anim[“walk”] .(AnimationState)
wrapMode循环播放设置,建议是在导入设置中对每一个动画片段的WrapMode单独处理好(WrapMode)

关于 WrapMode
推荐这样用:先在导入设置中设置每一个动画片段的WrapMode,当一个 AnimationState 被创建,它就会有用到的 AnimationClip 的 WrapMode 信息,并且也是可以通过程序来改变的。
如果一个AnimationState的 WrapMode 设为 Default,那么动画系统将会使用 Animation组件的 WrapMode。
.
意思应该就是说,
AnimationClip 的 WrapMode 最先考虑,AnimationState被创建的时候就会用到 AnimationClip的 WrapMode,但是也可以改变。如果 AnimationState 的 WrapMode 为默认,那么就会用到 Animation组件的设置

.

关于 AnimationCullingType,
.
即使逻辑和动画表现分离,也不能随便用,例如一个怪的动画里边有 后撤+突进+攻击,后撤的时候离开屏幕,接着就不会突进了,处理起来还更麻烦
.
AlwaysAnimate 、 BasedOnRenderers
.
When culling is enabled, Unity might stop animating if it thinks that the results of the animation won’t be visible to the user. This could save you some performance if you have things animating outside of the viewport, whose animation is only important when the user can actually see the thing that is being animated. When Animation component is culled it won’t do anything: it won’t update animation states, execute events or sample animations.

Animation 公共方法

Animation 公共方法说明
AddClip给Animation组件添加新动画片段,指定源动画,新名称,如果名称与已有的相同,那么会取代
Blend将某个名称的动画片段在 几秒内(默认0.3秒),改变权重到目标权重(默认1)。。fadeLength 应该是时间吧。。
CrossFade在指定时间内(默认0.3s),指定动画的淡入,其他动画的淡出(同一层/所有)
CrossFadeQueued动画的淡入淡出,特别注意 QueueMode 的设置,默认播放完其他动画才cross fade,然而如果循环播放,那么就相当于动画不会停止,所以也就不会 cross fade。然后如果设置为 QueueMode.PlayNow ,那么还可以自身cross fade到自身(似乎是unity内部会复制一份的意思)
GetClipCount获取这个Animation组件的动画片段数量
isPlaying是否正在播放某个动画
Play播放指定动画,没有任何混合
PlayQueued一般 QueueMode.CompleteOthers 等其他动画播完再播指定动画,没有淡入淡出,同样注意 循环播放的动画切换到指定动画,必须 QueueMode.PlayNow
RemoveClip从Animation组件的动画列表中移除指定动画片段,以及基于此动画片段的动画状态
Rewind就是将动画从头开始播放,不管是不是循环播放的,另外注意如果动画播放结束再执行 Rewind 是无效的
Sample应该是设置好一个动画状态,然后采用一次,效果貌似是那个动画状态的参数应用到其他动画状态?????
Stop可以停止指定动画,也可以停止该组件所有动画,注意Stop的同时也就Rewind到开始,“冻结”效果,anim.isPlaying ==false
//给组件添加新的动画片段,指定源动画片段实例,新动画片段的名称,这种是不会保存到FBX里边的,只会运行时有效
public void AddClip(AnimationClip clip, string newName); 
//这个也是给组件添加新的动画片段,并且指定新片段的名称、第一帧、结束帧取自源动画片段的哪一帧,是否开始和结束循环
public void AddClip(AnimationClip clip, string newName, int firstFrame, int lastFrame, bool addLoopFrame = false); 
//将指定名称的动画片段,过渡到指定的权重,fadeLength 是时间???
public void Blend(string animation, float targetWeight = 1.0F, float fadeLength = 0.3F); 
public void CrossFade(string animation,                 //目标动画名称
                      float fadeLength = 0.3F,          //时间,默认0.3s
                      PlayMode mode = PlayMode.StopSameLayer);   //默认是同个layer的动画 fade out

//PlayMode 用于 Animation.Play  Animation.CrossFade  决定处理的是同一层的动画还是所有动画
//PlayMode.StopSameLayer —— 针对同一层的动画(停止、淡出)(这种其他层的动画还可以继续播放)
//PlayMode.StopAll —— 针对所有动画(停止、淡出)
//在上一个动画播放结束之后cross fade到目标动画,就像是一个动画播放的队列

//string animation —— 目标动画名称
//float fadeLenght —— 时间 默认0.3s
//QueueMode queue —— 队列模式 默认QueueMode.CompleteOthers , QueueMode.PlayNow
//PlayMode mode —— 播放模式,默认停止同一层

public AnimationState CrossFadeQueued(string animation, 
                                      float fadeLength = 0.3F, 
                                      QueueMode queue = QueueMode.CompleteOthers, 
                                      PlayMode mode = PlayMode.StopSameLayer); 


//测试的结果是:
//1、特别注意 XXQueue 这样的函数,如果遇到循环播放的动画 WrapMode.Loop ,因为默认情况 QueueMode.CompleteOthers,所以无法切换到其他动画
//2、如果将动画队列模式设为 QueueMode.PlayNow,那么即使是 循环播放的动画,它也会自身切换自身,从头开始播放
//3、文档中的 Animation.CrossFadeQueue 没咋看明白

https://docs.unity3d.com/ScriptReference/Animation.CrossFadeQueued.html

public int GetClipCount();
public bool IsPlaying(string name); 
//播放默认的动画,如果没有默认动画,那么返回false
public bool Play(PlayMode mode = PlayMode.StopSameLayer);
//播放指定动画,PlayMode 影响其他层或所有层的 其他动画的播放
public bool Play(string animation, PlayMode mode = PlayMode.StopSameLayer); 

如果指定的动画已经正在播放,那么再执行这个 anim.Play("xx"); 不会导致回退到动画开始。
动画播放结束,除非是 WrapMode.Loop 那么动画就停在那了,模型也就一个pose,并且 anim.isPlaying == false
//和 CrossFadeQueue 类似,但是这个没有混合

public AnimationState PlayQueued(string animation, 
                                 QueueMode queue = QueueMode.CompleteOthers,
                                 PlayMode mode = PlayMode.StopSameLayer); 
public void RemoveClip(AnimationClip clip); 
public void RemoveClip(string clipName); 
//就是将动画从头开始播放,不管是不是循环播放的,另外注意如果动画播放结束再执行 Rewind 是无效的

public void Rewind(string name);    //指定某个动画从头开始播放
public void Rewind();    //全部动画都从头开始播放(可以有多个层的动画)
//貌似是先设置一个动画状态,然后 anim.Sample(); 采样一次,似乎是将这些参数应用到其他动画状态???

public void Sample(); 

//Samples animations at the current state.
//This is useful when you explicitly want to set up some animation state, and sample it once.


public class ExampleClass : MonoBehaviour {
    public Animation anim;
    void Start() {
        anim = GetComponent<Animation>();
        anim["MyClip"].time = 2.0F;
        anim["MyClip"].enabled = true;
        anim["MyClip"].weight = 1;
        anim.Sample();
        anim["MyClip"].enabled = false;
    }
}
public void Stop(); 
public void Stop(string name); 

最后贴上代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum ESelectedFunc
{ 
    Play,
    PlayQueue,
    CrossFade,
    CrossFadeQueue
}

public class TestPlayAnimation : MonoBehaviour {

    Animation anim;

    int animChangeModeSelected =0;
    int playModeSelected = 0;
    int queueModeSelected = 0;
  //  int animPlayModeSelected = 0;

    string[] animationNames = { "free", "walk", "attack" };

    string[] animChangeToolbar = { "Play", "PlayQueue", "CrossFade", "CrossFadeQueue" };
    string[] playModeToolbar = { "StopSameLayer", "StopAll" };
    string[] queueModeToolbar = { "CompleteOthers", "PlayNow" };

  //  string[] animationPlayModeToolbar = { "Mix", "Queue", "Stop" };


    void Start () 
    {
        anim = GetComponent<Animation>();
    }

    void OnGUI()
    {
        GUI.Label(new Rect(100, 50, 100, 50), "FunctionName");
        animChangeModeSelected = GUI.Toolbar(new Rect(200f, 50f, 500f, 50f), animChangeModeSelected, animChangeToolbar);

        GUI.Label(new Rect(100,110,100,50),"PlayMode");
        playModeSelected = GUI.Toolbar(new Rect(200, 110, 240, 50), playModeSelected, playModeToolbar);

        GUI.Label(new Rect(100, 170, 100, 50), "QueueMode");
        queueModeSelected = GUI.Toolbar(new Rect(200, 170, 240, 50), queueModeSelected, queueModeToolbar);

        //GUI.Label(new Rect(100, 260, 100, 50), "AnimationPlayMode");
        //animPlayModeSelected = GUI.Toolbar(new Rect(200, 260, 300, 50), animPlayModeSelected, animationPlayModeToolbar);

        OtherGUI();

        ProcessAnimation();
    }


    void OtherGUI()
    {
        GUI.Label(new Rect(100, Screen.height - 100, 200, 50), "anim.isPlaying :   " + anim.isPlaying);

        if (GUI.Button(new Rect(Screen.width - 220, Screen.height - 100, 100, 50), "Rewind"))
        {
            anim.Rewind();
        }
        if (GUI.Button(new Rect(Screen.width - 110, Screen.height - 100, 100, 50), "Stop"))
        {
            anim.Stop();
        }
    }

    void ProcessAnimation()
    {
          ESelectedFunc mode = (ESelectedFunc)animChangeModeSelected;

        foreach (string str in animationNames)
        {
            if (GUILayout.Button(str))
            { 
                switch(mode)
                {
                    case ESelectedFunc.Play:
                        anim.Play(str,(PlayMode)playModeSelected);
                        break;
                    case ESelectedFunc.PlayQueue:
                        anim.PlayQueued(str,(QueueMode)queueModeSelected,(PlayMode)playModeSelected);
                        break;
                    case ESelectedFunc.CrossFade:
                        anim.CrossFade(str,0.3f,(PlayMode)playModeSelected);
                        break;
                    case ESelectedFunc.CrossFadeQueue:
                        anim.CrossFadeQueued(str,0.3f,(QueueMode)queueModeSelected,(PlayMode)playModeSelected);
                        break;
                    default:
                        break;
                }
            }

        }
    }


}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值