Skip to content

Commit 307fb75

Browse files
update
Fixes and updates based on the most recent changes in the unified API.
1 parent 3cda26a commit 307fb75

5 files changed

Lines changed: 183 additions & 45 deletions

File tree

com.unity.netcode.gameobjects/Editor/NetworkObjectEditor.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
#if BYPASS_DEFAULT_ENUM_DRAWER && MULTIPLAYER_SERVICES_SDK_INSTALLED
33
using System.Linq;
44
#endif
5+
#if UNIFIED_NETCODE
6+
using Unity.NetCode;
7+
using Unity.NetCode.Editor;
8+
#endif
59
using UnityEditor;
610
using UnityEngine;
711

@@ -23,6 +27,34 @@ public class NetworkObjectEditor : UnityEditor.Editor
2327

2428
private static readonly string[] k_HiddenFields = { "m_Script" };
2529

30+
#if UNIFIED_NETCODE
31+
/// <summary>
32+
/// Register for the GhostAdapter removal event.
33+
/// </summary>
34+
[InitializeOnLoadMethod]
35+
private static void OnApplicationStart()
36+
{
37+
GhostAdapterEditor.OnGhostAdapterPreRemoval = OnGhostAdapterPreRemoval;
38+
}
39+
40+
/// <summary>
41+
/// Callback to remove the GhostBehaviours prior to removing GhostAdapter.
42+
/// </summary>
43+
/// <param name="gameObject">The <see cref="GameObject"/> with the <see cref="GhostAdapter"/> component being removed.</param>
44+
private static void OnGhostAdapterPreRemoval(GameObject gameObject)
45+
{
46+
var ghostBehaviours = gameObject.GetComponentsInChildren<GhostBehaviour>();
47+
for (int i = ghostBehaviours.Length - 1; i >= 0; i--)
48+
{
49+
DestroyImmediate(ghostBehaviours[i], true);
50+
}
51+
var networkObject = gameObject.GetComponent<NetworkObject>();
52+
networkObject.GhostAdapter = null;
53+
networkObject.HasGhost = false;
54+
networkObject.HadBridge = true;
55+
}
56+
#endif
57+
2658
private void Initialize()
2759
{
2860
if (m_Initialized)

com.unity.netcode.gameobjects/Editor/NetworkTransformEditor.cs

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Runtime.CompilerServices;
12
using Unity.Netcode.Components;
23
using UnityEditor;
34
using UnityEngine;
@@ -94,9 +95,38 @@ public override void OnEnable()
9495
base.OnEnable();
9596
}
9697

