Skip to content

Commit 28a34d2

Browse files
feat: remove the ability to disable prediction globally from game config
Disabling prediction globally had almost no benefits and very few use cases, but complicated the code and confused game developers. Predictability can still be configured for each ElympicsBehaviour independently and it is possible to disable it for every object in a game.
1 parent e0d5910 commit 28a34d2

7 files changed

Lines changed: 24 additions & 65 deletions

File tree

Editor/Config/ElympicsGameConfigEditor.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ private VisualElement PrepareInspectorTree(VisualTreeAsset sourceTree)
4242
var snapshotSendingInterval = inspectorTree.Q<SliderInt>("snapshot-sending-interval");
4343
var inputLag = inspectorTree.Q<SliderInt>("input-lag");
4444

45-
var predictionEnabled = inspectorTree.Q<Toggle>("prediction-toggle");
4645
var predictionLimit = inspectorTree.Q<SliderInt>("prediction-limit");
4746
var totalPredictionLimit = inspectorTree.Q<Label>("total-prediction-limit");
4847

@@ -88,8 +87,6 @@ private VisualElement PrepareInspectorTree(VisualTreeAsset sourceTree)
8887
_ = minClientTickRateFactor.RegisterValueChangedCallback(_ => UpdateTicksPerSecondLabel());
8988
_ = maxClientTickRateFactor.RegisterValueChangedCallback(_ => UpdateTicksPerSecondLabel());
9089

91-
_ = predictionEnabled.RegisterValueChangedCallback(_ => UpdatePredictionSection());
92-
9390
_ = snapshotSendingInterval.RegisterValueChangedCallback(_ => UpdateTotalPredictionLimitLabel());
9491
_ = inputLag.RegisterValueChangedCallback(_ => UpdateTotalPredictionLimitLabel());
9592
_ = predictionLimit.RegisterValueChangedCallback(_ => UpdateTotalPredictionLimitLabel());
@@ -116,7 +113,6 @@ private VisualElement PrepareInspectorTree(VisualTreeAsset sourceTree)
116113

117114
UpdateSceneButton();
118115
UpdateTicksPerSecondLabel();
119-
UpdatePredictionSection();
120116
UpdateTotalPredictionLimitLabel();
121117
UpdateDebugModeOptions();
122118
UpdateVersionUploadStatus();
@@ -136,12 +132,6 @@ void UpdateTicksPerSecondLabel()
136132
tpsLabel.text = $"Client ticks per second: {(minTps != maxTps ? $"from {minTps} to {maxTps}" : $"{minTps}")} ticks";
137133
}
138134

