How do I decrease the number of times my void update() updates? - c#

I am currently working on a weather app, which uses an API that allows 500 requests a day. I realised that I run out of my daily requests within 5 seconds of running the app. That means my void update() is fetching the values 60 times a second (= frame rate). How do I decrease that to something like once every 15 seconds? Thank you so much in advance!
Currently my void update looks something like this
void Update()
{
StartCoroutine(GetAqiInfo());
}

How do I decrease the number of times my void update() updates?
First of all to answer your question directly, you can't really change the times the updates method gets called besides changing the frames per seconds. That wouldn't make a lot of sense tough.
I would advise you to rather check that your IEnumerator is working properly, because it seems that you call it each frame instead of calling it once again after it's done.
To fix that you can use the Coroutine type and check if it's currently running or not.
Coroutine current;
void Update() {
if (current == null){
current = StartCoroutine(GetAqiInfo());
}
}
Now we can edit the Enumerator to set the Couroutine to false after it's done and after there has been a certain delay.
If you also want to make sure that there aren't more than 500 requests you could check that before entering your IEnumerator.
int requests = 0;
IEnumerator GetAqiInfo()
{
if (request >= 500){
return;
}
// Get the Aqi Info and increase the request count by 1
request++;
yield return new WaitForSeconds(15f);
current = null;
}
Coroutine Documentation

I would suggest you to look into the InvokeRepeting.
Link Here
Instead of Update method, you should create another method to be invoked every given amount of time.
using UnityEngine;
using System.Collections.Generic;
public class ExampleScript : MonoBehaviour
{
public Rigidbody projectile;
void Start()
{
InvokeRepeating("RepeatedAction", 2.0f, 0.3f);
}
void RepeatedAction()
{
GetAqiInfo();
}
}

Related

Unity - Problem with while loop on embedded coroutines

