Skip to content

Commit 9dd32d5

Browse files
update
Doing a second inspector UI pass to include tool tips and rename each element item to the component's standard inspector view naming where it is the GameObject's name followed by the class name that is separated by capitalization and contained within parenthesis.
1 parent 6d8f7a6 commit 9dd32d5

File tree

1 file changed

+76
-19
lines changed

1 file changed

+76
-19
lines changed

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

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22
using System.Collections;
33
using System.Collections.Generic;
44
using System.Reflection;
5+
using System.Runtime.CompilerServices;
6+
#if UNITY_EDITOR
7+
using System.Text.RegularExpressions;
8+
#endif
59
using UnityEngine;
610
using Object = UnityEngine.Object;
711

12+
813
namespace Unity.Netcode.Components
914
{
1015
/// <summary>
@@ -13,33 +18,48 @@ namespace Unity.Netcode.Components
1318
[Serializable]
1419
public class ComponentControllerEntry
1520
{
21+
[HideInInspector]
22+
// Ignoring the naming convention in order to auto-assign element names
23+
#pragma warning disable IDE1006
24+
public string name = "Component";
25+
#pragma warning restore IDE1006
26+
1627
/// <summary>
1728
/// When true, this component's enabled state will be the inverse of
1829
/// the value passed into <see cref="ComponentController.SetEnabled(bool)"/>.
1930
/// </summary>
20-
[Tooltip("When enabled, this component will inversely mirror the currently applied enable or disable state.")]
31+
[Tooltip("When enabled, this component will inversely mirror the currently applied ComponentController's enabled state.")]
2132
public bool InvertEnabled;
2233

2334
/// <summary>
2435
/// The amount of time to delay enabling this component when the <see cref="ComponentController"/> has just transitioned from a disabled to enabled state.
2536
/// </summary>
37+
/// <remarks>
38+
/// This can be useful under scenarios where you might want to prevent a component from being enabled too early prior to making any adjustments.<br />
39+
/// As an example, you might find that delaying the enabling of a <see cref="MeshRenderer"/> until at least the next frame will avoid any single frame
40+
/// rendering anomalies until the <see cref="Rigidbody"/> has updated the <see cref="Transform"/>.
41+
/// </remarks>
2642
[Range(0.0f, 2.0f)]
43+
[Tooltip("The amount of time to delay when transitioning this component from disabled to enabled. When 0, the change is immediate.")]
2744
public float EnableDelay;
2845

2946
/// <summary>
3047
/// The amount of time to delay disabling this component when the <see cref="ComponentController"/> has just transitioned from an enabled to disabled state.
3148
/// </summary>
49+
/// <remarks>
50+
/// This can be useful under scenarios where you might want to prevent a component from being disabled too early prior to making any adjustments.<br />
51+
/// </remarks>
52+
[Tooltip("The amount of time to delay when transitioning this component from enabled to disabled. When 0, the change is immediate.")]
3253
[Range(0f, 2.0f)]
3354
public float DisableDelay;
3455

3556
/// <summary>
36-
/// The component to control.
57+
/// The component that will have its enabled property synchronized.
3758
/// </summary>
3859
/// <remarks>
39-
/// You can assign an entire <see cref="GameObject"/> to this property which will
40-
/// add all components attached to the <see cref="GameObject"/>. The <see cref="StartEnabled"/>
41-
/// and <see cref="InvertEnabled"/> properties will be applied to all components found on the <see cref="GameObject"/>.
60+
/// You can assign an entire <see cref="GameObject"/> to this property which will add all components attached to the <see cref="GameObject"/> and its children.
4261
/// </remarks>
62+
[Tooltip("The component that will have its enabled status synchonized. You can drop a GameObject onto this field and all valid components will be added to the list.")]
4363
public Object Component;
4464
internal PropertyInfo PropertyInfo;
4565

@@ -141,17 +161,16 @@ internal PendingStateUpdate(ComponentControllerEntry componentControllerEntry, b
141161
}
142162

143163
/// <summary>
144-
/// Handles enabling or disabling commonly used components, behaviours, RenderMeshes, etc.<br />
145-
/// Anything that derives from <see cref="Component"/> and has an enabled property can be added
146-
/// to the list of objects.<br />
147-
/// <see cref="NetworkBehaviour"/> derived components are not allowed and will be automatically removed.
164+
/// Handles enabling or disabling commonly used components like <see cref="MonoBehaviour"/>, <see cref="MeshRenderer"/>, <see cref="Collider"/>, etc.<br />
165+
/// Anything that derives from <see cref="Component"/> and has an enabled property can be added to the list of objects.<br />
166+
/// NOTE: <see cref="NetworkBehaviour"/> derived components are not allowed and will be automatically removed.
148167
/// </summary>
149168
/// <remarks>
150-
/// This will synchronize the enabled or disabled state of the <see cref="Component"/>s with
151-
/// connected and late joining clients.<br />
152-
/// This class provides the basic functionality to synchronizing components' enabled state.<br />
153-
/// It is encouraged to create custom derived versions of this class to provide any additional
154-
/// functionality required for your project specific needs.
169+
/// This will synchronize the enabled or disabled state of the <see cref="Component"/>s with connected and late joining clients.<br />
170+
/// - Use <see cref="EnabledState"/> to determine the current synchronized enabled state. <br />
171+
/// - Use <see cref="SetEnabled(bool)"/> to change the enabled state and have the change applied to all components this <see cref="ComponentController"/> is synchronizing.<br />
172+
///
173+
/// It is encouraged to create custom derived versions of this class to provide any additional functionality required for your project specific needs.
155174
/// </remarks>
156175
public class ComponentController : NetworkBehaviour
157176
{
@@ -176,6 +195,21 @@ public class ComponentController : NetworkBehaviour
176195
private bool m_IsEnabled;
177196

178197
#if UNITY_EDITOR
198+
199+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
200+
private bool IsValidComponentType(Object component)
201+
{
202+
return !(component.GetType().IsSubclassOf(typeof(NetworkBehaviour)) || component.GetType() == typeof(NetworkObject) || component.GetType() == typeof(NetworkManager));
203+
}
204+
205+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
206+
private string GetComponentNameFormatted(Object component)
207+
{
208+
// Split the class name up based on capitalization
209+
var classNameDisplay = Regex.Replace(component.GetType().Name, "([A-Z])", " $1", RegexOptions.Compiled).Trim();
210+
return $"{component.name} ({classNameDisplay})";
211+
}
212+
179213
/// <inheritdoc/>
180214
/// <remarks>
181215
/// Checks for invalid <see cref="Object"/> entries.
@@ -188,6 +222,7 @@ protected virtual void OnValidate()
188222
}
189223

190224
var gameObjectsToScan = new List<ComponentControllerEntry>();
225+
// First pass is to verify all entries are valid and look for any GameObjects added as an entry to process next
191226
for (int i = Components.Count - 1; i >= 0; i--)
192227
{
193228
if (Components[i] == null)
@@ -207,9 +242,9 @@ protected virtual void OnValidate()
207242
continue;
208243
}
209244

210-
if (componentType.IsSubclassOf(typeof(NetworkBehaviour)))
245+
if (!IsValidComponentType(Components[i].Component))
211246
{
212-
Debug.LogWarning($"Removing {Components[i].Component.name} since {nameof(NetworkBehaviour)}s are not allowed to be controlled by this component.");
247+
Debug.LogWarning($"Removing {GetComponentNameFormatted(Components[i].Component)} since {Components[i].Component.GetType().Name} is not an allowed component type.");
213248
Components.RemoveAt(i);
214249
continue;
215250
}
@@ -222,14 +257,16 @@ protected virtual void OnValidate()
222257
}
223258
}
224259

