Hello, I have the following code and thought it would increase the spawnRate over time, but…it doesn’t. Can you give me a hint why? I tried to follow another thread int his forum.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Spawner : MonoBehaviour
{
public float spawnRate = 1f;
public GameObject circlePrefab;
private float timeToSpawn;
public int DelayAmount = 1;
protected float Timer;
void Update()
{
if (Time.time >= timeToSpawn)
{
Instantiate(circlePrefab, Vector3.zero, Quaternion.identity);
timeToSpawn = Time.time + 1f / spawnRate;
Timer += Time.deltaTime;
if( Timer >= DelayAmount)
{
spawnRate++;
}
}
}
}
It certainly seems like it might but then loops with gradually changing values both internal (spawnRate) and external (Time.time) are hard to reason about without seeing actual values.
To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.
Doing this should help you answer these types of questions:
is this code even running? which parts are running? how often does it run?
what are the values of the variables involved? Are they initialized?
Knowing this information will help you reason about the behavior you are seeing.
Welcome to debugging. First thing is to check if the code is even running. Add Debug.Log statements to the code and see if they are showing up in the console. Use as many as you want! You can always remove them later.
Otherwise, the most common mistake I see is people forget to attach scripts to a gameobject in the scene and that object needs to be active.
Will do that, however I am happy to learn and if this is a bit complicated, would there be a better/easier way to increase the spawn rate by a bit each second (or 5 seconds or whatever?
if it doesn´t reach that line, then the value of Timer is always smaller than DelayAmount (100k).
Do a “Debug.Log(Timer);” on line 26 (before you do your if statement), to see what the value of Timer is. As long as it is smaller than 100k it will not reach that line. So wether you decrease the value of DelayAmount or you have to wait longer.
Edit: Just saw right now, that your debug line is outside of the brackets! If you don´t use brackets after an if statement, it means in C#, that only the next line will be part of the if statement, so put that line with the Debug.Log… into the brackets
Right now, the “delayamount checked” debug belongs to the if statement, but because your open curly bracket { comes after the debug call, then really spawnRate and the “spawnrate increased” debug are on their own.
My guess is you don’t see “delayamount checked” is because your DelayAmount value is set to 100000f. Remember to Debug.Log values as well. In this case, I would suggest printing out the value of Timer to see how long it takes before it gets >= to 100000f.
thank you. I found out that (after tweaking my debugs haha) indeed everything was running “correctly”, but the increase was too much for the game, whatever I did, it got unplayable too fast → too many objects in the scene, not cool. but I admit spamming Debugs was very helpful :)!
therefore I moved from the spawner to the hexagon itself to increase the speed of those instances over time (just like that small indiegame you might have heard of, tetris). it’s a better idea, but this also is more complicated than I thought or I cant google correctly.
code below, but the problem again is it increases the value extremely fast (well, it’s ++ in the end). I didnt find any way to increase it slowly without stubling across things like lerping, but I can’t believe increasing the shrinkSpeed value gradually over a certain amount of time is so complicated (the debug is called)?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Hexagon : MonoBehaviour
{
public Rigidbody2D rb;
public float shrinkSpeed = 3f;
public float currentShrinkspeed;
public float targetShrinkspeed;
void Start()
{
rb.rotation = Random.Range(0, 360f);
transform.localScale = Vector3.one * 10f;
}
void Update()
{
transform.localScale -= Vector3.one * shrinkSpeed * Time.deltaTime;
if (currentShrinkspeed < targetShrinkspeed)
shrinkSpeed++;
Debug.Log("JOHOHO");
if (transform.localScale.x <= .05f)
{
Destroy(gameObject);
}
}
}
I’m going to give you some advice. Walk through your logic. Ask yourself questions as you step through your code.
But the only thing I can tell you is your code shows nothing to adjust currentShrinkSpeed or targetShrinkSpeed. So if current is < target, then shrinkSpeed will increase every frame. Now, imagine you get 60 fps, within 1 sec, shrinkSpeed is now 60.
These are all things you should be able to figure out if you just look at your code and think, when does this code execute and if I don’t want it to execute, what logic do you need.
You mentioned wanting to easily change a value over time, or every X seconds, etc., look to Invoke() or InvokeRepeating() for this. Invoke() is more flexible because you can have it call itself and change the amount of time between invokes:
Invoke("doThing", 3);
void doThing() {
// spawnRate++ or whatever you need
Invoke("doThing", Random.Range(1,5);
}
Hi seejayjames, great suggestion, I think that is exactly what I am looking for.
I’ve tried this for 2 scenarios: Spawning objects and changing the speed of them. The first one works fine:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Spawner : MonoBehaviour
{
public float spawnRate = 1f;
public GameObject hexagonPrefab;
private float timeToSpawn = 0f;
void Start()
{
InvokeRepeating("SpawnObject", 3, 3);
Debug.Log("Invoke Activated");
}
void SpawnObject()
{
if (Time.time >= timeToSpawn)
{
Instantiate(hexagonPrefab, Vector3.zero, Quaternion.identity);
timeToSpawn = Time.time + 1f / spawnRate;
}
}
}
The second one however does not. I suspect the update method messing around with it but couldnt find a solution for this. The “Shrinkspeed Increased” Debug does not get called once. Is there any way to use the Invoke like this? I already found out that I cant just put in in the Update also
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Hexagon : MonoBehaviour
{
public Rigidbody2D rb;
public float shrinkSpeed = 3f;
void Start()
{
rb.rotation = Random.Range(0, 360f);
transform.localScale = Vector3.one * 10f;
InvokeRepeating("IncreaseShrinkSpeed", 5, 1);
Debug.Log("Invoke Activated");
}
void IncreaseShrinkSpeed()
{
shrinkSpeed++;
Debug.Log("Shrinkspeed Increased!");
}
void Update()
{
transform.localScale -= Vector3.one * shrinkSpeed * Time.deltaTime;
if (transform.localScale.x <= .05f)
{
Destroy(gameObject);
}
}
}
Hmm, strange, seems like it should be fine. Update won’t interfere with these, and in fact you can call an Invoke from Update, but you can’t have the Invoke function itself inside Update (you can’t nest any function in another one). However, changes to variables in Update will affect the values of variables inside an Invoked function, just like any other function.
I know I am a bit baffled too, as exactly the same works fine for the other one, but I tested again and nope, only way I can get the IncreaseShrinkSpeed method to do something is to add it to Update and then well it gets called a bazillion times again…
Wait a minute…your console messages shouldn’t print out “Invoke Activated” more than once per run (in Start) but the time indices show they’re one second apart?
Edit: Oh, must be multiple instances of your Hexagon object. If so, then…hmm. Very strange.
Always try quitting and restarting Unity and renaming the method, because sometimes “things” happen…
yes hexagon spawns every second (it bascially is a very simple clone of super hexagon I use to test new stuff)
I dont know, for some reason no Invoke at all works in that particulart hexagon script. I just stopped trying and will do some other stuff because time is a limited resource and it is not really “needed” to finish anything, but still it is strange that it works in all scripts but this one.
Extremely strange…one last thought is to make another script for it, new name etc, and delete the old one. Or just make another script attached to the same hexagon object with just one Invoke() doing whatever, and see if that works. But yeah, time is an issue too…