98+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
99+
private void SetGUIActive(bool active = true)
100+
{
101+
#if UNIFIED_NETCODE
102+
if (Application.IsPlaying(m_NetworkObject) && m_NetworkObject.HasGhost)
103+
{
104+
GUI.enabled = false;
105+
}
106+
else
107+
{
108+
GUI.enabled = active;
109+
}
110+
#else
111+
GUI.enabled = active;
112+
#endif
113+
114+
}
115+
116+
private NetworkObject m_NetworkObject;
117+
97118
private void DisplayNetworkTransformProperties()
98119
{
99120
var networkTransform = target as NetworkTransform;
121+
122+
#if UNIFIED_NETCODE
123+
m_NetworkObject = networkTransform.GetComponent<NetworkObject>();
124+
var hasGhost = m_NetworkObject.HasGhost;
125+
SetGUIActive();
126+
#else
127+
var hasGhost = false;
128+
#endif
129+
100130
EditorGUILayout.LabelField("Axis to Synchronize", EditorStyles.boldLabel);
101131
{
102132
GUILayout.BeginHorizontal();
@@ -190,7 +220,7 @@ private void DisplayNetworkTransformProperties()
190220
{
191221
networkTransform.UseUnreliableDeltas = false;
192222
}
193-
GUI.enabled = !networkTransform.SwitchTransformSpaceWhenParented;
223+
SetGUIActive(!networkTransform.SwitchTransformSpaceWhenParented);
194224
if (networkTransform.SwitchTransformSpaceWhenParented)
195225
{
196226
EditorGUILayout.BeginHorizontal();
@@ -202,11 +232,13 @@ private void DisplayNetworkTransformProperties()
202232
{
203233
EditorGUILayout.PropertyField(m_UseUnreliableDeltas);
204234
}
205-
GUI.enabled = true;
235+
236+
SetGUIActive(true);
206237

207238
EditorGUILayout.Space();
208239
EditorGUILayout.LabelField("Configurations", EditorStyles.boldLabel);
209-
GUI.enabled = !networkTransform.UseUnreliableDeltas;
240+
241+
SetGUIActive(!networkTransform.UseUnreliableDeltas);
210242
if (networkTransform.UseUnreliableDeltas)
211243
{
212244
EditorGUILayout.BeginHorizontal();
@@ -218,7 +250,7 @@ private void DisplayNetworkTransformProperties()
218250
{
219251
EditorGUILayout.PropertyField(m_SwitchTransformSpaceWhenParented);
220252
}
221-
GUI.enabled = true;
253+
SetGUIActive(true);
222254
if (m_SwitchTransformSpaceWhenParented.boolValue)
223255
{
224256
m_TickSyncChildren.boolValue = true;
@@ -297,20 +329,23 @@ private void DisplayNetworkTransformProperties()
297329

298330
#if COM_UNITY_MODULES_PHYSICS
299331
// if rigidbody is present but network rigidbody is not present
300-
if (networkTransform.TryGetComponent<Rigidbody>(out _) && networkTransform.TryGetComponent<NetworkRigidbody>(out _) == false)
332+
if (hasGhost && networkTransform.TryGetComponent<Rigidbody>(out _) && networkTransform.TryGetComponent<NetworkRigidbody>(out _) == false)
301333
{
302-
EditorGUILayout.HelpBox("This GameObject contains a Rigidbody but no NetworkRigidbody.\n" +
334+
EditorGUILayout.HelpBox("This GameObject contains a Rigidbody but no NetworkRigidbody.\n " +
303335
"Add a NetworkRigidbody component to improve Rigidbody synchronization.", MessageType.Warning);
304336
}
305337
#endif // COM_UNITY_MODULES_PHYSICS
306338

307339
#if COM_UNITY_MODULES_PHYSICS2D
308-
if (networkTransform.TryGetComponent<Rigidbody2D>(out _) && networkTransform.TryGetComponent<NetworkRigidbody2D>(out _) == false)
340+
if (!hasGhost && networkTransform.TryGetComponent<Rigidbody2D>(out _) && networkTransform.TryGetComponent<NetworkRigidbody2D>(out _) == false)
309341
{
310342
EditorGUILayout.HelpBox("This GameObject contains a Rigidbody2D but no NetworkRigidbody2D.\n" +
311343
"Add a NetworkRigidbody2D component to improve Rigidbody2D synchronization.", MessageType.Warning);
312344
}
313345
#endif // COM_UNITY_MODULES_PHYSICS2D
346+
#if UNIFIED_NETCODE
347+
GUI.enabled = true;
348+
#endif
314349
}
315350

316351
/// <summary>

com.unity.netcode.gameobjects/Editor/Unity.Netcode.Editor.asmdef

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"Unity.Networking.Transport",
99
"Unity.Services.Core",
1010
"Unity.Services.Authentication",
11-
"Unity.NetCode"
11+
"Unity.NetCode",
12+
"Unity.NetCode.Editor"
1213
],
1314
"includePlatforms": [
1415
"Editor"

com.unity.netcode.gameobjects/Runtime/Components/Helpers/NetworkObjectBridge.cs

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
#if UNIFIED_NETCODE
22
using Unity.NetCode;
3-
#if UNITY_EDITOR
4-
using UnityEditor;
5-
#endif
63
using UnityEngine;
74

85
namespace Unity.Netcode
@@ -12,32 +9,50 @@ namespace Unity.Netcode
129
/// This is a component that is added to the root of all N4E-spawned hybrid prefab instances. It is used to link
1310
/// <see cref="NetworkObject.SerializedObject"/> the N4E-spawned hybrid prefab instances to the incoming <see cref="CreateObjectMessage"/>
1411
/// specific to the N4E-spawned hybrid prefab instance that has the matching <see cref="NetworkObjectId"/>.
15-
/// </summary>
12+
/// </summary>
13+
14+
[DefaultExecutionOrder(GhostAdapterExecutionOrder.ExecutionOrder + 1)]
15+
//BREAK --- Fix this on UNIFIED side 1st
1616
public partial class NetworkObjectBridge : GhostBehaviour
1717
{
18+
// DefaultExecutionOrder
19+
// TODO: Define a const for the value used on GhostAdapter and use that value
20+
// to set the execution order so if it changes on GhostAdapter it updates here.
1821
#if UNITY_EDITOR
19-
[HideInInspector]
20-
[SerializeField]
21-
private bool m_Sorted = false;
2222
private void OnValidate()
2323
{
24-
// TODO-UNIFIED: GhostAdapter must be above all GhostBehaviours in order to assure the GhostAdapter is initialized before any GhostBehaviour.
25-
// This auto-sorting is required because the GhostBehaviours rely on the GhostAdapter.Awake being invoked before any GhostBehaviour.Awake.
26-
if (!m_Sorted && !EditorApplication.isPlaying)
24+
hideFlags = HideFlags.HideInInspector;
25+
26+
var ghostAdapter = GetComponent<GhostAdapter>();
27+
if (ghostAdapter == null)
2728
{
28-
while (UnityEditorInternal.ComponentUtility.MoveComponentUp(this))
29-
{
30-
// Keep moving until it can't go higher
31-
}
32-
var ghostAdapter = gameObject.GetComponent<GhostAdapter>();
33-
// Now move the GhostAdapter to the top so it is above NetworkObjectBridge
34-
while (ghostAdapter != null && UnityEditorInternal.ComponentUtility.MoveComponentUp(ghostAdapter))
29+
return;
30+
}
31+
32+
// Start users with just interpolation (they can adjust this if they want prediction)
33+
// to make the initial transition less problematic for users.
34+
ghostAdapter.SupportedGhostModes = GhostModeMask.Interpolated;
35+
36+
#if COM_UNITY_MODULES_PHYSICS
37+
var rigidBody = GetComponent<Rigidbody>();
38+
var ghostRigidBody = GetComponent<GhostRigidbody>();
39+
if (rigidBody != null)
40+
{
41+
// This must be enabled when replicating the rigid body.
42+
43+
ghostAdapter.SingleWorldHostInterpolationSmoothing = SingleWorldHostInterpolationMode.Interpolate;
44+
// TODO: Currently, this is added only if you enable replication of the rigid body.
45+
// There is a bug where if you don't add this component it doesn't synchronize the transform.
46+
// Remove this once the issue is resolved.
47+
if (ghostRigidBody == null)
3548
{
36-
// Keep moving until it can't go higher
49+
gameObject.AddComponent<GhostRigidbody>();
3750
}
38-
39-
m_Sorted = true;
4051
}
52+
#endif
53+
#if COM_UNITY_MODULES_PHYSICS2D
54+
// TODO: Fill out a similar script as above but for the 2D version
55+
#endif
4156
}
4257
#endif
4358

@@ -67,6 +82,11 @@ internal void HybridParentUpdate(Vector3 scale)
6782
//Debug.Log($"---- New LT: {transform.localPosition} | {transform.localRotation}");
6883
Ghost.ApplyPostTransformMatrixScale(scale);
6984
}
85+
86+
internal void ApplyScale(Vector3 scale)
87+
{
88+
Ghost.ApplyPostTransformMatrixScale(scale);
89+
}
7090
}
7191
}
7292
#endif

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

Lines changed: 67 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -370,17 +370,38 @@ private void CheckForInScenePlaced()
370370
[SerializeField]
371371
internal bool HadBridge;
372372
#if UNITY_EDITOR
373+
private void OnApplicationUpdate()
374+
{
375+
NetworkObjectBridge = gameObject.AddComponent<NetworkObjectBridge>();
376+
HadBridge = true;
377+
// Transform synchronization is handled by unified netcode
378+
SynchronizeTransform = false;
379+
380+
EditorApplication.update -= OnApplicationUpdate;
381+
}
382+
373383
internal void UnifiedValidation()
374384
{
375385
NetworkObjectBridge = GetComponent<NetworkObjectBridge>();
376386
GhostAdapter = GetComponent<GhostAdapter>();
387+
377388
HasGhost = GhostAdapter != null;
378-
if (HasGhost && NetworkObjectBridge == null)
389+
if (HasGhost)
379390
{
380-
NetworkObjectBridge = gameObject.AddComponent<NetworkObjectBridge>();
381-
HadBridge = true;
382-
// Transform synchronization is handled by unified netcode
383-
SynchronizeTransform = false;
391+
//TODO: Needs to be validated once develop-2.0.0 is merged.
392+
if (InScenePlaced)
393+
{
394+
Debug.LogError($"This experimental version of NGO does not support hybrid in-scene placed objects.");
395+
Destroy(GhostAdapter);
396+
HasGhost = false;
397+
return;
398+
}
399+
400+
if (NetworkObjectBridge == null)
401+
{
402+
EditorApplication.update -= OnApplicationUpdate;
403+
EditorApplication.update += OnApplicationUpdate;
404+
}
384405
}
385406
else if (HadBridge && !HasGhost && !NetworkObjectBridge)
386407
{
@@ -389,6 +410,14 @@ internal void UnifiedValidation()
389410
}
390411
}
391412
#endif
413+
414+
public void ApplyScale(Vector3 scale)
415+
{
416+
if (HasGhost)
417+
{
418+
GhostAdapter.ApplyPostTransformMatrixScale(scale);
419+
}
420+
}
392421
#endif
393422
/// <summary>
394423
/// Gets the NetworkManager that owns this NetworkObject instance
@@ -2856,33 +2885,53 @@ internal bool InitializeChildNetworkBehaviours()
28562885
#endif
28572886
}
28582887
#if UNIFIED_NETCODE
2859-
// For now, cycle through all known NetworkTransform and NetworkRigidbodyBase derived components
2888+
// For now, cycle through all known NetworkRigidbodyBase derived components
28602889
// and destroy them all if this is a hybrid prefab instance.
28612890
// This allows a user to not have to make direct adjustments until trying out their NGO prefab
2862-
// as a hybrid spawned prefab (optional to completely remove, will eventually become obsolete and
2863-
// automatically removed later).
2891+
// as a hybrid spawned prefab.
28642892
if (HasGhost && !NetworkManager.DistributedAuthorityMode)
28652893
{
2894+
#if COM_UNITY_MODULES_PHYSICS || COM_UNITY_MODULES_PHYSICS2D
2895+
// TODO-UNIFIED: This needs to be updated to make it "opt-in".
2896+
// If the GhostAdapter is not configured for prediction but is still using a Rigidbody, then go ahead and remove it on
2897+
// the client side to improve performance by default.
2898+
// TODO-UNIFIED: Determine if recent unified physics updates does not require checking for prediction.
28662899
if (NetworkRigidbodies != null)
28672900
{
2901+
var isServer = NetworkManager.IsServer;
28682902
for (int i = NetworkRigidbodies.Count - 1; i >= 0; i--)
28692903
{
2870-
// TODO-UNIFIED: This needs to be updated to make it "opt-in".
2871-
// Only clients remove the rigidbody for performance purposes when running a hybrid spawn client-server topology.
2872-
if (!NetworkManager.IsServer)
2904+
var currenObject = NetworkRigidbodies[i].gameObject;
2905+
var currentHasGhostRigidBody = currenObject.GetComponent<GhostRigidbody>() != null;
2906+
if (!isServer)
28732907
{
2874-
var rigidBody = NetworkRigidbodies[i].gameObject.GetComponent<Rigidbody>();
2875-
if (rigidBody != null)
2908+
#if COM_UNITY_MODULES_PHYSICS
2909+
var rigidBody = currenObject.GetComponent<Rigidbody>();
2910+
2911+
if (rigidBody != null && !currentHasGhostRigidBody)
28762912
{
28772913
Destroy(rigidBody);
28782914
}
2915+
#endif
2916+
#if COM_UNITY_MODULES_PHYSICS2D
2917+
var rigidBody2D = currenObject.GetComponent<Rigidbody2D>();
2918+
if (rigidBody2D != null && !currentHasGhostRigidBody)
2919+
{
2920+
Destroy(rigidBody2D);
2921+
}
2922+
#endif
28792923
}
2880-
ChildNetworkBehaviours.Remove(NetworkRigidbodies[i].NetworkBehaviourId);
2881-
Destroy(NetworkRigidbodies[i]);
2924+
// Both the server and clients will still remove and destroy the NetworkRigidbody
2925+
// since there is no point in synchronizing these when it is handled via unified.
2926+
var networkRigidbody = NetworkRigidbodies[i];
2927+
NetworkRigidbodies.Remove(networkRigidbody);
2928+
ChildNetworkBehaviours.Remove(networkRigidbody.NetworkBehaviourId);
2929+
Destroy(networkRigidbody);
28822930
}
2883-
NetworkRigidbodies.Clear();
28842931
}
2885-
2932+
#endif
2933+
// This is defined out since users might have derived NetworkTransforms
2934+
#if UNIFIED_NETCODE_DESTROY
28862935
// When hybrid spawning, the transform is synchronized by the GhostObject.
28872936
// As a convenience, we remove and destroy all NetworkTransforms.
28882937
// TODO-Parenting-Related-Area: We need to replicate this functionality in a GhostAdapter
@@ -2898,6 +2947,7 @@ internal bool InitializeChildNetworkBehaviours()
28982947
}
28992948
NetworkTransforms.Clear();
29002949
}
2950+
#endif
29012951
}
29022952
#endif
29032953
return true;

0 commit comments

Comments
 (0)