2020-01-17 11:29:54 boyZhenGui 阅读数 1318

手动添加动画回调事件

在帧动画上方右键,添加Animation Event;
在Inspector选择添加的方法。
需要脚本挂载在相应有Animator的物体上,才可选择其public方法。
在这里插入图片描述

代码添加动画回调事件

需要用到的类
Animator、
AnimatorOverrideController 用于覆盖控制器中的动画剪辑,以针对给定的头像专门化动画,不会重置状态机的当前状态、
AnimationClip 存储基于关键帧的动画、
AnimationEvent 动画事件、
Action。
参数定义,使用Dictionary存储AnimationClip

添加动画事件代码:
方法一:Clip.AddEvent();有效期到运行结束。
方法二:AnimationUtility.SetAnimationEvents(),相当于手动添加,永久有效。

  	private Animator mAnim;
    private AnimatorOverrideController mController;
    private Dictionary<string, AnimationClip> mClipDic = new Dictionary<string, AnimationClip>();
    private Action mCallBack;
    private AnimationEvent evt;

初始化

  public void Awake()
    {
        mController = new AnimatorOverrideController();
        mAnim = transform.GetComponent<Animator>();
        //通过Animator中的runtimeAnimatorController,将AnimatorOverrideController与Animator链接
        mController.runtimeAnimatorController = mAnim.runtimeAnimatorController;
    }

播放调用

public void Play(string animName, Action action)
    {
    	//回调事件
        mCallBack = action;
        //避免重复添加多个回调函数到动画中。
        if (!mClipDic.ContainsKey(animName))
        {
        	//通过AnimatorOverrideController[动画名],获取clip
            mClipDic.Add(animName, mController[animName]); 
            //初始化AnimationEvent 动画事件。
            evt = new AnimationEvent();
            //事件挂载的时间位置。
            evt.time = mClipDic[animName].length;
            //事件调用的函数名
            evt.functionName = "MyCallback";
            //加入到clip中。有效期:播放结束
            //mClipDic[animName].AddEvent(evt);
            //加入到clip中。有效期:永久。直到手动删除。
            AnimationUtility.SetAnimationEvents(mClipDic[animName], new AnimationEvent[] { evt });
        }
        //播放动画
        mAnim.Play(animName,0,0);
    }
    
    private void MyCallback()
    {
        if(mCallBack != null)
            mCallBack.Invoke();
    }

完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using NaughtyAttributes;
using UnityEngine.Events;
using UnityEditor;
using System;
/// <summary>
/// 播放Animator并加入播放完成回调。
/// </summary>
[RequireComponent(typeof(Animator))]
public class UIAnim : MonoBehaviour
{
    private Animator mAnim;
    private AnimatorOverrideController mController;
    private Dictionary<string, AnimationClip> mClipDic = new Dictionary<string, AnimationClip>();
    private Action mCallBack;
    private AnimationEvent evt;
    public void Awake()
    {
        mController = new AnimatorOverrideController();
        mAnim = transform.GetComponent<Animator>();
        mController.runtimeAnimatorController = mAnim.runtimeAnimatorController;
    }

    public void Play(string animName, Action action)
    {
        mCallBack = action;
        if (!mClipDic.ContainsKey(animName))
        {
            mClipDic.Add(animName, mController[animName]); 
            evt = new AnimationEvent();
            evt.time = mClipDic[animName].length;
            evt.functionName = "MyCallback";
            //mClipDic[animName].AddEvent(evt);
            AnimationUtility.SetAnimationEvents(mClipDic[animName], new AnimationEvent[] { evt });

        }
        mAnim.Play(animName,0,0);

    }
    private void MyCallback()
    {
        if(mCallBack != null)
            mCallBack.Invoke();
    }
}

如果文章对你有帮助,不妨关注我一下,点个赞。
我会一直分享Unity开发中解决的坑,分享学到的技术,也会分享读书心得和理财心得,谢谢大家。

2019-07-28 10:34:23 weixin_44345862 阅读数 196

