Precise Timers

MelodyCatsMelodyCats Member, PRO Posts: 128
edited October 2023 in Working with GS (Mac)

I know this is an age old discussion that's been covered at different times over the years - but also been struggling with this for over ten years!

My timers seem to work great on iOS, but there's always issues with android.. Somehow when the game runs on Android, the timer seems to be a fraction faster than real time, or not completely reliable.

So it eventually throws everything off. especially as Im dealing with a rhythm game, in which the taps need to correspond within milliseconds to the sound.

My question to other GS users is:

  • whether you've encountered a similar difference btw iOS and android?
  • whether you have a fail safe solution for using timers in Android?

my timers are based on: self.Time

Im wondering if it would make any difference to base them off device time... game.Clock?

Im not sure however, if device time is any different to game time, and also how you would set up a timer based off the device time... Any discussion on this would be really useful.

Comments

  • adent42adent42 Key Master, Head Chef, Executive Chef, Member, PRO Posts: 3,170

    game.Clock or actor.Time will be more accurate than timers but might come with a performance cost, so you’ll need to test.

    Not sure about why android timers are off for you, but it does jog something in my mind, so will take a look.

  • MelodyCatsMelodyCats Member, PRO Posts: 128

    Thanks @adent42 , I'll try playing around with that.

    If it's not timers the issue could be from audio launching at fractionally different times on Android...

    Can anyone give me an example of how you might be able set up a timer based on device time?

    As it's devided separately in minutes, seconds, milliseconds, not sure how to do that.

  • MelodyCatsMelodyCats Member, PRO Posts: 128
    edited October 2023

    So after a day working on this I think I'm getting somewhere with a timer based on device time.

    However if I dispay text:

    game.clock.seconds ..".".. game.clock.milliseconds

    After 60 seconds, it wil loop back to zero.

    Is there a way to keeps seconds going up... for example to 90 seconds and beyond etc..

    If I can solve the issue I'll write a proper explanatory post for anyone else struggling with timers in Android.

    EDIT:

    Sorry, I realize that doesn't make any sense... 4am my time, so I should probably get some sleep before posting ! :)

  • MelodyCatsMelodyCats Member, PRO Posts: 128

    So after various different tests it seems that the timers on Android (at least the one I have) run about 30% faster than a real timer. (game.time and self.time) I would set a stopwatch and the scene off at the same time to compare.

    At first I thought my app might be too performance heavy, and causing performance issues, so I created a minimal scene. Just a button that sets off a display of self.time and had the same result.

    Id be curious to know if anyone else is encountering this. Again, on iOS, Im not having this issue.

    Also on the GS team side, if there might know of a reason this could be happening and maybe fixable?

    For most of my apps its not a problem. Its only for one of them where gameplay is synced to music so it throws everything off.

  • MelodyCatsMelodyCats Member, PRO Posts: 128
    edited October 2023

    Ok, I'll just add a final comment on this as I don't want to keep bumping up the post.

    I have a workaround solution I thought I would share, as I was about to give up altogether. then thought try a last thing which, was to try and slow down my game timer by using interpolate.

    So, for example if I want my game timer to match real time I use interpolate.

    For 72 seconds

    Interpolate Attribute; GameTimer to 60

    Now I have a timer that is slower but when running on android very closely matches real time. Well enough to be usable.

    I would just add that I created my own interpolate to avoid any possible performance issues as follows:

    When self.Time < 72

    Constrain Attribute: GameTime to 60*( self.Time /72)

    Lastly, I'd just say this is testing from my own device I can't yet confirm how my workaround will work over multiple android devices.

    Hope that helps anyone who has a similar issue.

  • adent42adent42 Key Master, Head Chef, Executive Chef, Member, PRO Posts: 3,170

    Wow, thanks for all the diligent testing! I'll look more deeply into how we do timers in Android to see what's up. Are you using a high refresh rate device? (i.e. 90 or 120hz vs the traditional 60hz devices).

    I had to do some adjustments for those, and the adjustment might have screwed with the timers. Ideally, they shouldn't, but I was in a hurry to stop apps from crashing / going crazy when I put in that fix, so this definitely sounds like a possibility.

  • adent42adent42 Key Master, Head Chef, Executive Chef, Member, PRO Posts: 3,170
  • adent42adent42 Key Master, Head Chef, Executive Chef, Member, PRO Posts: 3,170

    Yup, that's totally it. The engine is assuming 60fps for simulation steps. This works really well if you're simulation can divide nicely by 60 (30 of 120hz), but 90 is an odd duck in this case. The short term solution would be to assume a 30fps target, which would work nicely in all cases. The "real" solution is to figure out how fix how the engine simulates "steps" or to force the OS to only request frames at a near 60fps rate.

    So @MelodyCats, your solution won't work for all devices, you'd have to figure out a way to detect native frame rate (something we don't provide to you ATM).

    If you're up for it, DM me your game's publishing page and point out where you're doing your adjustment hacks, so I can disable them. Then we can see if setting things to 30fps fixes things.

Sign In or Register to comment.