协同没有开始

时间:2017-07-07 09:12:32

标签: unity3d yield coroutine

当我发射武器时,我使用闪电GameObject预制件来获得视觉效果。当我开火时,我启用了闪电对象,并且我有一个通用组件,在一定延迟后停用它。

问题是"应该等待"永远不会达到日志,而不是等待设置的延迟,它等待的时间要长得多,并且实际上并没有停用GameObject。

这里是DeactivateAfter组件的代码

public class DestroyAfter : MonoBehaviour {

    [SerializeField]
    private float delay;
    private bool firstRun = true;

    void OnEnable () {
        if (firstRun == false) {
            StartCoroutine(DestroyMethod());
        }
        firstRun = false;
    }

    public IEnumerator DestroyMethod() {
        Debug.LogFormat("Should wait; Time: {0}", Time.time);
        yield return new WaitForSeconds(delay);
        Debug.LogFormat("Should deactivate; Time: {0}", Time.time);
        gameObject.SetActive(false);
    }
}

4 个答案:

答案 0 :(得分:3)

条件永远不会成立,您需要先将firstRun条件设置为true。

private bool firstRun = **true**;

void OnEnable () {
    if (firstRun == **true**) {
        StartCoroutine(DestroyMethod());
    }
    firstRun = false;
}

我想首先设置旗帜,然后再做你想做的事情:

private bool firstRun = **true**;

void OnEnable () {
    if (firstRun == **true**) {
        firstRun = false;
        StartCoroutine(DestroyMethod());
    }    
}

答案 1 :(得分:1)

我认为你应该使用粒子系统来解决你的武器问题。无论如何,我认为您的代码无法正常工作,因为您正在停用游戏对象而不是停用该组件。使用以下内容激活和停用组件:

gameObject.GetComponent<YourComponent>().enabled = false;

答案 2 :(得分:1)

第一个解决方案 - 实例化并销毁延迟

如果我理解正确的话,闪电游戏对象已经是一个预制你在射击时实例化你想要在延迟后销毁它。

因此,在实际调用脚本后,使用实例化和销毁可以更简单地完成,而不是使用Coroutine解决方案并启用或禁用对象:

 
GameObject obj = GameObject.Instantiate(yourPrefab, position, rotation);    
GameObject.Destroy(obj, delay);

只要您向调用类提供yourGameObject,就可以从任何地方调用此函数。所以你甚至不需要一个自己的课程。

第二个浮点参数是以秒为单位的延迟(参见API

例如,你可以有一个类似的射击课:

public class Shooting : MonoBehavior 
{

    [SerializeField]
    private GameObject lightningPrefab;

    [SerializeField]
    private float delay;

    public void OnShooting(Vector3 position, Quaternion rotation){
        GameObject obj = GameObject.Instantiate(lightningPrefab, position, rotation);

        /* Directly after instantiating the Object
         * you can already "mark" it to be destroyed after x seconds 
         * so you don't have to store it as variable anywhere */
        GameObject.Destroy(obj, delay); 
    }
}

然后您还可以添加一些检查以不经常产生预制件:

[...]

private GameObject lightningObject;

public void OnShooting(Vector3 position, Quaternion rotation){
    if(lightningObject == null ){
        lightningObject = GameObject.Instantiate(lightningPrefab, position, rotation);            

        GameObject.Destroy(lightningObject, delay);
    }
}

通过这种方式,一次只有一个闪电物体。

第二个解决方案 - 超时

另一种不必一直实例化和销毁对象的方法是简单的超时而不是Coroutine:

public class Shooting : MonoBehavior 
{
    [Tooltip("The lightning Object")]
    [SerializeField]
    private GameObject lightningObject;

    [Tooltip("The time in sec the lightningObject stays visible")]
    [SerializeField]
    private float visibleDelay;

    /* track the time that passed since the last OnShooting call */
    private float timePassed;

    /* Additional bool to not perform Update when not needed */
    private bool isVisible;

    /* Update is called once each frame */
    private void Update(){
        /* If the object is not visible do nothing */
        if (isVisible != true) return;

        /* update the timePassed */
        timePassed += Time.deltaTime;

        /* if delay passed since last OnShooting call 
         * deactiavte the object */
        if (timePassed >= visibleDelay){
            lightningObject.SetActive(false);
        }
    }

    public void OnShooting(){
        /* Activate the Object */
        lightningObject.SetActive(true);

        /* set isVisible */
        isVisible = true;            

        /* reset the timePassed */
        timePassed = 0;
    }
}

答案 3 :(得分:0)

嗯。您的代码在我的项目中运行良好。

我正在做什么,某个对象有你的脚本,我停用然后在场景播放时激活gameObject。

你的毁灭方法是公开的。 检查你的项目,也许某处调用StopAllCoroutines()或StopCoroutine(DestroyMethod());