Skip to content

Commit 1fce513

Browse files
refactor
Refactoring the ComponentController to provide more flexibility as well as being able to have component entries that will apply the inverse of the current ComponentController's current state....which allows for switching between different sets of components depending upon the controller's state.
1 parent 2322d48 commit 1fce513

File tree

1 file changed

+94
-21
lines changed

1 file changed

+94
-21
lines changed

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

Lines changed: 94 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,36 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.Reflection;
34
using UnityEngine;
45
using Object = UnityEngine.Object;
56

67
namespace Unity.Netcode.Components
78
{
9+
/// <summary>
10+
/// This is a serializable contianer class for <see cref="ComponentController"/> entries.
11+
/// </summary>
12+
[Serializable]
13+
public class ComponentControllerEntry
14+
{
15+
/// <summary>
16+
/// When true, this component's enabled state will be the inverse of
17+
/// the value passed into <see cref="ComponentController.SetEnabled(bool)"/>.
18+
/// </summary>
19+
public bool InvertEnabled;
20+
21+
/// <summary>
22+
/// The component to control.
23+
/// </summary>
24+
/// <remarks>
25+
/// You can assign an entire <see cref="GameObject"/> to this property which will
26+
/// add all components attached to the <see cref="GameObject"/>. The <see cref="StartEnabled"/>
27+
/// and <see cref="InvertEnabled"/> properties will be applied to all components found on the <see cref="GameObject"/>.
28+
/// </remarks>
29+
public Object Component;
30+
31+
internal PropertyInfo PropertyInfo;
32+
}
33+
834
/// <summary>
935
/// Handles enabling or disabling commonly used components, behaviours, RenderMeshes, etc.<br />
1036
/// Anything that derives from <see cref="Component"/> and has an enabled property can be added
@@ -20,16 +46,21 @@ public class ComponentController : NetworkBehaviour
2046
/// <summary>
2147
/// Determines whether the selected <see cref="Components"/>s will start enabled or disabled when spawned.
2248
/// </summary>
23-
[Tooltip("The initial state of the components when spawned.")]
24-
public bool InitialState = true;
49+
[Tooltip("The initial state of the component controllers enabled status when instnatiated.")]
50+
public bool StartEnabled = true;
2551

2652
/// <summary>
2753
/// The list of <see cref="Components"/>s to be enabled and disabled.
2854
/// </summary>
2955
[Tooltip("The list of components to control. You can drag and drop an entire GameObject on this to include all components.")]
30-
public List<Object> Components;
56+
public List<ComponentControllerEntry> Components;
3157

32-
private Dictionary<Component, PropertyInfo> m_ValidComponents = new Dictionary<Component, PropertyInfo>();
58+
/// <summary>
59+
/// Returns the current enabled state of the <see cref="ComponentController"/>.
60+
/// </summary>
61+
public bool EnabledState => m_IsEnabled.Value;
62+
63+
private List<ComponentControllerEntry> m_ValidComponents = new List<ComponentControllerEntry>();
3364
private NetworkVariable<bool> m_IsEnabled = new NetworkVariable<bool>();
3465

3566
#if UNITY_EDITOR
@@ -44,39 +75,45 @@ protected virtual void OnValidate()
4475
return;
4576
}
4677

47-
var gameObjectsToScan = new List<GameObject>();
78+
var gameObjectsToScan = new List<ComponentControllerEntry>();
4879
for (int i = Components.Count - 1; i >= 0; i--)
4980
{
5081
if (Components[i] == null)
5182
{
5283
continue;
5384
}
54-
var componentType = Components[i].GetType();
85+
86+
if (Components[i].Component == null)
87+
{
88+
continue;
89+
}
90+
var componentType = Components[i].Component.GetType();
5591
if (componentType == typeof(GameObject))
5692
{
57-
gameObjectsToScan.Add(Components[i] as GameObject);
93+
gameObjectsToScan.Add(Components[i]);
5894
Components.RemoveAt(i);
5995
continue;
6096
}
6197

6298
if (componentType.IsSubclassOf(typeof(NetworkBehaviour)))
6399
{
64-
Debug.LogWarning($"Removing {Components[i].name} since {nameof(NetworkBehaviour)}s are not allowed to be controlled by this component.");
100+
Debug.LogWarning($"Removing {Components[i].Component.name} since {nameof(NetworkBehaviour)}s are not allowed to be controlled by this component.");
65101
Components.RemoveAt(i);
66102
continue;
67103
}
68104

69-
var propertyInfo = Components[i].GetType().GetProperty("enabled", BindingFlags.Instance | BindingFlags.Public);
105+
var propertyInfo = Components[i].Component.GetType().GetProperty("enabled", BindingFlags.Instance | BindingFlags.Public);
70106
if (propertyInfo == null && propertyInfo.PropertyType != typeof(bool))
71107
{
72-
Debug.LogWarning($"{Components[i].name} does not contain a public enabled property! (Removing)");
108+
Debug.LogWarning($"{Components[i].Component.name} does not contain a public enabled property! (Removing)");
73109
Components.RemoveAt(i);
74110
}
75111
}
76112

