引言
如果我们想在两秒内调用特定代码,或者规定间隔时间重复执行特定代码,我们首选想到的可能是使用协程。
而这篇文章将介绍协程的替代方案:MonoBehaviour .Invoke()。
简单介绍
实现看一下方法声明:
public void Invoke (string methodName , float time );
参数介绍
string methodName:将被调用的方法名。
float time:在 time 秒内调用该方法。
注意
如果时间设置为 0,则在下一个更新周期调用该方法。在这种情况下,最好直接调用该函数。
示例
在 2 秒内发射一个射弹。
public class ExampleScript : MonoBehaviour
{
// 射弹的刚体。
Rigidbody projectile;
void Start()
{
使用Invoke()调用发射方法。
Invoke("LaunchProjectile", 2.0f);
}
// 射弹发射方法。
void LaunchProjectile()
{
Rigidbody instance = Instantiate(projectile);
instance.velocity = Random.insideUnitSphere * 5.0f;
}
}
示例的协程版本
public class ExampleClass : MonoBehaviour {
// 射弹的刚体。
Rigidbody projectile;
// 等待指定时间并执行发射方法的协程。
IEnumerator WaitAndLaunchProjectile(float wait) {
yield return new WaitForSeconds(wait);
Rigidbody instance = Instantiate(projectile);
instance.velocity = Random.insideUnitSphere * 5;
}
// 调用协程。
void Start() {
StartCoroutine(LaunchProjectile(2));
}
}
为什么说这是协程的下位替代
当您想快速地开发出可以见到实际效果的游戏某功能的演示版本,Invoke()方法可能是一个不错的选择。从上面的例子中,可以很容易地看出,Invoke()方法的代码量,远少于使用协程。
但由于将字符串作为方法名称传递,因此如果你在后期开发中改变了那个方法名,游戏将会出错,但 IDE 不会在你写代码时给出错误信息。因此,重构错误仅在运行时可见,这通常意味着麻烦。
所以,使用协程可以获得更好的性能和可维护性。使用 Invoke() 则可以快速开发出游戏原型。
重复调用
作为协程的替代品,Invoke 方法也可以完成指定间隔时间重复调用指定方法的功能,只不过它换了一个名字,叫做:MonoBehaviour .InvokeRepeating()。
简单介绍
实现看一下方法声明:
public void InvokeRepeating (string methodName , float time , float repeatRate );
参数介绍
string methodName:将被调用的方法名。
float time:在 time 秒内调用该方法。
float repeatRate:每隔 repeatRate (秒)重复一次。
注意
如果您将时间刻度设置为 0,这将不起作用。
示例
2 秒后开始,然后每 0.3 秒发射一次射弹。
public class ExampleScript : MonoBehaviour
{
public Rigidbody projectile;
void Start()
{
InvokeRepeating("LaunchProjectile", 2.0f, 0.3f);
}
void LaunchProjectile()
{
Rigidbody instance = Instantiate(projectile);
instance.velocity = Random.insideUnitSphere * 5;
}
}
取消调用
CancelInvoke允许您取消使用前两种方法安排的调用。它有两个重载。
public void CancelInvoke();
取消此 MonoBehaviour 上的所有 Invoke 调用。
...
void Update ()
{
// 取消所有 Invoke 调用
if ( Input.GetButton ("Fire1"))
CancelInvoke();
}
...
public void CancelInvoke (string methodName );
在此 MonoBehaviour 上取消所有具有名称 methodName 的 Invoke 调用。
...
void Update ()
{
// 仅取消 LaunchProjectile 调用
if ( Input.GetButton ("Fire1"))
CancelInvoke("LaunchProjectile");
}
...
检查是否存在没有结束的 Invoke
MonoBehaviour.IsInvoking() 方法可以帮助我们检查当前 MonoBehaviour 中,是否存在没有结束的 Invoke 。它有两个重载。
public bool IsInvoking();
此 MonoBehaviour 是否有任何没有结束的调用?
public bool IsInvoking(string methodName);
此 MonoBehaviour 是否有没有结束的调用将调用名为 methodName 的方法?
示例
此示例将本文中的示例制作为具有 2 秒冷却时间,按空格键发射的大炮。
public class ExampleScript : MonoBehaviour
{
public Rigidbody projectile;
void Update()
{
// 按下空格并且没有炮弹即将发射时,调用 2 秒后发射的方法。
if (Input.GetKeyDown(KeyCode.Space) && !IsInvoking("LaunchProjectile"))
Invoke("LaunchProjectile", 2.0f);
}
void LaunchProjectile()
{
Rigidbody instance = Instantiate(projectile);
instance.velocity = Random.insideUnitSphere * 5;
}
}