C# 动态协同程序名
如何使协同程序的名称成为动态的? 我使用它使目标在几秒钟后自动死亡:C# 动态协同程序名,c#,unity3d,coroutine,C#,Unity3d,Coroutine,如何使协同程序的名称成为动态的? 我使用它使目标在几秒钟后自动死亡: void InitiateKill(int i) { //i is the number of the target StartCoroutine(TargetDie(i, timeAlive/1000)); //some other stuff } 当目标在计时器结束前被杀死时,我显然会得到一个错误,因为它无法再次杀死目标 这就是为什么我想停止特定目标的协同进程,但我不知道如何停止 我试过: Corout
void InitiateKill(int i)
{
//i is the number of the target
StartCoroutine(TargetDie(i, timeAlive/1000));
//some other stuff
}
当目标在计时器结束前被杀死时,我显然会得到一个错误,因为它无法再次杀死目标
这就是为什么我想停止特定目标的协同进程,但我不知道如何停止
我试过:
Coroutine b[i] = StartCoroutine(TargetDie(i, timeAlive/1000));
但这会产生语法错误<代码>b[i]不能用于协同程序
如何以正确的方式进行此操作
更新:
这是我的TargetDie功能的(相关部分):
IEnumerator TargetDie(int i, float delayTime)
{
yield return new WaitForSeconds(delayTime);
Destroy(targets[i]);
}
当玩家杀死目标时,我会:
void Damage(int i)
{
// at this time, the first Coroutine, started in InitiateKill, should stop, because otherwise it tries to destroy the target twice
StartCoroutine(TargetDie(i, 0));
}
因此,最简单的方法是,在对象本身上移动协程
public class DieScript: MonoBehaviour
{
private Manager manager;
public void StartDeathProcess(Manager manager)
{
this.manager = manager;
StartCoroutine(DieAsync(manager));
}
private IEnumerator DieAsync(Manager manager)
{
yield return new WaitForSeconds(timer);
Destroy(this.gameObject);
}
public void Dmaage() // This is register as listener for death of the object
{
this.manager.PropagateDeath(this);
Destroy(this.gameObject);
}
}
public class Manager:MonoBehaviour
{
private List<DieScript> die;
void InitiateKill(int i)
{
die[i].StartDeathProcess(this);
}
}
公共类DieScript:monobhavior
{
私人经理;
公共无效StartDeathProcess(管理器)
{
this.manager=经理;
start例程(DieAsync(manager));
}
专用IEnumerator DieAncy(管理器管理器)
{
产生返回新WaitForSeconds(计时器);
摧毁(这个游戏对象);
}
public void Dmaage()//这是注册为对象死亡的侦听器
{
这个。经理。死亡(这个);
摧毁(这个游戏对象);
}
}
公共类经理:单一行为
{
私人名单;
无效启动码(int i)
{
die[i].StartDeathProcess(this);
}
}
试图在控制器上保持控制将带来更多的痛苦而不是解决方案
您可以有一个IEnumerator列表来跟踪正在运行的协同程序。但是您仍然需要来自对象的消息来通知控制器它已死亡。所以你错过了这一部分。
您需要在目标上使用脚本,以便控制器了解此类型。
控制器运行协同程序,并引用该脚本,询问每个帧是否正在死亡。当目标注定死亡时,它会设置一个布尔值来通知。使用Destroy可以将对象保留到帧结束,这样它就可以工作了
但这注定会在以后失败。让一个控制器做所有事情有点违背编程概念。您应该更多地将其视为信息的旁路 您只需在销毁null之前检查null,就不会出现任何错误:
if (targets != null)
Destroy(targets[i]);
但是如果您想停止旧的协同程序,下面是推荐的方法
您可以使用
字典
来处理它。使用inti
作为键,使用Coroutine
作为值
调用InitiateKill时,将int i
添加到字典中,启动协同程序时,将coroutine
也添加到字典中作为值
调用Damage
时,检查字典中是否存在该int值。如果是,则使用它检索协同路由
值并停止旧的协同路由。如果没有退出,则启动一个新的协同程序,然后将其添加到该字典中
字典应如下所示:
Dictionary<int, Coroutine> dyingTarget = new Dictionary<int, Coroutine>();
新的Damage
函数现在检查项目是否已在字典中,然后重试,停止协同程序并将其从字典中删除
void Damage(int i)
{
// at this time, the first Coroutine, started in InitiateKill, should stop, because otherwise it tries to destroy the target twice
StopIfAlreadyRunning(i);
Coroutine crt = StartCoroutine(TargetDie(i, 0));
//Add to Dictionary
dyingTarget.Add(i, crt);
}
void StopIfAlreadyRunning(int i)
{
Coroutine crtOut;
//Retrieve and stop old coroutine if it exist then removes it
if (dyingTarget.TryGetValue(i, out crtOut))
{
StopCoroutine(crtOut);
dyingTarget.Remove(i);
}
}
新的TargetDie
函数,在杀死它后将其从字典中删除。在销毁之前,它还会检查null
:
IEnumerator TargetDie(int i, float delayTime)
{
yield return new WaitForSeconds(delayTime);
if (targets != null)
Destroy(targets[i]);
//Remove from Dictionary
dyingTarget.Remove(i);
}
你把目标的号码存储在什么地方了吗?如果你想让它自动停止,你可以在TargetDie函数中完成。值得解释一下这个函数在做什么,什么时候应该停止运行是的,它的名字是:target0,target1。。。这与协同程序部分有什么关系?@Programmer:我更新了我的问题,因为首先你应该在目标上运行协同程序,这样当它死亡时它会自动停止。否则,您需要从目标获取一些引用,以便目标可以传播它死亡的事实。或者某个循环,如果项目已死亡,则会中断协同程序。我了解如何在目标上运行协同程序。但是我所有的代码,包括StartCodes,都在一个叫做Controller的不同的空游戏对象上。这太棒了,谢谢你的回答和解释!很高兴你发现我的回答很有帮助
IEnumerator TargetDie(int i, float delayTime)
{
yield return new WaitForSeconds(delayTime);
if (targets != null)
Destroy(targets[i]);
//Remove from Dictionary
dyingTarget.Remove(i);
}