77113
foreach (var entry in gameObjectsToScan)
78114
{
79-
var components = entry.GetComponents<Component>();
115+
var asGameObject = entry.Component as GameObject;
116+
var components = asGameObject.GetComponents<Component>();
80117
foreach (var component in components)
81118
{
82119
// Ignore any NetworkBehaviour derived components
@@ -88,7 +125,12 @@ protected virtual void OnValidate()
88125
var propertyInfo = component.GetType().GetProperty("enabled", BindingFlags.Instance | BindingFlags.Public);
89126
if (propertyInfo != null && propertyInfo.PropertyType == typeof(bool))
90127
{
91-
Components.Add(component);
128+
var componentEntry = new ComponentControllerEntry()
129+
{
130+
Component = component,
131+
PropertyInfo = propertyInfo,
132+
};
133+
Components.Add(componentEntry);
92134
}
93135
}
94136
}
@@ -97,23 +139,24 @@ protected virtual void OnValidate()
97139
#endif
98140

99141
/// <summary>
100-
/// Also checks to assure all <see cref="Component"/> entries are valid and creates a final table of
101-
/// <see cref="Component"/>s paired to their <see cref="PropertyInfo"/>.
142+
/// This checks to make sure that all <see cref="Component"/> entries are valid and will create a final
143+
/// <see cref="ComponentControllerEntry"/> list of valid entries.
102144
/// </summary>
103145
protected virtual void Awake()
104146
{
105147
var emptyEntries = 0;
106-
foreach (var someObject in Components)
148+
foreach (var entry in Components)
107149
{
108-
if (someObject == null)
150+
if (entry == null)
109151
{
110152
emptyEntries++;
111153
continue;
112154
}
113-
var propertyInfo = someObject.GetType().GetProperty("enabled", BindingFlags.Instance | BindingFlags.Public);
155+
var propertyInfo = entry.Component.GetType().GetProperty("enabled", BindingFlags.Instance | BindingFlags.Public);
114156
if (propertyInfo != null && propertyInfo.PropertyType == typeof(bool))
115157
{
116-
m_ValidComponents.Add(someObject as Component, propertyInfo);
158+
entry.PropertyInfo = propertyInfo;
159+
m_ValidComponents.Add(entry);
117160
}
118161
else
119162
{
@@ -128,14 +171,17 @@ protected virtual void Awake()
128171
{
129172
Debug.Log($"{name} has {m_ValidComponents.Count} valid {nameof(Component)} entries.");
130173
}
174+
175+
// Apply the initial state of all components this instance is controlling.
176+
InitializeComponents();
131177
}
132178

133179
/// <inheritdoc/>
134180
public override void OnNetworkSpawn()
135181
{
136182
if (HasAuthority)
137183
{
138-
m_IsEnabled.Value = InitialState;
184+
m_IsEnabled.Value = StartEnabled;
139185
}
140186
base.OnNetworkSpawn();
141187
}
@@ -165,17 +211,44 @@ private void OnEnabledChanged(bool previous, bool current)
165211
ApplyEnabled(current);
166212
}
167213

214+
/// <summary>
215+
/// Initializes each component entry to its initial state.
216+
/// </summary>
217+
private void InitializeComponents()
218+
{
219+
foreach (var entry in m_ValidComponents)
220+
{
221+
// If invert enabled is true, then use the inverted value passed in.
222+
// Otherwise, directly apply the value passed in.
223+
var isEnabled = entry.InvertEnabled ? !StartEnabled : StartEnabled;
224+
entry.PropertyInfo.SetValue(entry.Component, isEnabled);
225+
}
226+
}
227+
228+
/// <summary>
229+
/// Applies states changes to all components being controlled by this instance.
230+
/// </summary>
231+
/// <param name="enabled">the state update to apply</param>
168232
private void ApplyEnabled(bool enabled)
169233
{
170234
foreach (var entry in m_ValidComponents)
171235
{
172-
entry.Value.SetValue(entry.Key, enabled);
236+
// If invert enabled is true, then use the inverted value passed in.
237+
// Otherwise, directly apply the value passed in.
238+
var isEnabled = entry.InvertEnabled ? !enabled : enabled;
239+
entry.PropertyInfo.SetValue(entry.Component, isEnabled);
173240
}
174241
}
175242

176243
/// <summary>
177-
/// Invoke on the authority side to enable or disable the <see cref="Object"/>s.
244+
/// Invoke on the authority side to enable or disable components assigned to this instance.
178245
/// </summary>
246+
/// <remarks>
247+
/// If any component entry has the <see cref="ComponentControllerEntry.InvertEnabled"/> set to true,
248+
/// then the inverse of the isEnabled property passed in will be used. If the component entry has the
249+
/// <see cref="ComponentControllerEntry.InvertEnabled"/> set to false (default), then the value of the
250+
/// isEnabled property will be applied.
251+
/// </remarks>
179252
/// <param name="isEnabled">true = enabled | false = disabled</param>
180253
public void SetEnabled(bool isEnabled)
181254
{

0 commit comments

Comments
 (0)