先上图:
在这里插入图片描述
我主要做了几件事:1.导入kl的unity package并拼接动画,2.添加两个UI中的按钮,Canvas是加载按钮时自动生成的,3.同时用代码实现了另外4个按钮的生成,效果图如下:
在这里插入图片描述
不管什么模型,fbx模型或者unity 包 里面含不含动画是可以在assets中看出来的,恐龙模型包导入后如下图:
在这里插入图片描述 assets中多了一个KL_Model文件夹,点击词文件夹,如下图(KLcontrol是后来我自己建的动画控制器):
在这里插入图片描述 最后面的那个是预制文件又叫prefabs文件,带三角说明下面还有其它文件,点击三角就知道有没有含动画了,如下图:
在这里插入图片描述 有很多,但是都不能播放,需要自己建animator control。步骤如下:预制文件拖入层级目录
在这里插入图片描述 inspector中,controller中是none,此时assets空白处右键->create->animator controller,命名KL-control,然后拖入右侧的controller编辑框中就有了如上图的效果。此时动画控制器内还没有动画,我们双击编辑此动画控制器,如下图:
在这里插入图片描述 默认只有三个状态(每个button是一个状态):Any state,entry和exit。一切从entry开始,其它的连个可以不用。把恐龙预置文件中的动画片段随便选几个一一托到base layer中,在每个按钮上右键->make transition,然后左键点到你想连的按钮(状态)上,就会出现图中的箭头了,其中entry的那个箭头是自动生成的,拖进去的第一个按钮会自动和他建立箭头。保存,然后就可以play看效果了,如果想连续循环播放,只需要将最后一个状态连箭头到第一个状态即可,很棒的,注意inspector中的has exit time一定要是勾选上的状态,此动画默认是勾选了的,CHAN模型就没有,如果没勾选,不会自动顺序播放动画的。
在这里插入图片描述
所有想控制的动作,必须拖到此画布中,可以不连线,但必须在base layer中,否则找不到。动画之间的跳转可以通过按钮控制,我这里在WalkFW和RunFW两个状态之间的连线上加了一个key参数,bool型的,通过按键控制此参数,从而影响动画是否往下播放。具体操作:选中此箭头,左边点到parametres标签中,然后点中间的加号,选中bool,随意命个名,我的为key,然后在inspector中的conditions一栏,点击加号,选择刚才的key,并将其值选为true,意思是为true的时候自动播放后面;如果选择false,那么就有些别扭,意思为:当key值为false的时候,自动播放后面,为了写代码时,好理解,所以选择true.
在这里插入图片描述 不加Key的时候,不用写代码,动画是会自动播放的,这里不是向交互嚒,就加key。然后写代码,附加到恐龙模型上。
在这里插入图片描述 其代码如下:

using System.Collections;
using UnityEngine;
public class BehaviourScript : MonoBehaviour
{

Animator animator;
private float scaleW = 1.0f;        //宽度缩放比
private float scaleH = 1.0f;        //高度缩放比
                                    // Use this for initialization
void Start()
{
    //获取动画组件
    animator = GetComponent<Animator>();      
}

// Update is called once per frame
void Update()
{
    scaleW = (float)Screen.width / 800;     //计算宽度缩放比
    scaleH = (float)Screen.height / 480;    //计算高度缩放比
    if (animator)
    {
        AnimatorStateInfo stateinfo = animator.GetCurrentAnimatorStateInfo(0);
    //    if (stateinfo.IsName("WalkFW"))
        
            if (Input.GetKeyDown(KeyCode.UpArrow))
            {
                animator.SetBool("key",true);
            }
        
    //    if (stateinfo.IsName("WalkFW"))
        
            if (Input.GetKeyDown(KeyCode.DownArrow))
            {
                animator.SetBool("key", false);
            }
        
    }
}

void OnGUI()//代码生成第一个图中左侧的4个大按钮
{
    GUI.skin.button.fontSize = (int)(25 * scaleW);        //调整按钮字体大小

    if (GUI.Button(new Rect(70 * scaleW, 50 * scaleH, 90 * scaleW, 40 * scaleH), "WalkFW"))
    {
        animator.Play("WalkFW");
    }
    if (GUI.Button(new Rect(70 * scaleW, 110 * scaleH, 90 * scaleW, 40 * scaleH), "RunFW"))
    {
        animator.Play("RunFW");
    }
    if (GUI.Button(new Rect(70 * scaleW, 170 * scaleH, 220 * scaleW, 40 * scaleH), "idle"))
    {
        animator.CrossFade("idle", 0.5f);
    }
    if (GUI.Button(new Rect(70 * scaleW, 230 * scaleH, 220 * scaleW, 40 * scaleH), "Attack01"))
    {
        animator.CrossFade("Attack01", 0.5f);
    }

}

}

