InvokeRepeating()限制? (C#)

时间:2014-08-26 23:24:45

标签: c# unity3d

我目前正在尝试以给定的速率实例化游戏对象。通常InvokeRepeating可以完成这项工作,除了在实例化对象时我不希望速率为常量这一事实。

我知道应该在代码的Start()部分内调用InvokeRepeating。所以我的问题是:有什么方法可以解决这个问题,还是我必须采取不同的方法?

提前谢谢大家!

以下是代码的一部分,说明了我所说的问题:

using UnityEngine;
using System.Collections;

public class InstantiateLARSpider : MonoBehaviour {

public float instantiateRate;
public GameObject xSpider;
private Vector3 position;
public float minimumSpeed;

void Start () {

    // instantiateRate is a variable that I want to modify over time.  
    InvokeRepeating("NewSpider", 1.0f, instantiateRate);
}

void NewSpider ()
{
    position = new Vector3(transform.position.x, Random.Range(-4.5f,4.5f), 0);
    Debug.Log("Instantiated");
    var Spider = Instantiate(xSpider, position, Quaternion.identity) as GameObject;
    if(transform.position.x>=11.0f){
        Spider.rigidbody2D.velocity = new Vector2(-1.0f * Random.Range(minimumSpeed, 6.0f), 0.0f);
    }
    else if(transform.position.x<=-11.0f){
        Spider.rigidbody2D.velocity = new Vector2(1.0f * Random.Range(minimumSpeed, 6.0f), 0.0f);
    }
    //I was thinking about increasing the instantiateRate by 0.1 every time a Spider is instantiated.
    instantiateRate -= 0.1f;
    minimumSpeed += 0.1f;
}

}

3 个答案:

答案 0 :(得分:2)

在这种情况下,在用于调用InvokeRepeating之后更改instantiateRate并不会实际更改InvokeRepeating收到的参数的副本。要镜像InvokeRepeating的功能,您可能会得到类似于以下内容的内容:

    public delegate void MethodToCall(); //A delegate - you can pass in any method with the signature void xxx() in this case!
    public IEnumerator InvokeRepeatingRange(MethodToCall method, float timeUntilStart, float minTime, float maxTime)
    {
        yield return new WaitForSeconds(timeUntilStart);
        while (true)
        {
            method(); //This calls the method you passed in
            yield return new WaitForSeconds(Random.Range(minTime, maxTime))
        }
    } 

我没有在这台机器上安装Unity,所以我无法验证编译(主要是Random.Range部分,其余我非常熟悉)。你在案件中称之为的方式是:

    void Start()
    {
        StartCoroutine(InvokeRepeatingRange(NewSpider, 2, 5, 10));
    }

    void NewSpider() //Since NewSpider matches the signature void xxx(), we can pass it to InvokeRepeatingRange()
    {
        //...
    }

调整InvokeRepeatingRange中的参数和逻辑以获得所需的效果,可能:

    public delegate void MethodToCall();
    public IEnumerator InvokeRepeatingDecreasingTime(MethodToCall method, float timeUntilStart, float minTime, float maxTime)
    {
        float currentTime = maxTime;
        yield return new WaitForSeconds(timeUntilStart);
        while (currentTime >= minTime)
        {
            method();
            currentTime -= .1f;
            yield return new WaitForSeconds(currentTime);
        }
    }

希望这能为您提供一种思考这种做事方式的新方法,并回答您原来的问题。

编辑:更新以获得更好的变量名称和更多解释。       添加了StartCoroutine()调用,如评论中所述!

答案 1 :(得分:2)

为什么不在Update方法中执行,而不是使用InvokeRepeating?您可以使用字段来跟踪上次创建新对象的时间。

private float lastTimeCreated;
private float timeBetweenCreation;
...

void Start()
{
    // Initial time between object creation
    this.timeBetweenCreation = 1f;
}

void Update()
{
    float now = Time.time;

    // Check if it's time to create a new object
    if (now - this.lastTimeCreated > this.timeBetweenCreation)
    {
        this.NewSpider();

        // Object created, so set new lastTimeCreated
        this.lastTimeCreated = now;

        // Some logic to change your timeBetweenCreation.  Do it here or in NewSpider().
        // this.timeBetweenCreation = ...
    }
}

void NewSpider ()
{
    // Mostly what you had
    position = new Vector3(transform.position.x, Random.Range(-4.5f,4.5f), 0);
    Debug.Log("Instantiated");
    var Spider = Instantiate(xSpider, position, Quaternion.identity) as GameObject;
    if(transform.position.x>=11.0f){
        Spider.rigidbody2D.velocity = new Vector2(-1.0f * Random.Range(minimumSpeed, 6.0f), 0.0f);
    }
    else if(transform.position.x<=-11.0f){
        Spider.rigidbody2D.velocity = new Vector2(1.0f * Random.Range(minimumSpeed, 6.0f), 0.0f);
    }

    // Some logic to change your timeBetweenCreation.  Do it here or in Update().
    // this.timeBetweenCreation = ...
}

答案 2 :(得分:2)

由于您希望以不断变化的速率进行实例化,我会使用Invoke代替InvokeRepeating

void Start () {
    Invoke("NewSpider", 1.0f);
}

void NewSpider () {
    ...
    Invoke("NewSpider", instantiateRate);
}
首先会在NewSpider内调用

Start。然后,在NewSpider方法结束时,NewSpider将被设置为instantiateRate的任何内容再次调用。