我目前正在尝试以给定的速率实例化游戏对象。通常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;
}
}
答案 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
的任何内容再次调用。