手动添加按钮的代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public class buttontest : MonoBehaviour
{

// Use this for initialization
void Start () {

    // 获取按钮游戏对象
     GameObject btnObj = GameObject.Find("Canvas/Button");
             //获取按钮脚本组件
     Button btn = (Button)btnObj.GetComponent<Button>();
            //添加点击侦听
     btn.onClick.AddListener(onClick);
}
void onClick()
 {
     Debug.Log ("click!");
 }
 void Update () {	
}

}
在这里插入图片描述 书上说赋给canvas,我也是这么做的。另外说一句,上图中的fbx格式的熊猫,预制文件展开,很明显都是贴图,就没有动画(害的我一门心思的向给他重组动画呢,野路子下载的模型,根本就不含动画,费了不少时间弄个明白的!)。
按钮肯定要用到代码,就不要想着通过其inspector下面的On click()添加动作了,此平台跟其它的不一样,没那么简单的事情。自己写代码,拖到按钮上是必经之路。除了前面的全代码生成和控制。
在这里插入图片描述

2016-12-09 17:39:49 era2521 阅读数 1447

看了雨松的自动生成生成动画方案,我觉得太麻烦了。所以我准备自己写一篇代码加载动画方案。这个是解决帧动画的,因为u3d没有播放gif的功能,有了这个神器,传入图片和总时间,就ok了。
首先我们准备一个图集,里面是播放动画的小图片。
connectAnim.png
然后创建一个sprite,放入资源文件做成profab。��,准备工作就差不多做好了。记得不要把下面这个代码添加到profab上,因为我在初始化这个profab的时候用代码添加了。

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

public class AnimationByCode :MonoBehaviour{

    // Use this for initialization
    //动画间隔时间
    private float circleTime = 0;
    //定义一个变量存储需要改变动画的sprite
    private SpriteRenderer aniSprite;
    //动画总需时间
    private float sumTime = 0;
    //记录运行时间
    private float countTime = 0;
    private int countIndex = 0;
    private Sprite[] aniList;
    //为了避免这个代码一直执行,我们可以在需要添加动画的时候,再添加这个AnimationByCode的脚本
    //动画结束以后,可以把动画的gameobject destory
    private void SetAnimationWithMaterial(string[] obj){
        float alltime = float.Parse(obj[1].ToString());

        this.aniSprite = transform.GetComponent<SpriteRenderer>();
        //获取图集中所有的图片
        this.aniList = Resources.LoadAll<Sprite>(obj[0].ToString());
        //一张图片需要的时间
        this.circleTime = alltime / this.aniList.Length;
        //把图片播放完成需要多少图片
        this.sumTime = alltime;

    }

    // Update is called once per frame
    void Update () {
        if (countTime < sumTime) {
            countTime += Time.deltaTime;
            float temp = countTime / circleTime;
            if (temp >= countIndex) {
                countIndex = (int)temp;
                print ("countIndex" + countIndex);
                //这里要剔除最后一张,如果不判断就会超过数组 越界
                if (countIndex <= this.aniList.Length - 1) {
                    this.aniSprite.sprite =this.aniList[countIndex];
                }
            }

        } 
        else if(countTime > sumTime) {
            Destroy (gameObject);
        }
    }
}

如果要初始化这个profab,并通过生成的gameobj 传入动画需要的图片和动画总时间。

public class Example : MonoBehaviour {

    public void InstanceObjectAndMakeAnimation(){

        GameObject aniProfab= Resources.Load ("AniProfab")as GameObject;
        GameObject aniObject = Instantiate (aniProfab,Vector3.zero,Quaternion.identity) as GameObject;
        aniObject.AddComponent<AnimationByCode> ();
        string[] message = new string[2];  
        message[0] = "connectAnim";  
        message[1] = "2";  
        aniObject.SendMessage ("SetAnimationWithMaterial",message);
    }
}

