I've trying to do a multiple timer in flutter, when one ends, another one should start, for some reason, when the first timer ends, the next one doesn't begin. Here is the code
Timer timer;
//Create the sets
void startSets(){
startTimer(10,0); //10 seconds, 0 minutes
for(int i=0; i<sets;i++){
for(int j=0;j<exercises;j++){
startTimer(15,0); //15 seconds, 0 minutes
}
startTimer(12,0); //12 seconds, 0 minutes
}
}
void stopTimer(){
timer.cancel();
}
void startTimer(int seconds, int minutes){
timer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
if(seconds>0){
seconds--;
}else if(seconds==0 && minutes>0){
minutes--;
seconds = 59;
}else{
timer.cancel();
}
minText=minToString(minutes);
secText=secToString(seconds);
});
});
}
minText and secText are global variables which I use for a Text Widget
Your code doesn't match your description. You say you want one Timer to start when another one ends, but startSets start all its Timers at the same time without any waiting. If you actually want only one Timer in-flight at a time, you will need to create a queue that you process when each Timer completes.
One way to do it would be something like (this is untested code):
var timerQueue = Queue<Duration>();
Timer currentTimer;
//Create the sets
void startSets() {
timerQueue.add(Duration(seconds: 10));
for (var i = 0; i < sets; i++) {
for (var j = 0; j < exercises; j++) {
timerQueue.add(Duration(seconds: 15));
}
timerQueue.add(Duration(seconds: 12));
}
startNextTimer();
}
void stopTimer() {
currentTimer?.cancel();
currentTimer = null;
}
void startNextTimer() {
if (timerQueue.isEmpty) {
return;
}
var duration = timerQueue.removeFirst();
var seconds = duration.inSeconds % 60;
var minutes = duration.inMinutes;
assert(currentTimer == null);
currentTimer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
if (seconds > 0){
seconds--;
} else if (seconds == 0 && minutes > 0) {
minutes--;
seconds = 59;
} else {
currentTimer.cancel();
currentTimer = null;
}
minText = minToString(minutes);
secText = secToString(seconds);
if (currentTimer == null) {
startNextTimer();
}
});
});
}
declare timer variable inside startTimer method like this
void startTimer(int seconds, int minutes){
Timer timer;
...
}
so that for every time startTimer is called it will be declared
Related
I want to spawn a 100 object whit 0.1 seconds in between.
I have this but they still spawn all at once.
private float timer = 0.0f;
bool goSpawn = false;
private void Update()
{
if (goSpawn)
{
timer += Time.deltaTime;
}
}
public void spawnAnimals()
{
goSpawn = true;
for (int i = 0; i < 100;)
{
if (timer > 2f)
{
RndSpawnPos = new Vector3(Random.Range(3.30f, 5.70f), 0.78f, Random.Range(-3.00f, 3.01f));
Instantiate(animal, RndSpawnPos, Quaternion.identity);
i++;
timer = 0.0f;
}
}
}
Use an IEnumerator. I put an example to solve the problem:
public void Start() => StartCoroutine(SpawnObject(100, .1f));
public IEnumerator SpawnObject(int count, float intervalTime)
{
for (var i = 0; i < count; i++)
{
Instantiate(" something in here...");
yield return new WaitForSeconds(intervalTime);
}
}
i would like to have a Timer runing once in main.dart to check user activity
#override
void initState() {
super.initState();
initPlatformState();
_fetchMasterData("a", "b");
_startActivityTimer();
}
bool _activityTimerRunning = false;
void _startActivityTimer() {
if (!_activityTimerRunning) {
Timer.periodic(Duration(seconds: 5), (timer) {
_timerTicked(timer);
setState(() {
_activityTimerRunning = true;
});
print("Timer started");
});
}
}
But initState gets called more than once, so it is not the right place to register the timer. Where should it be placed?
The code in the question has i silly mistake, the print statement is in the wrong place. Here is the working code:
#override
void initState() {
super.initState();
initPlatformState();
_fetchMasterData("a", "b");
_startActivityTimer();
}
void _startActivityTimer() {
print("Timer started");
Timer.periodic(Duration(seconds: 5), (timer) {
_timerTicked(timer);
});
}
"TimerStarted" get executed only once
Try this sample code.
int start = 5;
fName(){
Timer _timer;
const oneSecond = Duration(seconds: 5);
_timer = Timer.periodic(
oneSecond,
(Timer timer) => setState((){
if(start == 0)
timer.cancel();
else{
_activityTimerRunning = true;
start -= 1;
}
})
);
}
When you want to start you timer, call fName() method, after that timer can started. So and also you can check condition, when
if(start != 0){
...
}
I have this 3 buttons
When I press the hit button, it plays one animation and the interactable button is set to off for a time period with "bt.interactable = false;".
After that time period, it is set to true.
And it let me play again after that time.
However, the second play of the animation only works if I play one of the other buttons before I play the "hit button" again.
This is the code that leads with the button timer:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ldbutton : MonoBehaviour
{
public Image loading;
public Button bt;
int sec;
string pl1_name = "Unicorn";
public int counterclick;
bool buttonLocked;
Firebase_Bridge FB = new Firebase_Bridge();
int tmp_sec;
int totalSeconds = 0;
int TOTAL_SECONDS = 0;
async void Start()
{
if (bt.name.Equals("SpecialHitButton")){
string time = await FB.LoadData_player_timeplsuperhit(pl1_name);
sec = int.Parse(time);
}
if (bt.name.Equals("HitButton"))
{
string time = await FB.LoadData_player_timeplhit(pl1_name);
sec = int.Parse(time);
}
if (bt.name.Equals("DefendButton"))
{
string time = await FB.LoadData_player_timepldefend(pl1_name);
sec = int.Parse(time);
}
Debug.Log("star");
tmp_sec = sec;
bt.onClick.AddListener(() =>
{
loading.fillAmount = 1.0f;
bt.interactable = false;
if (counterclick < 2)
{
bt.interactable = false;
sec = tmp_sec;
if (sec > 0)
{
bt.interactable = false;
totalSeconds += sec;
}
TOTAL_SECONDS = totalSeconds;
StartCoroutine(second());
}
}
);
}
IEnumerator second()
{
bt.interactable = false;
Debug.Log("second");
yield return new WaitForSeconds(1f);
if (sec > 0)
{
sec--;
fillLoading();
StartCoroutine(second());
}
if (sec == 0)
{
counterclick = 0;
totalSeconds = 0;
TOTAL_SECONDS = 0;
//sec = 0;
StopCoroutine(second());
Debug.Log("termina");
yield return new WaitForSeconds(1f);
StartCoroutine(wait());
}
}
IEnumerator wait ()
{
bt.interactable = true;
bt.enabled=true;
return null;
}
void fillLoading()
{
Debug.Log("fillLoading");
totalSeconds--;
float fill = (float)totalSeconds / tmp_sec;
loading.fillAmount = fill;
Debug.Log("update");
}
}
And this my animator:
Does anyone know what is happening?
I would like to use my circlecollider2d as a sort of force field to push objects back for a given amount of time, on button press. Here is the code I have, to simply turn it on and off again.
void Update()
{
if (Input.GetKey(KeyCode.Space))
{
GetComponent<CircleCollider2D>().radius = 25.0f;
}
else
{
GetComponent<CircleCollider2D>().radius = 2.1f;
}
}
You can use Invoke to call a function after x number of seconds. I modified your code below to clear the force field 5 seconds after it is activated. The forceFieldActive flag will prevent it from being activated again while it's already active.
int forceFieldDuration = 5; //5 second duration
bool forceFieldActive = false;
void Update()
{
if (Input.GetKey(KeyCode.Space) && forceFieldActive == false)
{
forceFieldActive = true;
GetComponent<CircleCollider2D>().radius = 25.0f;
Invoke("DisableForceField", 5);
}
}
void DisableForceField()
{
GetComponent<CircleCollider2D>().radius = 2.1f;
forceFieldActive = false;
}
Note: You can also use a coroutine which is more efficient as Draco18s mentioned in the comments. It would look like this:
int forceFieldDuration = 5; //5 second duration
bool forceFieldActive = false;
void Update()
{
if (Input.GetKey(KeyCode.Space) && forceFieldActive == false)
{
forceFieldActive = true;
GetComponent<CircleCollider2D>().radius = 25.0f;
StartCoroutine(DisableForceField());
}
}
IEnumerator DisableForceField()
{
yield return new WaitForSeconds(forceFieldDuration);
GetComponent<CircleCollider2D>().radius = 2.1f;
forceFieldActive = false;
}
//A simple countdown timer
var myTimer : float = 5.0;
function Update () {
if(myTimer > 0){
myTimer -= Time.deltaTime;
}
if(myTimer <= 0){
Debug.Log("GAME OVER");
}
}
This is a countdowntimer script I just want it to show it up on the screen while it counts down .
Put it OnGUI() such as
function OnGUI () {
GUI.Label (Rect (10,10,150,100), myTimer.ToString());
}
You probably also want to have this outside the Update() method, and have the logic run only when it's necessary. This can be done by using the InvokeRepeating method like this (C#):
float myTimer = 5.0f;
void Start() {
InvokeRepeating( "DecreaseTime", 1, 1 ); // Called every second
}
void DecreaseTime() {
myTimer--;
}
void onGUI() {
GUI.Label(new Rect(10,10,400,90), "myTimer = " + myTimer );
}