飞行射击游戏3D中发现的问题
- c#的字串==为直接判断值而java的字串==对于new俩个一样的是不等!为比地址
- 旋转基于中心!赋予上层对象时小心中心不一定在子对象中心
- 物理的velocity表速度,在start给予一次时一直保持
关于yield return XXXX 的原理:
划重点:IEnumerale和IEnumerator 枚举器和迭代器
一. 首先明白c#中的foreach遍历枚举器
这个东西初见源自枚举集合————为了自己实现的数据结构类能使用foreach遍历。而实现foreach首先需要本类实现IEnumerable接(其实现等同于可枚举集合)查看该接口:
PS:针对类前加[]语法还没深究,估计和UI显示有关
好的,就一个方法IEnumerator
- 创建Tree(一个自己写的树数据结构类)的枚举器:
|
|
在Tree中使用:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071public class Tree<TItem> : IEnumerable<TItem> where TItem : IComparable<TItem>{public TItem NodeData { get; set; }public Tree<TItem> LeftTree { get; set; }public Tree<TItem> RightTree { get; set; }public Tree(TItem nodeValue){this.NodeData = nodeValue;this.LeftTree = null;this.RightTree = null;}public void Insert(TItem newItem){TItem currentNodeValue = this.NodeData;if (currentNodeValue.CompareTo(newItem) > 0){// Insert the item into the left subtreeif (this.LeftTree == null){this.LeftTree = new Tree<TItem>(newItem);}else{this.LeftTree.Insert(newItem);}}else{// Insert the new item into the right subtreeif (this.RightTree == null){this.RightTree = new Tree<TItem>(newItem);}else{this.RightTree.Insert(newItem);}}}public string WalkTree(){string result = "";if (this.LeftTree != null){result = this.LeftTree.WalkTree();}result += String.Format($" {this.NodeData.ToString()} ");if (this.RightTree != null){result += this.RightTree.WalkTree();}return result;}IEnumerator<TItem> IEnumerable<TItem>.GetEnumerator(){return new TreeEnumerator<TItem>(this);}IEnumerator IEnumerable.GetEnumerator(){throw new NotImplementedException();}}这样就可以用了
12345Tree<int> tree1 = new Tree<int>(10);foreach(int item in tree1){Console.WriteLine(item);}
以上就是实现foreach遍历可枚举集合的创建方法,但是…..太复杂了!所以有了一种 迭代器 实现IEnumerator
二.迭代器与yield
官方定义:迭代器是能生成已排序值序列的代码块。也就是说,迭代器是对序列的一种描述C#用它自动生成枚举器
实现方法:
这段代码是对上面提到的一般枚举器实现方式的重写,只需关注yield即可:它不反回IEnumerator对象,而是 每次将方法叫停,讲一个值传回调用者,当调用者需要下一个值时,就从上次停止处继续,数据耗尽时停止
三.unity中的用法
- WWW - after Updates happen for all game objects; check the isDone flag. If true, call the IEnumerator’s MoveNext() function;
- WaitForSeconds - after Updates happen for all game objects; check if the time has elapsed, if it has, call MoveNext();
- null or some unknown value - after Updates happen for all game objects; Call MoveNext();
- WaitForEndOfFrame - after Render happens for all cameras; Call MoveNext().
有一篇博客写的很实践:点这里
在这里我简单总结本示例需要用到的:
Unity使用 StartCoroutine(routine: IEnumerator): Coroutine 启动协程,参数必须是 IEnumerator 对象。在函数内使用前面介绍 yield 关键字返回 IEnumerator 对象,Unity 中实现了 YieldInstruction 作为 yield 返回的基类,有 Cortoutine, WaitForSecondes, WaitForEndOfFrame, WaitForFixedUpdate, WWW 几个子类实现。StartCoroutine 将 传入的 IEnumerator 封装为 Coroutine 返回,引擎会对 Corountines 存储和检查 IEnumerator 的 Current值。
总之,使用是就是用StartCoroutine调用一个带yield返回的函数,这个函数会按照yield后的规定慢慢一段一段执行完,该过程位于Update之后,永远产生一波波敌人时只用在start调用StartCoroutine启动迭代器让其在update后面默默运行就好了