Skip to content

feat: implement NetworkTickSystem based on NetworkUpdateLoop#502

Merged
jeffreyrainy merged 6 commits intodevelopfrom
feature/networktick
Feb 26, 2021
Merged

feat: implement NetworkTickSystem based on NetworkUpdateLoop#502
jeffreyrainy merged 6 commits intodevelopfrom
feature/networktick

Conversation

@jeffreyrainy
Copy link
Copy Markdown
Contributor

Implements the very minimal part of a tick system we need for synced networked variables.

I tried to keep it to the bare minimum and avoid any difficult design decision. This would be a first stepping stone.

Later on, we can consider what it means to pause/resume the tick system, to scale time, etc. Tests are pending, I'll get started on them.

Comment on lines +19 to +29
public static NetworkTickSystem Instance
{
get
{
if (m_Instance == null)
{
m_Instance = new NetworkTickSystem();
}
return m_Instance;
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

singleton on its own vs an instance attached to a specific NetworkManager? I prefer the latter, what do you think? :)

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.

Attached to a specific NetworkManager is cleaner.
But the singleton PR has not landed yet. So, I'd rather push this as-is, and when we have converged on the correct way to deal with singletons, we replicate the pattern for this, too? Workable?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

you can still put instances under NetworkManager and access via NetworkManager.Singleton later on right?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why not instantiate it within the NetworkUpdateLoop itself? That was my original plan, have it accessible via NetworkUpdateLoop. Really, this is not the final version for the tick system, so NetworkManager or NetworkUpdateLoop... one of the two would be nice.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

NetworkUpdateLoop will always be a static class but NetworkManager is not a static class and will not be a singleton in the future so I'd suggest putting this instance under NetworkManager instead of NetworkUpdateLoop — also I don't want to repeat singleton pattern, we should be trying to avoid and remove them, not introduce them IMHO.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

See how the RPCQueueContainer is instantiated

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.

Addressed in latest update. Thanks!

Comment on lines +65 to +79
/// <summary>
/// Constructor
/// Defaults to k_DefaultTickDuration if no tick duration is specified
/// </summary>
/// <param name="tickDuration">Duration of a network tick</param>
private NetworkTickSystem(double tickDuration = k_DefaultTickDuration)
{
NetworkUpdateLoop.RegisterNetworkUpdate(this, NetworkUpdateStage.EarlyUpdate);

//Assure we don't specify a value less than or equal to zero for tick frequency
m_TickDuration = (tickDuration <= 0d) ? k_DefaultTickDuration : tickDuration;

// ticks might not start at 0, so let's update right away at construction
UpdateNetworkTick();
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

super-minor: should we move this constructor block up above Dispose()? it took me a CTRL+F to find .RegisterNetworkUpdate() and constructor :P

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.

yeah, will move constructor and Dispose at the top. 👍

/// </summary>
private void UpdateNetworkTick()
{
m_NetworkTick = (int)(Time.unscaledTime / m_TickDuration);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why (int)(float / double) instead of (int)(float / float)? m_TickDuration could be a float no?

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 had tried to keep the design for the original branch and thus kept the doubles. But yeah, you raise a good point if our source data is float, no point going over-board with double. I've got in my plans to eventually review the float usage for precision. But float would give us already ~2ms resolution after 5hours game time. Good enough for now. Will change.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's add a comment saying we plan to move to FixedTime, etc.

{
public class NetworkTickSystem : INetworkUpdateSystem, IDisposable
{
private const double k_DefaultTickDuration = 0.016;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

hmm, 62.5 ticks per sec. do you mind inlining 1/0.016 math here and also explain what this variable is and why 62.5 tps instead of 20 or 30 or something else for now?

Copy link
Copy Markdown
Contributor Author

@jeffreyrainy jeffreyrainy Feb 26, 2021

Choose a reason for hiding this comment

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

The games I shipped in the past used integer number of millis to be able to do all computation on integers. So, that's why 16 milliseconds felt natural. But I don't really care since we're using floats now. Do you insist on making this 1/60f ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

you can keep 0.016 if you want but I'm asking for a comment explaining its math + why 62.5fps specifically instead of any other number.

Comment on lines +9 to +10
private double m_TickDuration;
private int m_NetworkTick; //How many network ticks have passed?
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
private double m_TickDuration;
private int m_NetworkTick; //How many network ticks have passed?
private float m_TickInternalMs;
private int m_NetworkTickCount;

I feel a little bit mixed here. if variable name is not good enough, we should probably change its name rather than comment next to it IMHO. I'd propose m_NetworkTickCount instead of m_NetworkTick and m_TickIntervalMs instead of m_TickDuration here. what do you think?

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.

Yeah, will change. I was trying to stay aligned with original branch, but it's worth improving upon.

Copy link
Copy Markdown
Contributor Author

@jeffreyrainy jeffreyrainy Feb 26, 2021

Choose a reason for hiding this comment

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

Noted. I think the long-term goal will be:
Read float unscaledtime, because that's the precision we have.
Maintain an integral number of millis for precision alignment and then surface out any time via APIs in double

Or better: accumulate FixedUpdate time as integral, quantize it during EarlyUpdate in ticks. Offer API for people who want to know the time in float/double.

@0xFA11 0xFA11 changed the title feat: Feature/networktick feat: NetworkTickSystem Feb 26, 2021
@0xFA11 0xFA11 changed the title feat: NetworkTickSystem feat: implement NetworkTickSystem based on NetworkUpdateLoop with INetworkUpdateSystem interface Feb 26, 2021
@0xFA11 0xFA11 changed the title feat: implement NetworkTickSystem based on NetworkUpdateLoop with INetworkUpdateSystem interface feat: implement NetworkTickSystem based on NetworkUpdateLoop Feb 26, 2021
Comment thread com.unity.multiplayer.mlapi/Runtime/Core/NetworkTickSystem.cs Outdated
Copy link
Copy Markdown
Contributor

@0xFA11 0xFA11 left a comment

Choose a reason for hiding this comment

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

🚀

Copy link
Copy Markdown
Member

@NoelStephensUnity NoelStephensUnity left a comment

Choose a reason for hiding this comment

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

LGMT!

@jeffreyrainy jeffreyrainy merged commit 45ec6bf into develop Feb 26, 2021
@jeffreyrainy jeffreyrainy deleted the feature/networktick branch February 26, 2021 18:26
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.

4 participants