大家好,又见面了,我是你们的朋友全栈君。
协程
前言
协程是unity提供的一个特殊的机制,他的特点就是可以方便的实现流程化的东西。但是就他的效率而言个人感觉并不乐观,个人理解有点像LUA的闭包,C#的goto语句,需要保存大量的数据和大量的逻辑处理,而针对于实际业务来讲我们可能需要的逻辑量并没有那么大,另外协程中如果有比较复杂的逻辑处理,对于扩展和维护还是比较费力的。
当然协程既然这样,还有使用么?当然还是有用的,只不过大家需要根据场景进行使用。因为有些逻辑用协程来还是比较方便的,如果不用的话可能需要手敲一串子代码。
调用方式
被调用函数必须返回IEnumerator。
- public Coroutine StartCoroutine(string methodName);
- public Coroutine StartCoroutine(string methodName, [DefaultValue(“null”)] object value);
- public Coroutine StartCoroutine(IEnumerator routine);
以上方法均为Monobehavior的内部方法可在MonoBehavior的子类中直接使用,方式1,2通过名称调用,区别在于1只能调用无参函数,2可以调用一个带有参数的函数。3是通过方法直接调用,可以支持任何参数。
由上可以看出,1.对于使用方法名的调用带参数的函数,运行时会报错。
2 .同一个协程函数可以被多次调用。
细心的同学可能会有问,如果上例中的函数别重载,使用方法名的方式调用会不会有问题呢?如果你知道结果给你点个赞。我们测试一下。
没错,发现了什么?使用方法名的带参数的调用居然使用没参数的重载方法(unity版本2018.4,使用方法名方式调用协程,不会识别重载,只会调用编译时第一个名称符合的方法),而使用方法体的方法却可以区分开重载。所以使用方法名调用的方式慎用。
由于协程的调用依赖于Mono脚本,在实际开发中我们可以进行其进行一个封装,
停止方式
- public void StopAllCoroutines();
- public void StopCoroutine(string methodName);
- public void StopCoroutine(IEnumerator routine);
- public void StopCoroutine(Coroutine routine);
方式1:停止此Mono脚本内的所有协程。
方式2:停止使用方法名启动的此方法的协程函数,如图所示
并没有停止使用调用方式3开启的协程
方式3:停止对应启动方式3开启的协程,如图
方式4:停止的开启时的其返回值,可以停止以以上三种方式开启的协程。
yiled return语句执行时机
WaitForSeconds(float Time)
等待一段时间后继续执行,yiled return 数字,和其效果一致。由上图可以发现,等待时间结束后的执行时机在update后,lateupdate前。
WaitForSecondsRealtime(float time)
与WaitForSeconds不同的是,此方法不受timescale的影响
WaitForEndOfFrame()
等待到当前帧结束。
WaitForFixedUpdate()
等到物理帧结束。
WaitUntil(Func predicate)
直到predicate返回true。predicate执行时机为首次执行为调用时机(比如在Start中开启的协程,则本帧在Start时执行,本帧的Update后则不再执行),之后执行时机为Update之后,LateUpdate之前。如图
WaitWhile(Func predicate)
与WaitUnitl相似,唯一不同的是predicate返回false结束。
实现自定义函数
继承CustomYieldInstruction。实现keepWaiting即可。例如实现等待指定帧数后执行的自定义函数
Tips 返回任意类型
如果yiled return 返回的类型是我们的随意定义的一个类型,比如yiled return vecter3.one,则下一帧继续执行后续内容。
实际开发中使用建议
开发中,并不是所有的脚本都继承自mono,相反实际项目中大部分都不会继承自mono,所以我们可以单独拿出来一个继承自Mono的单例类,专门用于开启协程。但是应该禁止使用sting的方式开启和关闭协程,所以我们的单例应该禁止其访问这些方法。大致如下
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Internal;
public class CoroutineManager : MonoBehaviour
{
public static CoroutineManager Instance { get; private set; }
private void Awake()
{
if (Instance == null)
{
Instance = this;
}
}
public new Coroutine StartCoroutine(IEnumerator routine)
{
return base.StartCoroutine(routine);
}
[Obsolete("无法使用此方法开启协程", true)]
public new Coroutine StartCoroutine(string methodName)
{
return null;
}
[Obsolete("无法使用此方法开启协程", true)]
public new Coroutine StartCoroutine(string methodName, [DefaultValue("null")] object value)
{
return null;
}
public new void StopCoroutine(IEnumerator routine)
{
base.StopCoroutine(routine);
}
public new void StopCoroutine(Coroutine routine)
{
base.StopCoroutine(routine);
}
[Obsolete("无法使用此方法关闭协程", true)]
public new void StopCoroutine(string methodName)
{
}
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/147704.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...