Skip to content

doc: Input gathering tips and tricks#452

Merged
elementbound merged 5 commits intomainfrom
doc/input-gathering-tutorial
May 10, 2025
Merged

doc: Input gathering tips and tricks#452
elementbound merged 5 commits intomainfrom
doc/input-gathering-tutorial

Conversation

@elementbound
Copy link
Copy Markdown
Contributor

@elementbound elementbound commented Apr 29, 2025

Closes #402

Rendered page

Comment on lines +12 to +16
To have a shared notion of time, *netfox* provides its own time synchronization
and a *tick loop*. The *tick loop* will check how much time has passed since
the last network tick, and will run as many ticks as needed to catch up. Most
often this is a single tick every few frames, but in special cases it might
need to run multiple ticks in a single loop.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling out why we use network ticks over physics ticks can provide clarity on why this is necessary

Suggested change
To have a shared notion of time, *netfox* provides its own time synchronization
and a *tick loop*. The *tick loop* will check how much time has passed since
the last network tick, and will run as many ticks as needed to catch up. Most
often this is a single tick every few frames, but in special cases it might
need to run multiple ticks in a single loop.
To have a shared notion of time, *netfox* provides its own time synchronization
through its *tick loop*, which handles network ticks. Network ticks are similar
to physics ticks, with the exception that they dynamically speed up or slow
down to keep all clients in synchronized time. Using physics ticks on two
separate machines may cause drift and desync issues, and as such aren't suited
for multiplayer. The *tick loop* will check how much time has passed since the
last network tick, and will run as many ticks as needed to catch up. Most often
this is a single tick every few frames, but in special cases it might need to
run multiple ticks in a single loop.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More context is better context, though I didn't want to elaborate on that here - my idea was to give the absolutely minimal description ( what the thing is, but not why or how ), and for further details, direct the reader to the network time guide.

Maybe some extra context would make sense in the NetworkTime guide? What do you think?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think context is important where it's going to be used. Having someone read through this doc without proper context would make it harder to grasp exactly why it's done this way, and directing them to an entirely different document with more information than is needed could overwhelm them. No reason it couldn't be in both places, but I see this document as part of a starting point for people to understand the networking, whereas minimal context is more for already experienced devs.

Comment on lines +21 to +26
Since multiple ticks may be ran in a single tick loop, it makes no sense to
gather input for each tick - the hardware wouldn't update, since the ticks are
run one after the other.

Instead, ticks are gathered *before* each tick loop. This explains why special
measures need to be taken in some cases.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple ticks being run in a single loop do need input gathered for each tick though. If ticks 7, 8, 9 get run for the same tick, all ticks should register a held action, but only tick 7 should register a just_pressed action.

Suggested change
Since multiple ticks may be ran in a single tick loop, it makes no sense to
gather input for each tick - the hardware wouldn't update, since the ticks are
run one after the other.
Instead, ticks are gathered *before* each tick loop. This explains why special
measures need to be taken in some cases.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but I don't see yet how that leads to your suggestion of deleting those lines.

If ticks 7, 8 and 9 get run in the same loop, it makes no sense to check inputs again - they will yield the same value, as the OS hasn't updated the input devices yet. Hence running the gather code before the loop.

And the mentioned special measure is explained later, which makes it possible to have a just pressed input on tick 7, and a held input on 8 and 9.

My intention was to shed some light on why the examples and BaseNetInput use the before loop signal for input gathering.

Could you please clarify / rephrase your reasoning? Thanks!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Referenced in a below comment.

Comment on lines +62 to +66
0 is Empty
1 is Up
3 is Right: Tick
4 is Up
6 is Right: Tick
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be in line with the majority comment below, and have a non-tick contain a right input to break the correlation of right being pressed coinciding with Tick.

Suggested change
0 is Empty
1 is Up
3 is Right: Tick
4 is Up
6 is Right: Tick
0 is Up
1 is Up
2 is Up
3 is Right: Tick
4 is Up
5 is Right
6 is Right: Tick

Comment on lines +101 to +102
_movement_buffer = Vector3.ZERO
_movement_samples = 0
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would cause artifacting. If ticks 7, 8, 9 were run simultaneously, 7 would be gathered as movement, and 8, 9 would be given a movement vector of 0, even if you've been holding the buttons down continuously.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so - _gather() only runs at the start of the loop, and then the same values are recorded for ticks 7, 8, and 9. Please let me know if I'm missing something!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I was misunderstanding how _Gather applied its inputs for this and the comment for lines 21-26. If this doesn't cause an issue then the other comment shouldn't be an issue either.

Comment on lines +124 to +126
Godot provides methods such as [Input.is_action_just_pressed()] to check if a
given input was just pressed. Counterintuitively, this does not work as
expected - let's see it on a timeline:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explaining the reason why it doesn't work with netfox would be beneficial to teach readers:

Suggested change
Godot provides methods such as [Input.is_action_just_pressed()] to check if a
given input was just pressed. Counterintuitively, this does not work as
expected - let's see it on a timeline:
Godot provides methods such as [Input.is_action_just_pressed()] to check if a
given input was just pressed. Unfortunately, the built in function of
[Input.is_action_just_pressed()] is hard-coded to work with physics ticks and
process ticks, but won't work with our network ticks. See the below example:

Comment on lines +144 to +145
This can be solved by sampling the input on each `_process()`, and setting the
corresponding variable to true:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing sticky inputs through the _input override may be a better practice, don't have an example to suggest though.

@elementbound elementbound merged commit e6e9c7d into main May 10, 2025
2 checks passed
@elementbound elementbound deleted the doc/input-gathering-tutorial branch May 10, 2025 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add extended tutorial on input gathering

2 participants