-
-
Notifications
You must be signed in to change notification settings - Fork 95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add stopwatch functionality to the Timer node #2878
Comments
Stopwatch functionality requires careful filesystem handling to avoid naming conflicts (or you need to store all timers used by the project into a single file using JSON or similar). Also, some people may want to prevent timer manipulation while the app is closed, which means encryption would have to be used. As you can see, there's not "one true way" to implement a stopwatch that works across app restarts. Due to this, I think this should be an add-on instead. Speedrun timers or game time tracking might be fairly common functionality in more polished games, but you generally won't need it in earlier stages of development. |
Sorry if I was unclear: the time_elapsed property wouldn't persist across app restarts, it would persist across the timer restarting itself after time_left is < zero. When one_shot = false the time_left property is set to the wait_time after the timer times-out to keep going, the time_elapsed property would not be reset when that happens. It would be reset when the timer is started again manually in code. |
All you really need to do to track that time is to use Using timers would be excessive for long tracked sessions, and if you want to have a real time clock visible, you can just use delta in the process func. |
This sounds like a good use case to me already. I've also needed this kind of functionality for speedruns. I foresee that this enhancement won't be implemented in core. Due to this, I think it makes sense to create The byproduct of creating a separate implementation for
|
@Xrayez I think even if a |
I think he implies that |
Yeah, what I mean is that timer/stopwatch functionalities are fairly distinct to warrant making a separate class for both. If you type "stopwatch" in Google, you'll see both "TIMER" and "STOPWATCH" tabs: So, I'd say these features mutually complement each other. Therefore, this is something Godot could have as well, in theory. But being complete is not part of Godot's development principles, since the development is based on concrete use cases as used by majority of real-life projects using Godot instead, and not because a particular feature complements the other. This is why I've added this proposal to goostengine/goost#7 as well, because the feature is clearly in alignment with Goost goals. See also https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well. |
What I'm proposing is adding only one property to the timer node that keeps track of how long it has been since the timer was last started. That's it. This would solve my use case of tracking the time and the uses of many users in the forums who's problems I linked to. I get that time can be tracked by using delta in the process function (that's what the timer node does in the source code), but telling users to deal with that doesn't seem to make much sense to me. Why provide functionality for a timer to count down in a node, but tell users who want to count up that they have to do it themselves? The current time_left property counts down already, the proposed time_elapsed property would just count up. They're two sides of the same coin. |
I'd rather have a separate |
@likeich Again, you don't need a timer to know how much time has elapsed. You just need to call And for real time counters like that speedrunning example a new node is better be introduced as suggested by others, though it can be done as an addon easily. (Timer node is more versatile than just a controller for counting time, so it makes sense to have in core). |
@pycbouh While not impossible to get around, the problem I deal with doing that is that my code would become much more complex. My launcher works by caching different sections of the ui when they are not in use and removing them from the tree. Using the proposed time_elapsed property would keep me from having to change between these ui sections and saving each time spent whenever a ui section is left. A timer would automatically stop whenever it exited the tree and I would only have to save the time_elapsed once: right before the app closes. The beauty of the property would be that I could:
I can't imagine a stopwatch requiring a whole new node but I'm interested to hear what others have to say about that |
So you rely on the node being removed from the tree to "pause" a timer? I can see why the proposed solution would be complicating things, but that's a bit of a hack itself. That said, we've probably spent more time discussing it here (combined) than it would take to make a nice and reusable bit for your project. I've made a time tracker plugin for Godot, and it tracks how much time you spend on each main tab (2D, 3D, Script, etc) so I have a point of reference for that sort of task. |
I have implemented
If you look at the exact implementation, it's indeed similar to As a bonus, the editor has separate icons for both My rule of thumb is: when we have separate objects in the real world that are used differently, this already signifies that those should be implemented as separate classes. Of course, there are types of timers that do include stopwatch functionality, but any universal tool is less useful in solving a specific task effectively, at least that's the way I see it. |
Btw, Timer node may be removed in a future version, same as Tween has been refactored, see godotengine/godot#41794 (comment) |
Timer can be used without any script, which wasn't true for Tween node. So I don't think it will be removed. |
Can it though? 🙃 You can set it up and start it in the Inspector, true, but can you actually use it in any meaningful way without a script that reacts to its |
You can e.g. connect |
@Xrayez Please don't use magic keywords in your repositories like that as you can actually close the issue here being a member and GitHub doesn't mind 🙃 |
Oh sorry, I usually remove closing keywords when I decide to merge PR, my bad. The only reason why I link PRs like that is because people stumbling upon the proposal can already find a potential solution to the problem, and I've basically resolved it, even if it's not directly solved by Godot core developers officially. |
Describe the project you are working on
An Android launcher. I want to be able to easily keep track of how long the user spends time in each app drawer that my app provides.
Describe the problem or limitation you are having in your project
It requires a stopwatch to keep track of elapsed time, which the Timer node seems like it should provide. It is not intuitive to build a timer that starts whenever a section of the ui is clicked and saving the elapsed time when the app is exited or the ui is clicked again.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Adding a simplistic stopwatch ability to the current Timer node would make it really easy to keep track of time.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
I think the best bet would be to add the simplest stopwatch functionality possible and to require the least amount of code. My proposal is to add one new property to the Timer node: time_elapsed. This would complement the already-used time_left property. However, instead of counting down when the timer is started, it would count up.
The time-elapsed property would persist on timer resets from one_shot being false and would only stop counting when the stop() function is called or the timer is started again. The benefit to persisting time_elapsed is that the timeout signal could still be called at specific intervals to update other parts of the code. For example, if the user wants to make a second counter from a label in their game, the wait time could be set to 1 and the label would be updated from the timeout signal.
Speedrun timer example code:
The timeout signal is ignored in this code.
Second counter example code:
I'm using the 3.x connection code b/c I don't know how the new connections work.
Note: The time_elapsed property could be completely ignored and the Timer would still work as it is currently used.
If this enhancement will not be used often, can it be worked around with a few lines of script?
It could, but I think that this is a widely-used capability that would require few enough changes to enable in core.
An example of a stopwatch in code can be found here: https://godotforums.org/discussion/18694/how-to-make-a-stopwatch-in-godot
Another example: https://godotengine.org/qa/3641/how-display-elapsed-time-in-game
Search "stopwatch in godot" for many users asking how to make this functionality in their games.
Is there a reason why this should be core and not an add-on in the asset library?
This solves a very common use case and makes sense being a part of the timer node.
Non-exhaustive list of use-cases:
The text was updated successfully, but these errors were encountered: