Trying to program a timer to do something when it reaches 5 seconds - unity3d

I can't seem to figure out what to do here. I'm creating a learn to type game where if the user doesn't get the word correct in 5 seconds, they lose a life.
Either this could be implemented by counting down to 0 from 5, or counting up to 5.
I tried using the stopwatch for c# system diagnostics, which works for everything except I can't figure out how to check when it hits 5 seconds. It is a time object you cant compare it to an int.

you have two options here.
You can check the time in the Update function with Time.time or Time.deltaTime, or you can use a Coroutine with the new WaitForSeconds(5) object.
It could be as simple as:
float time;
void Update()
{
time += Time.deltaTime;
if(time > 5)
{
LoseALife();
}
}
If you need to restart the timer each time you complete a word you might have an aditional method like:
public void RestartTimer()
{
time = 0;
}
This would make the timer go back to 0 any moment you need it.

Related

UNITY | Update or InvokeRepeating?

I use many timers in my Unity project, they done like this:
void Update()
{
timer -= Time.deltaTime;
if(timer < 0)
{
DoSomething();
}
}
And in every google link they looks like this.
But today i found (im newbie) InvokeRepeating(); method.
So here is updated timer
int timer = 60;
void Start()
{
InvokeRepeating("Timer", 1f, 1f);
}
void Timer()
{
timer -= 1;
}
So why people change timers in Update()?
And which method less inpact on performance?
Depends!
As usual in programming there are most of the time multiple valid solutions for a problem.
In my eyes the bigest difference is that InvokeRepeating is also working on inactive GameObjects or disabled Components while Update is only called while the object is active and the component enabled.
Note, however, that your current examples do different things. To make them equivalent it should look like either
void Start()
{
timer = 1f;
}
void Update()
{
timer -= Time.deltaTime;
if(timer < 0)
{
timer = 1f;
DoSomething();
}
}
or
void Start()
{
InvokeRepeating(nameof(DoSomething), 1f, 1f);
}
Btw: A third basically equivalent solution would be a Coroutine (which is basically a temporary Update method - in fact the MoveNext call gets executed right after the Update would)
// Yes, Start can be an IEnumertaor and is in this case internally implicitly started as Coroutine!
IEnumerator Start()
{
while(true)
{
yield return new WaitForSeconds(1f);
DoSeomthing();
}
}
As mentioned by Kuruchy: There is also a difference in behavior related to the timeScale.
Update: since it uses Time.deltaTime to decrease the timer it will be affected by the time scale
→ in order to avoid this you would need to use Time.unscaledDeltaTime instead. But afaik still if setting Time.timeScale = 0; then Update isn't called at all.
Coroutine: Similar to update the WaitForSeconds is also timeScale dependent.
→ in roder to avoid this you would need to use WaitForSecondsRealitme but afaik even then setting Time.timeScale = 0; would lead to the routine not getting called at all.
InvokeRepeating: Fromt he docs I can only see that
This does not work if you set the time scale to 0.
not sure how it reacts to the timescale though but I would actually guess the same. Though, here there is no real work around like for the other two.
Performance wise you most probably don't even have to care! I guess it would be over-optimizing.
However my guess would be that Update is actually slightly faster since there you already know the method reference while when using InvokeRepeating you are passing it as a string which is additionally error prone and means that internally Unity has to find that method first.
Without going into too much detail is because of the performance.
The Update() method is invoked internally by Unity and they've done a pretty good job in optimizing it.
InvokeRepeating is much slower in comparison. First of all because the initial method invocation is using the Reflection to find the method you want to start and it's respective calls also take more time than Update. And you want to avoid using Reflection in your code as much as possible.
Here is nice, short article in which the tests were performed between these two methods - http://www.kittehface.com/2017/09/unity-performance-with-invokerepeating.html

Why does my game freeze inside coroutine?

sorry if this question is very basic. I created a coroutine that detects collisions every 5 seconds. Inside this coroutine I would like to execute an animation for 3 seconds so I came up with this bit of code:
private IEnumerator OnCollisionStay2D(Collision2D collision)
{
if (collision.collider.tag == "mama") {
//interrupt movement
float currentTime = Time.time;
float madBegin = Time.time;
while (currentTime - madBegin < 3)
{
personAnimator.runtimeAnimatorController = Resources.Load("Animations/human1mad_0") as RuntimeAnimatorController;
currentTime = Time.time;
Debug.Log(currentTime);
}
isAngry = true;
}
yield return new WaitForSeconds(5);
}
I logged the elaped time in the while loop and currentTime does not seem to be updating. As a result, the elapsed time equals 0 and my while loop never exits. Furthermore since this is executing in a coroutine that is supposed to run concurrently I don't get why a nonexiting while loop would freeze the entire game.
Clarification is much appreciated.
From the Unity docs on Time.time
The time at the beginning of this frame (Read Only)
This means that your Time.time will not change over the course of your loop so the difference between currentTime and madBegin will always be 0.
Time.realtimeSinceStartup may be what you're looking for.

Is There A Consistent Method That's Not Fixed/Update() or OnGUI() in Unity?

