- Home /
Making a timer that ends on a consistent update
Hello! I am making a snake clone to get a better understanding of unity and coding. It uses 1 1x1 block that is the head, what you control. And a body block that is Instantiated to the head and waits to be destroyed at the right time. The head moves 1 block in any direction and will move again in a given direction after a certain amount of time. Each time it moves, it instantiates the body block to the head's position. The snake body script immediately use Invoke("DestroySelf" , snakeLength * snakeSpeed). This way it will destroy itself when the head has moved it's full length. However, since it the timer might end slightly before or slightly after an update, the end of the snake will get longer or shorter then they should be. Is there a way to have the body destroy itself on a consistently so it lands on the same update away from when it was instantiated?
Answer by Kennai · Jul 31, 2019 at 08:02 AM
Hello, @GlassesGuy !
Are you sure that your time is correct for snake? If snake has higher speed, then lifetime of block should be shorter, shouldnt it? Maybe you need to devide snakeLength by snakeSpeed and multiply it by some value if needed (to increase overall lifetime)?
Also, instead of always instantiate and destroy game objects, maybe better to store a list of objects and just move last snake block to a new head position? If you are interested in it, I can explain how to do it ;)
Answer by GlassesGuy · Jul 31, 2019 at 10:45 PM
@Kennai , It's multiplied because the speed is really just the amount of time it takes before it moves another block, so the smaller the speed value is the faster the snake goes. I thought it made sense to instantiate and destroy objects so there isn't a limit since the snake can get longer based on how many apples it eats. I'm looking into tracking the amount of updates and maybe using that to trigger the timing on the snake. It would probably work the way I want but depending on what device you use the snake will be faster or slower so if you have any suggestions I would love to hear them!
Okay! So...
First, you need a function, which will "move" your snake. You will call this function in Update after some time, lets say, every 1 second or 0.5 - this value will represent your snake speed. Best way is to do something like this:
public class snake
{
public float speedTime = 0.5f;
private float nextTime = 0f;//time when we need to call func $$anonymous$$oveSnake
private void Start()
{
nextTime = Time.time + speedTime;
}
private void Update()
{
if(nextTime<Time.time)
{//time to move snake
nextTime += speedTime;
$$anonymous$$oveSnake();
}
}
private void $$anonymous$$oveSnake()
{//all magic with blocks is here
}
}
then you can change speedTime at runtime and your snake will go faster or slower!
Now we only need to figure out best way to move blocks.
Have you heard about List object? I suggest you to use it
$$anonymous$$ain idea is to store all your snake blocks in a list.
Lets say, your snake has 4 blocks at start, it means you will have a list with 4 elements, where first element means tail (index 0) and last element means head (index 3).
Then your snake do "movement" - it means that you need to move block from tail position to head position, right?
So you take your index 0 element and set it position to new head position (where your snake is moving). After that index 3 wont be head anymore. Head will be index 0 now.
I mean, you will need additional attribute where you will store head index.
after some amount of time your snake do movement again, it means that you need to move block from tail to head again. your head is index 0, then your tail index is (headIndex + 1) =1.
You take element with index headIndex+1 and move it to new snake position. after that you increment headIndex again .
so by math your index will look like
//get tail index
tailIndex = (headIndex + 1) % snakeList.count;
//after you move your tail block to head, you will have new head index:
headIndex = tailIndex;
Now we need figure out how to increase or decrease length.
Probably, we will add new blocks to tail (new added block will have same pos as tail block) and remove not needed blocks from tail too (if you need to cut or something). I suggest to write func for add 1 block and write func to cut 1 block. then, if you need to add or cut few blocks - just call func few times.
in func AddBlock - you will need:
1. instantiate new block 2. get tail index 3. copy position from tail block to new added block 4. insert your new block into list at position tailIndex
in func CutBlock you will need:
1. get tailIndex
2. destroy object at tailIndex
3. remove element from list at tailIndex
probably, that's all. I hope you got main idea :)
if you will have questions, let me know ;)
Your answer

Follow this Question
Related Questions
Can't seem to destroy instantiated objects. 1 Answer
Can a Network.Instantiate()'d object be Object.Destroy()'d? 0 Answers
Checking Instantiate/Destroy has been called | Checking number of scene GameObjects 1 Answer
Proper/Best way to Instantiate and Destroy with Unity Networking? 2 Answers
instantiate,destroy,gain speed in time 2 Answers