139-
void UpdatePredictionSection()
140-
{
141-
predictionLimit.SetEnabled(gameConfig.Prediction);
142-
totalPredictionLimit.SetEnabled(gameConfig.Prediction);
143-
}
144-
145135
void UpdateTotalPredictionLimitLabel()
146136
{
147137
var totalLimit = (int)Math.Round(gameConfig.TotalPredictionLimitInTicks * gameConfig.TickDuration * 1000);

Editor/Config/ElympicsGameConfigEditor.uxml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
<ui:SliderInt picking-mode="Ignore" label="Input buffer size" high-value="100" name="input-buffer-size" low-value="1" show-input-field="true" binding-path="inputToSendBufferSize" tooltip="Number of ticks from which input shuld be locally stored by client and sent to server each time to decrease the risk of loosing input due to network conditions" />
2424
<ui:SliderInt picking-mode="Ignore" label="Max allowed lag" high-value="100" name="max-lag" show-input-field="true" binding-path="maxAllowedLagInTicks" tooltip="Limits the size of the prediction buffer" />
2525
<ui:SliderInt picking-mode="Ignore" label="Force jump threshold" high-value="100" name="force-jump-threshold" binding-path="forceJumpThresholdInTicks" show-input-field="true" tooltip="How far behind the desired tick client has to be to force a jump to that tick" />
26-
<ui:Toggle label="Prediction" name="prediction-toggle" binding-path="prediction" />
2726
<ui:SliderInt picking-mode="Ignore" label="Prediction limit" high-value="100" name="prediction-limit" binding-path="predictionLimitInTicks" show-input-field="true" tooltip="How much further ahead of server than it is supposed to client can go before it stops to wait for server" />
2827
<ui:Label text="Total prediction limit: XX ms" display-tooltip-when-elided="true" name="total-prediction-limit" tooltip="With input lag and snapshot sending period included" />
2928
<ui:IMGUIContainer name="client-connection-config" />

Runtime/Behaviour/ElympicsBehaviour.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ public void ThrowIfRpcContextNotValid(ElympicsRpcProperties _, MethodInfo method
6262
{
6363
if (ElympicsBase.CurrentCallContext is ElympicsBase.CallContext.RpcInvoking or ElympicsBase.CallContext.Initialize)
6464
return;
65-
if (!ElympicsBase.Config.Prediction)
66-
return;
6765
if (ElympicsBase.CurrentCallContext is ElympicsBase.CallContext.ElympicsUpdate)
6866
return;
6967
throw new ElympicsException($"Error calling {method.DeclaringType?.FullName}.{method.Name}: " + $"RPC cannot be scheduled outside of {nameof(IUpdatable.ElympicsUpdate)} " + $"or {nameof(IInitializable.Initialize)}");

Runtime/Behaviour/ElympicsMonoBehaviour.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,6 @@ internal ElympicsBase ElympicsBase
8181

8282
private GameObject InstantiateInternal(string pathInResources, ElympicsPlayer player, InstantiatedTransformConfig? transformConfig)
8383
{
84-
if (!Elympics.IsServer && !_elympics.Config.Prediction)
85-
throw new ElympicsException($"You cannot use {nameof(ElympicsInstantiate)} as a client or bot when prediction is disabled.");
86-
8784
ThrowIfCalledInWrongContextWithPlayer(player);
8885
return GetFactory().CreateInstance(pathInResources, player, transformConfig);
8986
}
@@ -106,9 +103,6 @@ private void ThrowIfCalledInWrongContextWithPlayer(ElympicsPlayer player, [Calle
106103
/// <remarks>Only objects instantiated with <see cref="ElympicsInstantiate"/> may be destroyed with this method.</remarks>
107104
public void ElympicsDestroy(GameObject createdGameObject)
108105
{
109-
if (!Elympics.IsServer && !_elympics.Config.Prediction)
110-
throw new ElympicsException($"You cannot use {nameof(ElympicsDestroy)} as a client or bot when prediction is disabled.");
111-
112106
ThrowIfCalledInWrongContext();
113107
GetFactory().DestroyInstance(createdGameObject);
114108
}

Runtime/BehaviourPredefined/ElympicsUnityPhysicsSimulator.cs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace Elympics
44
{
55
[DisallowMultipleComponent]
6-
public class ElympicsUnityPhysicsSimulator : ElympicsMonoBehaviour, IInitializable, IUpdatable, IStateSerializationHandler
6+
public class ElympicsUnityPhysicsSimulator : ElympicsMonoBehaviour, IInitializable, IUpdatable
77
{
88
private static ElympicsUnityPhysicsSimulator instance;
99

@@ -36,15 +36,7 @@ public void Initialize()
3636
}
3737

3838
public void ElympicsUpdate() => SimulatePhysics(Elympics.TickDuration);
39-
public void OnPostStateDeserialize()
40-
{
41-
//This is special case when Prediction is turned off for entire game.
42-
if (ElympicsBase.Config.Prediction)
43-
return;
4439

45-
//We must to force physics simulation because Unity GameObject Transform does not refresh automatically when ElympicsRigidBody components are updated.
46-
SimulatePhysics(float.Epsilon);
47-
}
4840
private void SimulatePhysics(float deltaTime)
4941
{
5042
if (!_isActive)
@@ -57,6 +49,5 @@ private void SimulatePhysics(float deltaTime)
5749
_currentPhysicsScene?.Simulate(deltaTime);
5850
_ = _currentPhysicsScene2D?.Simulate(deltaTime);
5951
}
60-
public void OnPreStateSerialize() { }
6152
}
6253
}

Runtime/Config/ElympicsGameConfig.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ public class ElympicsGameConfig : ScriptableObject
4343
[SerializeField] private int inputToSendBufferSize = InputsToSendBufferSizeDefault;
4444
[SerializeField] private int maxAllowedLagInTicks = 15;
4545
[SerializeField] private int forceJumpThresholdInTicks = 6;
46-
[SerializeField] private bool prediction = true;
4746
[SerializeField] private int predictionLimitInTicks = 25;
4847

4948
[SerializeField] private bool detailedNetworkLog;
@@ -84,7 +83,6 @@ public string GameVersion
8483
? ApplicationParameters.Parameters.ShouldUseWebRtc.GetValue(useWeb)
8584
: !ApplicationParameters.Parameters.ShouldUseTcpUdp.GetValue(!useWeb);
8685
#endif
87-
public bool Prediction => prediction;
8886
public bool ReconnectEnabled => enableReconnect;
8987
public ClientConnectionSettings ConnectionConfig => connectionConfig;
9088

Runtime/ElympicsSystems/ElympicsClient.cs

Lines changed: 23 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -180,49 +180,38 @@ internal override void ElympicsFixedUpdate()
180180

181181
_snapshotTracker.ProcessNewSnapshot(receivedSnapshot);
182182

183-
if (Config.Prediction)
184-
{
185-
CheckIfPredictionIsBlocked();
183+
CheckIfPredictionIsBlocked();
186184

187-
using (ElympicsMarkers.Elympics_ReconcileLoopMarker.Auto())
188-
ReconcileIfRequired(_latestReconciliationBaseSnapshotTick == receivedSnapshot.Tick
189-
? null
190-
: receivedSnapshot);
191-
_latestReconciliationBaseSnapshotTick = receivedSnapshot.Tick;
185+
using (ElympicsMarkers.Elympics_ReconcileLoopMarker.Auto())
186+
ReconcileIfRequired(_latestReconciliationBaseSnapshotTick == receivedSnapshot.Tick
187+
? null
188+
: receivedSnapshot);
189+
_latestReconciliationBaseSnapshotTick = receivedSnapshot.Tick;
192190

193-
using (ElympicsMarkers.Elympics_PredictionMarker.Auto())
194-
if (_clientTickCalculator.Results.CanPredict)
195-
{
196-
_tick = _clientTickCalculator.Results.CurrentTick;
191+
using (ElympicsMarkers.Elympics_PredictionMarker.Auto())
192+
if (_clientTickCalculator.Results.CanPredict)
193+
{
194+
_tick = _clientTickCalculator.Results.CurrentTick;
197195

198-
using (ElympicsMarkers.Elympics_ApplyUnpredictablePartOfSnapshotMarker.Auto())
199-
ApplyUnpredictablePartOfSnapshot(receivedSnapshot);
196+
using (ElympicsMarkers.Elympics_ApplyUnpredictablePartOfSnapshotMarker.Auto())
197+
ApplyUnpredictablePartOfSnapshot(receivedSnapshot);
200198

201-
_snapshotTracker.InitializeNewBehaviours();
199+
_snapshotTracker.InitializeNewBehaviours();
202200

203-
InvokeQueuedRpcMessages();
204-
ElympicsBehavioursManager.CommitVars();
201+
InvokeQueuedRpcMessages();
202+
ElympicsBehavioursManager.CommitVars();
205203

206-
using (ElympicsMarkers.Elympics_ApplyingInputMarker.Auto())
207-
ApplyPredictedInput();
204+
using (ElympicsMarkers.Elympics_ApplyingInputMarker.Auto())
205+
ApplyPredictedInput();
208206

209-
using (ElympicsMarkers.Elympics_ElympicsUpdateMarker.Auto())
210-
ElympicsBehavioursManager.ElympicsUpdate();
207+
using (ElympicsMarkers.Elympics_ElympicsUpdateMarker.Auto())
208+
ElympicsBehavioursManager.ElympicsUpdate();
211209

212-
using (ElympicsMarkers.Elympics_ProcessSnapshotMarker.Auto())
213-
ProcessSnapshot(Tick);
210+
using (ElympicsMarkers.Elympics_ProcessSnapshotMarker.Auto())
211+
ProcessSnapshot(Tick);
214212

215-
_previousTick = Tick;
216-
}
217-
}
218-
else
219-
{
220-
ApplyFullSnapshot(receivedSnapshot);
221-
_snapshotTracker.InitializeNewBehaviours();
222-
InvokeQueuedRpcMessages();
223-
ElympicsBehavioursManager.CommitVars();
224-
_previousTick = Tick;
225-
}
213+
_previousTick = Tick;
214+
}
226215

227216
ElympicsUpdateDuration = 1 / _clientTickCalculator.Results.ElympicsUpdateTickRate;
228217

0 commit comments

Comments
 (0)