动画的脚本不需要管理,只需要负责初始化profab,绑定脚本就可以了。是不是很简单!

这个只是简单加载帧动画吧,并不是万能的。如果需要循环播放,位置偏移,自己去修改下。

2019-12-22 05:10:12 QQhelphelp 阅读数 102
  1. //绑定到宿主身上
  2. public class AAAA : MonoBehaviour {
  3.     private Animator animator;//animator组件
  4.     public AnimationClip[] clips;//动画片段
  5.     
  6.     void Start() {
  7.         animator = GetComponent<Animator>();
  8.         clips = animator.runtimeAnimatorController.animationClips;
  9.         string a = "attack";//动画名
  10.         string b = "attack2";
  11.         for (int i = 0; i <clips.Length; i++)
  12.         {
  13.             if (clips[i].name==a)
  14.             {                                   //动画状态机,动画名,绑定的方法,绑定到动画的中间                    
  15.                 AddAnimationEvent(animator,a,"Hello",clips[i].length*0.5f);//添加动画事件
  16.             }
  17.             if (clips[i].name==b)
  18.             {                                                                    //0.8*24所在的位置 
  19.                 AddAnimationEvent(animator,b, "Attack", 0.8f);
  20.             }
  21.         }
  22.         
  23.     }
  24.     /// <summary>
  25.     /// 给动画添加动画事件
  26.     /// </summary>
  27.     /// <param name="ani"></param>//Animator组件
  28.     /// <param name="name"></param>//动画名字
  29.     /// <param name="fun"></param>//绑定的方法
  30.     /// <param name="time"></param>//绑定到那一帧
  31.     private void AddAnimationEvent(Animator ani, string name, string fun, float time)
  32.     {
  33.         AnimationClip[] temp = ani.runtimeAnimatorController.animationClips;
  34.         for (int i = 0; i < temp.Length; i++)
  35.         {
  36.             if (temp[i].name==name)
  37.             {
  38.                 AnimationEvent _event = new AnimationEvent();
  39.                 _event.functionName = fun;
  40.                 _event.time = time;
  41.                 temp[i].AddEvent(_event);
  42.                 break;
  43.             }
  44.         }
  45.         //重新绑定
  46.         ani.Rebind();
  47.     }
  48.     void Update() {
  49.     }
  50. //动画a绑定的方法
  51.     public void Hello() {
  52.         Debug.LogError("hello"+"-------------------");
  53.     }
  54. //动画b绑定的方法
  55.     public void Attack()
  56.     {
  57.         HelloAttack("helloAttack");
  58.     }
  59.     void HelloAttack(string str)
  60.     {
  61.         Debug.LogError("攻击攻击攻击" + str);
  62.     }
  63.     void OnDestory() {
  64.         CleanAllEvent();
  65.     }
  66.     /// <summary>
  67.     /// 清除动画事件
  68.     /// </summary>
  69.     private void CleanAllEvent()
  70.     {
  71.         for (int i = 0; i <clips.Length; i++)
  72.         {
  73.             clips[i].events = default(AnimationEvent[]);
  74.         }
  75.     }
  76. }
2013-10-31 12:55:44 braveyoung123 阅读数 1190

iGUI插件似乎国人都不使用该插件,或许是太简单了。相对于NGUI个人感觉还是挺不错的!我们来看看老外们

使用iGUI的案例吧:



ok!我们进入主题:

我们在游戏开发中呢,难免会使用动画效果。当然iGUI内置的动画系统可以让我们进行拖拽组件实现,有的时候

我们也希望通过代码在运行时添加动画效果。这样做的好处是不言而喻的!

琢磨一番,我们可以使用如下的代码实现这样的效果:

代码样例:


把脚本拖拽到一个gameobject上,Play一下

前提是:你的场景中需要添加iGUIButton才有效果!

层级视图中new 出来的对象


最后效果如下:


结束语:

Enjoy!


Unity 设置3D动画

阅读数 1222

没有更多推荐了,返回首页