How to make powerup timer? - c#

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;
}

Related

How to subtract hundreds/thousands of times a second in unity?

I am currently working on an idle game but am having trouble with time. The code below runs when a business is activated in order to prevent the player activating the business again before it finishes. The variable "subtractTime" is the time it takes for the business to finish multiplied by 100.
There are different kinds and levels of businesses that require a different amount of time each. When you upgrade the business to certain levels, the time it takes to make money cuts in half.
When the time is lower than a second, the code below works as it is fast enough to not be able to tell it can't keep up. However, when dealing with larger amounts of time, such as 6 seconds, it does not subtract fast enough.
while (subtractTime > 0)
{
completed = false;
yield return new WaitForSeconds(.01f);
subtractTime = subtractTime - 1;
}
There are multiple ways to achieve that.
One simple way is to just wait until the timer has finished:
IEnumerator StartCooldown(float subtractTime) {
subtractTime *= 0.1f;
completed = false;
yield return new WaitForSeconds(subtractTime);
completed = true;
}
The only problem with this is that you don't have the remaining time updated as time passes, which may be useful for other things such as a cooldown bar.
A workaround to that would be something like this:
IEnumerator StartCooldown(float subtractTime) {
subtractTime *= 0.1f;
completed = false;
while (subtractTime > 0) {
subtractTime -= Time.deltaTime;
yield return null;
}
completed = true;
}
Time.deltaTime is just the time elapsed between the last frame and the current one, and yield return null just stops the execution of the Coroutine and resumes it on the next frame.
Note: you can remove the subtractTime *= 0.1f; line in both examples if the value you pass to the function is in seconds, since both examples work with time measured in seconds :)
The problem is the fixed time WaitForSeconds(.01f) because you don't know if the players' CPU can keep to that schedule, it may be too slow or be busy on other tasks. Instead we use the time it took to complete the game loop each frame, which is called Time.deltaTime:
IEnumerator ITimeSomething(float timeLimit)
{
float t = 0;
while (t < timeLimit)
{
t+= Time.deltaTime;
yield return null;
}
// do something when the time runs out
}

My second game object is working on background

I have two cheesbar in the game... once finished the other appears...and there is "eat button". when a mouse approaches to chees that button is being activated and make continueeating bool active. And I press and hold the button , cheese is being eaten and when cheese finished , second game object appears which means second cheese bar, somewhere, but start as a half cheesebar ...so even if it has SetActive(false); in the beginning , it is decreasing as if it was activated... how can I correct this.
thanks in advance.
void Start ()
{
eatingcheese = maxcheese;
eatingcheese2 = maxcheese2;
}
void Update ()
{
cheesebar.fillAmount = eatingcheese / maxcheese;
cheesebar2.fillAmount = eatingcheese2 / maxcheese2;
if (continueeating)
{
eatingcheese--;
eatingcheese2--;
hungerscript.gettinghungery+=1.5f;
}
if (eatingcheese <=0)
{
cheesebar.gameObject.SetActive(false);
cheesebar2.gameObject.SetActive(true);
}
}
public void eating()
{
continueeating = true;
}
public void stopeating()
{
continueeating = false;
}
I notice that in the code
if (continueeating)
{
eatingcheese--;
eatingcheese2--;
hungerscript.gettinghungery+=1.5f;
}
You decrement eatingcheese2 whether or not cheesebar2 is active. You could check to see if the cheese is ready to be eaten and only proceed with decrementing eatingcheese2 if it is. You could use an integer to track which cheese you are currently eating to do that, and a switch statement to decrement either value based on that state. Or if you are sure you'll only ever have two cheeses, you can use a bool and an if statement.
Note that Update() is framerate dependent and you are dealing with eatingcheese numbers that will be very large (since they decrement every update while being eaten). I would suggest using a float from 1 to 0 representing whole and fully eaten cheese, and I would also recommend multiplying the amount eaten each step by Time.deltaTime so avoid the issue of scaling too fast and unpredictably.

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.

Difficult C# if then logic

Object is forced up. After 10 seconds, object will be forced back down. Alternatively, object can be clicked and thereby forced back down before 10 seconds has elapsed.
What is currently happening: If object is forced down, GAME OVER.
What I am trying to do instead: If object is forced down before you are able to click it, GAME OVER.
In other words, the GAME OVER is being shown in 10 seconds, regardless of whether or not the object was clicked.
I'm having a really difficult time with this logic and I am hoping a fresh perspective might be able to help.
public void FixedUpdate() {
// Increase the kick timer
kickTimer += Time.fixedDeltaTime;
// If the next kick time has came
if (nextKick < kickTimer) {
// Schedule the kick back corresponding to the current kick
nextKickBacks.Enqueue (nextKick + 10f);
// Apply the kick force
rb.AddForce (transform.up * thrust, ForceMode.Impulse);
// Plan the next kick
nextKick = kickTimer + Random.Range (MinKickTime, MaxKickTime);
}
// If there are more kick backs to go, and the time of the closest one has came
if (0 < nextKickBacks.Count) {
if (nextKickBacks.Peek () < kickTimer) {
// Apply the kick back force
rb.AddForce (-transform.up * thrust, ForceMode.Impulse);
// Show the GAME OVER gameObject
GameObject.Find ("icetextureONfile").transform.localScale = new Vector3 (0.02f, 0.02f, 0.02f);
// Dequeue the used kick back time
nextKickBacks.Dequeue ();
}
}
}
void OnMouseDown()
{
rb.AddForce(-transform.up * thrust,ForceMode.Impulse);
}
}
You need to add the logic for what happens when you click on the object. Right now you are applying force, but there is nothing in the code changing the state of the Update loop.
I don't know what type of game you are making. So I am not sure what you want to do when the click is executed, but I am guessing you want to reset the kickbacks.
In that way you can do something like this. Change .Clear() to whatever method suits your needs.
void OnMouseDown()
{
rb.AddForce(-transform.up * thrust,ForceMode.Impulse);
nextKick = 0; // reset timer to force a new kick to be set next frame
nextKickBacks.Clear(); // clear current set kickbacks
}

Make a bonus last for 3 seconds in XNA

I'am building a game in XNA, and I'am very new to XNA as well, but I got to start somewhere. Almost everything in my games works perfect. It is an topview racing game. The only problem is that I want to last the bonuses, that I pickup from the map last for a given time, like 3 seconds, I know that I need to use a timer, but I don't know how I should use it.
this is a part of code, I use when the car collides with a tile of my map:
if (map[x][y] == 0)
{
if (speedBonus)
{
car.speed = 450;
}
else
{
car.speed = 200;
}
I hope one of you guys can help me with this problem, because I have spent like 2 hours fixing it, but my code didn't help me out. Thanks in advance!
You'll want to record the time the bonus was picked up, which you can save into a DateTime object. Then, during each iteration of your main loop, check to see if the TimeSpan is greater than 3 seconds. If so, remove the bonus.
Thanks for the help, I fixed my code this way:
With 2 variables on top:
float timer = 3;
const float TIMER = 3;
And in the update:
if (map[x][y] == 0)
{
if (speedBonus)
{
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
timer -= elapsed;
car.speed = 450;
if (timer <= 0)
{
speedBonus = false;
timer = TIMER; //Reset Timer
}
}
else
{
car.speed = 200;
}
it now works like a charm, thanks for the help!

Categories

Resources