So, I'm working on a unity project and I find myself with functions that don't need to be called 33 times per second or every 0.02 seconds. I'm not sure how often then GUI renders. Is there a method like the aforementioned that takes place maybe.. four times per second?
Because if not, I'd have to make one and that seems like it in itself will cost resources.
You can create the method that has to be executed X times per second, and call it using InvokeRepeating.
Something like this:
InvokeRepeating("methodName", 0.0, 1.0/X);
You could call this one in the Start() function.
//Example (executing "methodName" 4 times per second).
void Start(){
InvokeRepeating("methodName", 0.0, 0.25f);
}
for this cases you can use a corrutine
this method can help you
void Start(){
StartCoroutine(yourMethod());
}
IEnumerator yourMethod()
{
while(true){
// do something every 4 seconds
yield return new WaitForSeconds(4);
}
}
important
every method that you create with IEnumerator must to be called inside the Coroutine();
yield return new WaitForSeconds(4) put this method to wait for 4 seconds.

Sound for collision only once

Ive got the following code to check for agent collision.
I want to fire a MIDI message only once when they start colliding.
Ive got this so far.
void draw(){
//Loop through people, and check collision, then play note, if intersecting
for(int i=0;i<people.size();i++){
Person p = people.get(i);
p.collide(people,collisions);
p.triggerMidi();
p.run();
}
}
public void collide(ArrayList<Person> people, ArrayList<Person> connections) {
for(Person other : people) {
if (other != this) {
if (this.collide(other)) {
this.isIntersecting=true;
//connections.add(other); // when a collision is found, add it to a list for later use.
}
}
}
}
void triggerMidi(){
if(!hasPlayed && this.isIntersecting==true){
MIDI.sendNoteOn(channel, agentNote, 127);
delay(200);
MIDI.sendNoteOff(channel,agentNote, 127);
hasPlayed=true;
}
}
This works to play the sound only once at the start of collision.
But how do I get it to play again at the start of another collision.
Obviously I have to set hasPlayed back to false.
But where?
When I set it to false in the collide loop, the sound play a million times.
Any ideas?
First off, you probably shouldn't have a call to delay() from your drawing thread. That will cause your sketch to become laggy and unresponsive. Instead, you might want to put your sound playing on a different thread.
Then, to answer your original question- do you know how long the note plays for? If so, just record the time that the note starts, and then use that time to check the elapsed time. The millis() function might come in handy for that. When the elapsed time is greater than the duration of the note, then you can set hasPlayed back to false.

Time Delay for a process in Unity 3D

I have to give the delay for the process to happen, which I am calling in the Update function.
I have tried CoUpdate workaround also. Here is my code:-
function Start()
{
StartCoroutine("CoStart");
}
function CoStart() : IEnumerator
{
while(true)
{
yield CoUpdate();
}
}
function CoUpdate()
{
//I have placed the code of the Update().
//And called the wait function wherever needed.
}
function wait()
{
checkOnce=1; //Whenever the character is moved.
yield WaitForSeconds(2); //Delay of 2 seconds.
}
I have to move an object when a third person controller(which is another object) moves out of a boundary. I have included "yield" in my code. But, the problem happening is: The object which was moving when I gave the code for in the Update(), is moving, but isn't stopping. And it is moving up and down. I don't know what is happening! Can someone help? Please, thanks.
I am not entirely clear what you are trying to accomplish, but I can show you how to set up a Time Delay for a coroutine. For this example lets work with a simple cool down, much like you set up in your example. Assuming you want to continuously do something every 2 seconds while your game is running a slight modification can be made to your code.
function Start()
{
StartCoroutine(CoStart);
}
function CoStart() : IEnumerator
{
while(true)
{
//.. place your logic here
// function will sleep for two seconds before starting this loop again
yield WaitForSeconds(2);
}
}
You can also calculate a wait time using some other logic
function Start()
{
StartCoroutine(CoStart);
}
function CoStart() : IEnumerator
{
while(true)
{
//.. place your logic here
// function will sleep for two seconds before starting this loop again
yield WaitForSeconds(CalculateWait());
}
}
function CalculateWait() : float
{
// use some logic here to determine the amount of time to wait for the
// next CoStart cycle to start
return someFloat;
}
If I have missed the mark entirely then please update the question with a more detail about what you are attempting to accomplish.
I am not 100% sure that I understand you question but if you want to start one object to move when the other is out of bound then just make a reference in the first object to the second object and when the first object is out of bounds (check for this in Update of the first object) call some public function StartMove on the second object.
I wouldn't suggest CoRoutines. It can sometimes crash your computer. Just define a variable and decrement it. Example:
private float seconds = 5;
then do anywhere you want to delay:
seconds -= 1 * Time.deltaTime;
if(seconds <= 0) {your code to run}
This will make a delay of 5 seconds. You can change 5 to any value to change the number of seconds. Also you can speed up the decrement by changing the value of 1. (This is mostly useful when you want to sync 2 delayed actions, by using the same variable)
Hope this helps. Happy coding :)