260+
// Second pass is to process any GameObjects added.
261+
// Scan the GameObject and all of its children and add all valid components to the list.
225262
foreach (var entry in gameObjectsToScan)
226263
{
227264
var asGameObject = entry.Component as GameObject;
228-
var components = asGameObject.GetComponents<Component>();
265+
var components = asGameObject.GetComponentsInChildren<Component>();
229266
foreach (var component in components)
230267
{
231-
// Ignore any NetworkBehaviour derived components
232-
if (component.GetType().IsSubclassOf(typeof(NetworkBehaviour)))
268+
// Ignore any NetworkBehaviour derived, NetworkObject, or NetworkManager components
269+
if (!IsValidComponentType(component))
233270
{
234271
continue;
235272
}
@@ -247,6 +284,16 @@ protected virtual void OnValidate()
247284
}
248285
}
249286
gameObjectsToScan.Clear();
287+
288+
// Final (third) pass is to name each list element item as the component is normally viewed in the inspector view.
289+
for (int i = 0; i < Components.Count; i++)
290+
{
291+
if (!Components[i].Component)
292+
{
293+
continue;
294+
}
295+
Components[i].name = GetComponentNameFormatted(Components[i].Component);
296+
}
250297
}
251298
#endif
252299

@@ -270,6 +317,9 @@ protected override void OnSynchronize<T>(ref BufferSerializer<T> serializer)
270317
/// This checks to make sure that all <see cref="Component"/> entries are valid and will create a final
271318
/// <see cref="ComponentControllerEntry"/> list of valid entries.
272319
/// </summary>
320+
/// <remarks>
321+
/// If overriding this method, it is required that you invoke this base method.
322+
/// </remarks>
273323
protected virtual void Awake()
274324
{
275325
ValidComponents.Clear();
@@ -310,6 +360,9 @@ protected virtual void Awake()
310360
}
311361

312362
/// <inheritdoc/>
363+
/// <remarks>
364+
/// If overriding this method, it is required that you invoke this base method.
365+
/// </remarks>
313366
public override void OnNetworkSpawn()
314367
{
315368
if (OnHasAuthority())
@@ -321,6 +374,7 @@ public override void OnNetworkSpawn()
321374

322375
/// <inheritdoc/>
323376
/// <remarks>
377+
/// If overriding this method, it is required that you invoke this base method. <br />
324378
/// Assures all instances subscribe to the internal <see cref="NetworkVariable{T}"/> of type
325379
/// <see cref="bool"/> that synchronizes all instances when <see cref="Object"/>s are enabled
326380
/// or disabled.
@@ -332,6 +386,9 @@ protected override void OnNetworkPostSpawn()
332386
}
333387

334388
/// <inheritdoc/>
389+
/// <remarks>
390+
/// If overriding this method, it is required that you invoke this base method.
391+
/// </remarks>
335392
public override void OnDestroy()
336393
{
337394
if (m_CoroutineObject.IsRunning)

0 commit comments

Comments
 (0)