-
Notifications
You must be signed in to change notification settings - Fork 465
fix: NetworkTransform Bitset not being properly reset if there is no delta [MTT-4275] #2102
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
fix: NetworkTransform Bitset not being properly reset if there is no delta [MTT-4275] #2102
Conversation
These changes make the player client authoritative within the Samples Menu->Additive Scene Loading manual test/sample.
updating test to account for reverting back to the private m_Bitset.
| private readonly NetworkVariable<NetworkTransformState> m_ReplicatedNetworkStateOwner = new NetworkVariable<NetworkTransformState>(new NetworkTransformState(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); | ||
|
|
||
|
|
||
| internal NetworkVariable<NetworkTransformState> GetReplicatedNetworkState() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Consider a getter property instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getter properties with logic are more expensive than methods?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, they're identical (and even if they weren't, this would be firmly in the micro-optimization territory). Properties ARE methods, and access to a property getter will be a callvirt, just like access to a method.
{
int result = app.MyProp;
int res2 = app.MyMethod();
}
public int MyProp { get { /* ... */ } }
public int MyMethod() { /* ... */ }
// [17 9 - 17 33]
IL_0015: ldloc.0 // app
IL_0016: callvirt instance int32 HelloWorld::get_MyProp()
IL_001b: stloc.1 // result
// [18 9 - 18 35]
IL_001c: ldloc.0 // app
IL_001d: callvirt instance int32 HelloWorld::MyMethod()
IL_0022: stloc.2 // res2
.method public hidebysig specialname instance int32
get_MyProp() cil managed
.method public hidebysig instance int32
MyMethod() cil managed
Perhaps you're thinking of the general guidance that "getters shouldn't be used to hide mutations or heavy calculations"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that is what I was thinking of...
Will change this to a getter. 👍
| } | ||
| else | ||
| { | ||
| networkState.HasPositionX = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it safer (and cleaner to read) to set this unconditionally and then change it only if there is a substantial change?
networkState.HasPositionX = false;
if (syncposx && abovethreshold)
{
haspositionx = true
}
Would safeguard against someone changing the SyncPositionX from true to false and having HasPositionX be stuck true with an old value? Not sure if that's an actual scenario that can happen - I'm not familiar enough with the code yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the non-authority side it means that by disabling SyncPositionX all updates to the x axis would cease for that instance. Upon re-enabling SyncPositionX, the HasPositionX value would be re-synchronized (the new state would either have a bitset or not) and will be reset at that time.
For this PR I am going to say that we might just keep it the way it is. PR #2110 has some more clean up and additional fixes that help with the readability.
Bandwidth Consumption Fix:
NetworkTransform's NetworkTransformState.Bitset was having bits set but never having bits "un-set" when there was no delta from the previous relative value or the delta had not crossed the threshold. This would result in any axis marked to synchronize previously being always marked to be synchronized which, in turn, would cause all marked axis to be sent anytime a delta in any of the marked axis crossed the threshold value.
On the non-authoritative side, NetworkTransform.ApplyInterpolatedNetworkStateToTransform was using the NetworkTransform.Sync<Position,RotAngle,Scale> (i.e. NetworkTransform.SyncPositionX) as the determining factor as to whether it should apply all associated axis values as opposed to checking the updated NetworkTransformState.Has<Position,RotAngle,Scale> to determine if it should be updated locally.
Example of the Bitset Issue:
Authoritative Side Interpolation Fix
This includes changes to fix the issue where the authoritative side was interpolating when it should not be.
Client/Owner Authority Adjustments
This includes adjustments to how we handle client-owner authority. Instead of sending a ServerRpc which makes adjustments to a server write authority NetworkVariable, NetworkTransform now creates two versions of the NetworkVariable with one having server write permissions and the other having owner write permissions.
Pertains to #2022 and #2093, BR-694
Changelog
Testing and Documentation