楼主: 路丝丝

[脚本]   Unity3D教程-自定义YieldInstruction

[复制链接]

28

主题

20

听众

285

积分

小学生

Rank: 2

升级   28.33%

发表于 2015-12-3 16:53 |显示全部楼层
共享资源获取更多积分!share your resources get more credits!
  本篇文章我们来看下扩展Coroutine:自定义YieldInstruction,Unity 的Coroutine机制无疑是这个引擎的一个亮点,可以把很多异步的逻辑用一种顺序的书写方式去实现,这个还是很重要的。
  关于Coroutine的原理,说实话,这个没有源代码,不好说具体是怎么实现的。看他用到了IEnumerator,想象是使用了.Net的枚举机制。网上有不是探讨Coroutine实现原理的帖子,有兴趣的同学可以翻开看看。
  Coroutine之所以强大,缺不了一系列YieldInstruction的派生类,包括:WaitForSeconds , WaitForFixedUpdate,AsyncOperation等等,我一直在琢磨能不能实现自己的YieldInstruction派生类呢?今天花时间尝试了一些,答案是“不能,也能”,哈哈。为什么说“不能”呢,是因为YieldInstruction这个类可没什么虚函数可以去override的,为什么说“能”呢!我们可以借用一个特殊的YieldInstruction派生类,来实现等同的功能,这个类就是Coroutine。
  假设我们想实现这样一个YieldInstruction:当一个动画播放完事儿之后,程序再继续。
  具体的实现也很简单,首先我们需要一个IEnumerator的派生类,并实现其3个接口,具体代码如下:
  using UnityEngine;
  using System.Collections;
  public class WaitForEndOfAnim : IEnumerator
  {
  AnimationState m_animState;
  public WaitForEndOfAnim(AnimationState animState)
  {
  m_animState = animState;
  }
  //-- IEnumerator Interface
  public object Current
  {
  get
  {
  return null;
  }
  }
  //-- IEnumerator Interface
  public bool MoveNext()
  {
  return m_animState.enabled;
  }
  //-- IEnumerator Interface
  public void Reset()
  {
  }
  }
  这里面核心的逻辑就在“MoveNext”函数中,我通过m_animState.enabled来判断动画是否播放完了。
  有了这个类时候,如果我们在协程函数体中写:yield return new WaitForEndOfAnim(animState),发现并没有其作用。后来改为:yield return StartCoroutine(new WaitForEndOfAnim(animAttack));就OK了。完整的测试代码如下:
  using UnityEngine;
  using System.Collections;
  public class UnitTest : MonoBehaviour
  {
  // Use this for initialization
  void Start()
  {
  }
  void OnGUI()
  {
  GUILayout.BeginArea(new Rect(6, 6, 200, 300));
  GUILayout.BeginVertical();
  GUILayout.Box("Conrountinue测试");
  if (GUILayout.Button("启动"))
  {
  StartCoroutine(DoTest());
  }
  GUILayout.EndVertical();
  GUILayout.EndArea();
  }
  IEnumerator DoTest()
  {
  Animation anim = GetComponentInChildren();
  AnimationState animAttack = anim["attack"];
  animAttack.speed = 0.1f;
  AnimationState animHit = anim["hit"];
  animHit.speed = 0.1f;
  AnimationState animDie = anim["die"];
  animDie.speed = 0.1f;
  Debug.Log("1.开始播放攻击动画。" + Time.time * 1000);
  anim.Play(animAttack.name);
  yield return StartCoroutine(new WaitForEndOfAnim(animAttack));
  Debug.Log("2.开始播放受击动画。" + Time.time * 1000);
  anim.Play(animHit.name);
  yield return StartCoroutine(new WaitForEndOfAnim(animHit));
  Debug.Log("3.开始播放死亡动画。" + Time.time * 1000);
  anim.Play(animDie.name);
  yield return StartCoroutine(new WaitForEndOfAnim(animDie));
  }
  }
  最后,运行结果看下图,注意时间戳:
  好了,本篇unity3d教程关于自定义扩展Coroutine的讲解到此结束,下篇我们再会。
  资源地址: http://cg.silucg.com/dongman/unity3d/7993.html

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

楼主热帖

0

主题

19

听众

203

积分

小学生

Rank: 2

升级   1%

发表于 2017-4-26 09:57 |显示全部楼层
楼主是超人
回复

使用道具 举报

0

主题

19

听众

202

积分

小学生

Rank: 2

升级   0.67%

发表于 2017-4-26 10:31 |显示全部楼层
好帖就是要顶
回复

使用道具 举报

0

主题

19

听众

201

积分

小学生

Rank: 2

升级   0.33%

发表于 2017-4-26 09:50 |显示全部楼层
顶顶多好
回复

使用道具 举报

0

主题

19

听众

203

积分

小学生

Rank: 2

升级   1%

发表于 2017-4-26 10:38 |显示全部楼层
说的非常好
回复

使用道具 举报

0

主题

19

听众

203

积分

小学生

Rank: 2

升级   1%

发表于 2017-4-26 10:14 |显示全部楼层
LZ真是人才
回复

使用道具 举报

0

主题

7

听众

6

积分

问题学生

Rank: 1

升级   3%

发表于 2017-5-11 20:27 |显示全部楼层
学习学习学习学习一下
回复

使用道具 举报

0

主题

19

听众

206

积分

小学生

Rank: 2

升级   2%

发表于 2017-5-21 20:42 |显示全部楼层
好帖就是要顶
回复

使用道具 举报

0

主题

19

听众

206

积分

小学生

Rank: 2

升级   2%

发表于 2017-5-21 20:39 |显示全部楼层
真心顶
回复

使用道具 举报

4

主题

19

听众

203

积分

小学生

Rank: 2

升级   1%

发表于 2017-5-21 21:09 |显示全部楼层
难得一见的好帖
回复

使用道具 举报

温馨提示:求助请到“Unity技术讨论”版块中发帖,便于集中解决!
您需要登录后才可以回帖 登录 | 立即注册

懒人模式:

关闭

站长推荐 上一条 /1 下一条

Unity3D游戏开发联盟(资源共享平台) -Unity3D,Unreal ( 苏ICP备12051100号 )   

GMT+8, 2019-9-19 13:06 , Processed in 0.113312 second(s), 49 queries .