unity3d - 如何启动和停止子系统?
问题描述
就像标题所说的那样,我正在尝试使用 Invoke 功能的计时器启动和停止统一 3D 中的“复杂”部分系统,基本上是火炬的火焰发射。问题是,我可以停止 PS(部分系统),但无法重新启动它。
在创建一个数组之前,我尝试使用GetComponentsInChildren
不同的标签访问和标记 PS 的孩子。正如我之前所说,我可以成功地停止 PS,方法是在使用函数GetComponent<PartycalSystem>
之前标记主要对象并使用数组中的每个对象。Stop()
但是由于某种原因,我无法使用该Start()
功能以相同的方式重新启动它。
public bool blindmode = false;
public GameObject[] lightfx;
public GameObject[] torches;
void Start()
{
//getting the reference to the light Objects
torches = GameObject.FindGameObjectsWithTag("light");
lightfx = GameObject.FindGameObjectsWithTag("fx");
}
void Update()
{
if (blindmode==false)
{
Invoke("blindmodeon", 20);
}
if (blindmode==true)
{
Invoke("blindmodeoff", 20);
}
}
void blindmodeon()
{
blindmode = true;
foreach (GameObject torch in torches)
{
var fire = torch.GetComponent<Light>();
fire.enabled = false;
}
foreach (GameObject fire in lightfx)
{
var flame = fire.GetComponent<ParticleSystem>();
flame.Stop();
}
}
在代码的最后一部分中,我禁用了灯光和 PS。由于灯光部分工作得很好,我希望你只看一下粒子系统。
void blindmodeoff()
{
blindmode = false;
foreach (GameObject torch in torches)
{
var fire = torch.GetComponent<Light>();
fire.enabled = true;
}
foreach (GameObject fire in lightfx)
{
var flame = fire.GetComponent<ParticleSystem>();
flame.Play();
var child1 = transform.GetChild(0).GetComponent<ParticleSystem>();
child1.Play();
var child2 = transform.GetChild(1).GetComponent<ParticleSystem>();
child1.Play();
var child3 = transform.GetChild(2).GetComponent<ParticleSystem>();
child1.Play();
var child4 = transform.GetChild(3).GetComponent<ParticleSystem>();
child1.Play();
}
}
这是我最后一次尝试,也未能重新启用 PS。你可以从中猜到,PS 有它的母亲 PS 和 4 个孩子。
火把在 PS 激活时生成。调用的第一个计时器成功停止 PS。第二个计时器应该重新启动它,使用所述计时器创建一个 On 和 Off 循环,但它没有这样做。我尝试了很多东西,包括启用排放,但似乎没有任何效果。提前致谢!
解决方案
在
void Update()
{
if (blindmode==false)
{
Invoke("blindmodeon", 20);
}
if (blindmode==true)
{
Invoke("blindmodeoff", 20);
}
}
你重复添加一个调用......每一帧,所以在接下来的 20 秒后的 20 秒后,你可能会得到与你想要做的相矛盾的调用方法。
在我看来,你想把灯开 20 秒,然后一直开 20 秒,对吧?
我建议使用一种方法,例如
private bool blindmode;
private void ToggleLights()
{
// invert the flag
blindmode = !blindmode;
foreach (var torch in torches)
{
var fire = torch.GetComponent<Light>();
// set according to the flag
fire.enabled = !blindmode;
}
foreach (var fire in lightfx)
{
// here I would do GetComponentsInChildren
// passing true so we get also inactive children
var particleSystems = fire.GetComponentsInChildren<ParticleSystem>(true);
foreach(var system in particleSystems)
{
// according to the blindmode
if(blindmode)
system.Stop();
else
system.Play();
}
}
}
所以你可以使用InvokeRepeating
private void Start()
{
InvokeRepeating("ToggleLights", 0, 20f);
}
或者你也可以使用协程,比如
// yes, Start can be a Coroutine
private IEnumerator Start()
{
while(true)
{
ToggleLights();
yield return WaitForSeconds(20f);
}
}
或者如果您想坚持该Update
方法,请使用类似的计时器
private float timer = 20f;
private void Update()
{
timer -= Time.deltaTime;
if(timer > 0) return;
ToggleLights();
timer = 20f;
}
一般来说,尽量避免那些重复调用GetComponent
and GetComponentsInChildren
!而是打一次电话,例如Awake
,重新使用参考文献,例如
// rather directly store the type you want
public List<Light> torches = new List<Light>();
public List<ParticleSystem> lightfx = new List<ParticleSystem>();
private void Awake()
{
//getting the reference to the light Objects
var torchObjects = GameObject.FindGameObjectsWithTag("light");
var lightfxObjects = GameObject.FindGameObjectsWithTag("fx");
foreach(var torch in torchObjects)
{
torches.Add(torch.GetComponent<Light>());
}
foreach(var fx in lightfxObjects)
{
lightfx.AddRange(fx.GetComponentsInChildren<ParticleSystem>(true));
}
}
然后以后直接使用
foreach (var torch in torches)
{
torch.enabled = !blindmode;
}
foreach (var fire in lightfx)
{
if(blindmode)
fire.Stop();
else
fire.Play();
}
推荐阅读
- python - 在块 __name__ == "__main__" 中将变量声明为全局变量
- r - 如何访问在 Rmpi 请求之外创建的变量?
- angular - 订阅从ngrx的实体收集服务返回的observable没有返回正确的结果
- c# - 使用 DbContext 和 ADO.NET 的良好查询不返回任何结果
- javascript - JavaScript 中的错误 SQL 查询?
- python - Python:从嵌套的字典列表创建目录树
- c++ - 使用 unsigned int 时的无限循环
- r - 应用 group_by 和 summarise(sum) 但保留大量附加列
- tensorflow - 即使在冻结所有层之后,神经网络也需要时间来训练
- c++ - C++ 使用源代码、静态存档和其他动态库创建动态库