“SingleCoroutine”。用GameObject.Active来管理协程Coroutine的方案

time:20210909
更新一下这篇文章,现有版本StartCoroutine已经有返回值了,可以自己保存返回值,用于Stop。但是这篇SingleCoroutine还是有意义的。
取决于设计上采用什么样的设计模式。

因为Coroutine有各种开启方法
StartCoroutine(字符串);
StartCoroutine(函数);
StopCoroutine(字符串);
StopCoroutine(函数);
StopAllCoroutines();
用过就会知道 开启和停止的调用比较混乱。
用字符串启动,可以用字符串停止。
用函数启动,无法用函数停止。

1.为了解决这个对应关系,所以可以考虑到Coroutine和MonoBehaviour的特性:
Coroutine是依赖于MonoBehaviour运行的。
GameObject.Active设置为false,可以停止这个GameObject上MonoBehaviour的所有行为。
MonoBehaviour.Enable设置为false,可以停止这个脚本的所有行为。

2.经过测试,发现启动Coroutine可以用MonoBehaviour的子类启动,并不关注IEnumerator函数所在的脚本。
函数所在的脚本被Enable(false)或者Active(false),并不影响启动Coroutine的MonoBehaviour脚本继续跑Coroutine。
所以可以得出结论: Coroutine会跑在启动它的MonoBehaviour脚本上。

所以就有了SingleCoroutine的方案:
其实逻辑很简单,用一个空脚本Attach到GameObject上,用这个GameObject上的MonoBehaviour脚本去启动Coroutine。
那么我们要停止Coroutine,只需要操作这个GameObject或者MonoBehaviour脚本的 enable或者active 就可以了。

在这样的情况下,我们就无所谓启动Coroutine用哪种方法,因为停止Coroutine并不需要找对应的函数,
而是无脑简单的去关脚本就好了。

这个方案有个缺点就是 为了针对一个Coroutine做开关,
所以使用的时候,一个MonoBehaviour只允许启动一个Coroutine。启动多个。。那么停止的时候,就会把起在同一个MonoBehaviour的Coroutine全部停止。

代码如下:

SingleCoroutine类:

public class SingleCoroutine : MonoBehaviour
{
}

SingleCoroutine对象池;

	private Queue<SingleCoroutine> m_queueSingleCoroutine = new Queue<SingleCoroutine>();

	public SingleCoroutine AcquireSingleCoroutine()
	{
		SingleCoroutine result = null;
		if (m_queueSingleCoroutine.Count > 0)
		{
			result = m_queueSingleCoroutine.Dequeue();
		}
		else
		{
			GameObject newObj = new GameObject();
			result = newObj.AddComponent<SingleCoroutine>();
		}
		result.gameObject.SetActive(true);
		return result;
	}

	public void FreeSingleCoroutine(SingleCoroutine sc)
	{
		sc.StopAllCoroutines();
		sc.gameObject.SetActive(true);
		m_queueSingleCoroutine.Enqueue(sc);
	}

这边我使用了 sc.gameObject.SetActive(),实际上用MonoBehaviour.Enable也是可以的。用GameObject的原因是因为在面板上比较容易看到 灰色和白色的 Active状态,便于调试。而且对比之下性能差异,基本可以忽略。

测试代码:


	private SingleCoroutine m_scUsing = null;
	public void BeginCoroutineTest()
	{
		m_scUsing = AcquireSingleCoroutine();
		m_scUsing.StartCoroutine(test());
	}

	public void EndCoroutineTest()
	{
		FreeSingleCoroutine(m_scUsing);
	}

	private IEnumerator test()
	{
		Debug.Log("1");
		yield return new WaitForSeconds(1);
		Debug.Log("2");
		yield return new WaitForSeconds(1);
		Debug.Log("3");
		yield return new WaitForSeconds(1);
		Debug.Log("4");
		yield return new WaitForSeconds(1);
		Debug.Log("5");
		yield return new WaitForSeconds(1);
		Debug.Log("6");
		yield return new WaitForSeconds(1);
	}

	void Update ()
	{
		if (Input.GetKeyDown(KeyCode.A))
		{
			BeginCoroutineTest();
		}
		if (Input.GetKeyDown(KeyCode.S))
		{
			EndCoroutineTest();
		}
	}

这里的Demo是一个概念,具体编码和设计方法,可以随意调整。

程序学无止尽。
欢迎大家沟通,有啥不明确的,或者不对的,也可以和我私聊
我的QQ 334524067 神一般的狄狄

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
public void Move() { int stt = sun; scoreText.text = stt.ToString(); if (Input.GetKey(KeyCode.W)) { direction = 0; this.gameObject.GetComponent<SpriteRenderer>().sprite = prota[2]; this.gameObject.transform.Translate(Vector3.up * speed * Time.deltaTime); } else if (Input.GetKey(KeyCode.S)) { this.gameObject.GetComponent<SpriteRenderer>().sprite = prota[0]; direction = 2; this.gameObject.transform.Translate(Vector3.down * speed * Time.deltaTime); } else if (Input.GetKey(KeyCode.D)) { direction = 3; this.gameObject.GetComponent<SpriteRenderer>().sprite = prota[1]; this.gameObject.transform.Translate(Vector3.right * speed * Time.deltaTime); } else if (Input.GetKey(KeyCode.A)) { direction = 1; this.gameObject.GetComponent<SpriteRenderer>().sprite = prota[3]; this.gameObject.transform.Translate(Vector3.left * speed * Time.deltaTime); } // 攻击 if (Input.GetMouseButtonDown(0)) { // 处理鼠标左键点击事件 GameObject ins = Instantiate(bulletPrefab); Vector2 clickPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition); ins.GetComponent<Blogs>().clickPosition = clickPosition; if (direction == 0) { ins.transform.position = new Vector3(this.gameObject.transform.position.x, this.gameObject.transform.position.y + 0.15f); } else if (direction == 2) { ins.transform.position = new Vector3(this.gameObject.transform.position.x, this.gameObject.transform.position.y - 0.15f); } else if (direction == 3) { ins.transform.position = new Vector3(this.gameObject.transform.position.x + 0.15f, this.gameObject.transform.position.y); } else if (direction == 1) { ins.transform.position = new Vector3(this.gameObject.transform.position.x - 0.15f, this.gameObject.transform.position.y); } } }增加移动时脚步声
最新发布
05-17
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值