Sorry if this is a newbie question, but I looked around and can't find any clue to fix my problem yet.
I am currently encountering a freeze when I try to run two coroutines together.
My end goal is:
to have one long coroutine representing the duration of a day.
one other smaller coroutine that will activate repeatedly while the day is not finished.
The two cotourines works fine independantly or when the second coroutine is directly embedded into the first one without the check on the endDay bool.
But when I tried to include the while loop, unity freeze at play (it reaches the 'DayStart.SetActive(true)' of the code below but does not go further).
Thinking the endDay bool being at the end of the first coroutine was probably the reason to the problem, I tried to build two completely independant ones (non-embedded coroutines with only the endDay bool as link between the two) but it didn't go better.
Does someone has an idea on how I could make it work?
For information, here is the code I initially used and that reverted the error. I spare you the detail of the second coroutine as it is quite long and probably not the problem here.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Transaction : MonoBehaviour
{
public GameObject DayStart;
public GameObject DayTracker;
private bool endDay;
private void Awake()
{
instance = this;
}
public void MainDayCycle()
{
StartCoroutine(MainDayCycleCO());
}
IEnumerator MainDayCycleCO()
{
endDay = false;
// Beginning of day picture
DayStart.SetActive(true);
yield return new WaitForSeconds(3);
DayStart.SetActive(false);
// [To be completed] Day Tracker bar
DayTracker.SetActive(true);
TradeCycle();
// Lancement de délai de journée et enregistrement de la fin
yield return new WaitForSeconds(20);
endDay = true;
}
public void TradeCycle()
{
while (endDay == false)
{
StartCoroutine(TradeCycleCO());
}
}
As I said this one
public void TradeCycle()
{
while (endDay == false)
{
StartCoroutine(TradeCycleCO());
}
}
Doesn't have any yield and this loop will freeze because nowhere inside the endDay is changed!
It sounds like what you rather want to do is (still don't have your TradeCycleCO code)
// Does this even need to be public?
public void TradeCycle()
{
StartCoroutine(TradeCycleCO());
}
IEnumerator TradeCycleCO()
{
while(!endDay)
{
// Your code here
// Make sure something yield returns in here
// If needed you could also interrupt at certain points via checking again
// Use that to do e.g. some cleaning up after the loop
if(endDay) break;
// or use that to immediately leave the coroutine overall
if(endDay) yield break;
}
// Code that may be executed after the day has ended e.g. for cleaning up stuff
}

How to make powerup timer?

I want to make countdown timer that will return value of bool when he is active , so I can check on other script if is active give double points if is not then you need to give normal points..
I want to make it more complicated and I want to add time on timer if the timer is active, if is not then we use default time on countdown...
I don't know how to use courutine specially when I need to add time if the timer is not over..
Lets say like a example:
I pick up power up and timer starts for 5 seconds counting to 0.
If i pick up again powerup and timer is on lets say 3 , Power up need to have now 8 seconds. When powerup is over he must go from 5 seconds when player pick up new one..
Here is my code that doesn't work how I want also my code doesn't have a function to add time to power up when power up is active.. In other words I don't know how i can check if powerup is active and if yes just to add to counter 5 more seconds..
Here is code that doesn't contain adding time it only contains working counter..
void startDoublePoints()
{
StartCoroutine("doublePoints");
Time.timeScale = 1;
}
//Simple courutine
IEnumerator doublePoints()
{
while (true)
{
yield return new WaitForSeconds(1);
timeLeft--;
}
}
I hope someone will explain me more about how I can achieve my goal.. I hope I explained what I need to achieve.. If you do not understand something please ask on comment and I will try to explain it again..
Thank you so much community I don't know how would I learn anything without this great place :)
float powerUpTimer;
bool isDoublePoints = false;
void Update()
{
// Check timer only when Power up time
if(isDoublePoints)
{
// Countdown the timer with update time
powerUpTimer -= Time.deltaTime;
if(powerUpTimer <= 0)
{
// End of power up time
isDoublePoints = false;
powerUpTimer = 0;
}
}
}
// Add any time player picks to timer
public void OnPickPowerUp(float buffTime)
{
isDoublePoints = true;
powerUpTimer += buffTime;
}

Why does why C# code keep crashing Unity? (I'm a beginner to Unity and C#)

Whenever I run my game it freezes, but it doesn't without this C# script.
I've tried changing around my code, and it works outside of Unity, in .NET (with some tweaks to certain functions) but when it's in Unity it crashes.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Throw : MonoBehaviour
{
public Rigidbody rb;
string final = "final:";
public float force = 1;
public float accuracy = 0;
void incto(float amount)
{
while (force < amount)
{
Debug.Log(force);
force++;
}
}
void decto(float amount)
{
while (force > amount)
{
Debug.Log(force);
force--;
}
}
void fstart()
{
while (true)
{
force = 1;
incto(200);
decto(1);
if(Input.GetKey(KeyCode.E))
{
Debug.Log(final + force);
break;
}
}
}
// Start is called before the first frame update
void Start()
{
fstart();
}
// Update is called once per frame
void FixedUpdate()
{
Debug.Log(force);
}
}
It should decrease and increase the force value, then stop when you press E, but Unity just crashes.
Unity takes care of the while(true) for you. Unity's while(true) calls your FixedUpdate, you just need to fill it in.
Unity only captures keystrokes once per frame, so Input.GetKey(KeyCode.E) will always return the same value. Unity crashes because of your while(true) is an infinite loop.
More info: https://docs.unity3d.com/Manual/ExecutionOrder.html
i belive that unity starts catching key strokes after the first frame, not before, try moving fstart() behind a first run bool in the FixedUpdate function
oh and this will hang the entire program every time it executes a frame.....
The code crashes because you have an infinite loop here:
while (true)
{
}
It will never exit the loop so nothing more happens. Just put that code into Update() method, which gets called by the engine on every frame, it will do the trick

Second Coroutine isn't working Unity

I am making 2D game and want to cause delay of about 3 sec after player's all lives ran out. I tried to implement Coroutine method before the scene start all over again but it doesn't work.
I have already implemented Coroutine method for each time my player falls of a cliff and respawn back to its position. And it works like a charm.
public void Respawner()
{
StartCoroutine("RespawnCoroutine");
}
// Coroutine Delay of 2 sec for each time player Respawn
public IEnumerator RespawnCoroutine()
{
classobj.gameObject.SetActive(false);
yield return new WaitForSeconds(respawnDelaySec);
classobj.transform.position = classobj.respawnPoint;
classobj.gameObject.SetActive(true);
}
public void ReduceLives()
{
if (lives <= 3 && lives >= 2)
{
lives--;
live_text.text = "Remaining Live " + lives;
}
else
{
StartCoroutine("RestartScene1");
}
}
public IEnumerable RestartScene1()
{
yield return new WaitForSeconds(RestartSceneDelaySec);
SceneManager.LoadScene("demo2");
}
here is no error on console window but SceneManager.LoadScene("demo2"); is never called and the player is respawning each time after i die and after 1 life remaining
The issue with your second coroutine is..
You have mistakenly used "IEnumerable" instead "IEnumerator", make it change to "IEnumerator" and it will work..
You should not call SceneManager.LoadScene("demo2"); after StartCoroutine("RestartScene1");.
StartCoroutine("RestartScene1"); this code you can say is an asynchronous code. It is called, and the execution of program keeps going forward (the execution does not await here). You should call the code you want to delay inside that Coroutine after yielding.
Small exampel:
public void SomeFunction()
{
StartCoroutine("RestartScene1");
// The code here will **not** be delayed
}
public IEnumerable RestartScene1()
{
yield return new WaitForSeconds(RestartSceneDelaySec);
// The code here will be delayed
}

Keeping several countdown timers using a queue

I need to keep up to an X (changeable amount) instances of countdown timers, each being added by the user, once a single one of them reaches 0 it calls for a function while the other counters keep counting.
for that purpose i tried to create a queue of them, but as it turns out, I can't change the value of an iteration variable in foreach:
public struct Debuff
{
public float Timer;
public int Stack;
public int MaxStack;
...
}
public Debuff Poisoned;
public void CalcDamage(...)
{
...
if (Poisoned.Stack < Poisoned.MaxStack)
{
Poisoned.Stack++;
PoisonStacksTimer.Enqueue(Poisoned.Timer);
InvokeRepeating("Poisoning", 0.1F, 1F);
}
else
{
PoisonStacksTimer.Dequeue();
PoisonStacksTimer.Enqueue(Poisoned.Timer);
}
}
public void Poisoning()
{
foreach(float PTimer in PoisonStacksTimer)
{
TakeDamage(Poisoned.DmgTranslate);
PTimer -= Time.deltaTime; // here lies at least one of the problems
if (PTimer <= 0)
{
Poisoned.Stack--;
PoisonStacksTimer.Dequeue();
CancelInvoke("Poisoning");
}
}
}
is there any other way to use countdown timers in queue? or maybe a better way to achieve my objective?
this is my first time asking a question here so I hope I explained my problem clearly.
Off the top my head, I'd use coroutines.
Every time you need to start a timer, you start an associated coroutine, so if you, at a specific moment, have for example 4 active timers, there'll be 4 coroutines.
In order to keep a reference to every single coroutine, use a List<IEnumerator>: every time a timer needs to be started, add the new IEnumerator reference and start the coroutine, so when a coroutine ends naturally or needs to be stopped, you can remove that reference from the list while keeping the other alive coroutines' references in the list.

Categories

Resources