-
Notifications
You must be signed in to change notification settings - Fork 562
feat: tool to enable monobehaviours only on server or client #477
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
Changes from all commits
6080134
cd026e6
e673ac9
864b789
fb6a563
ada0a1d
e1e5528
21410ee
7e88dda
cb365f2
2e55d32
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Unity.Netcode; | ||
using UnityEngine; | ||
|
||
namespace Unity.Multiplayer.Samples.Utilities | ||
{ | ||
/// <summary> | ||
/// Classes implementing this interface get disabled on Awake by the OnSpawnBehaviorEnabler, then only enabled when | ||
/// it is spawned on a client. | ||
///<remarks> | ||
/// Any class implementing this should add the "[RequireComponent(typeof(OnSpawnBehaviourEnabler))]" attribute | ||
/// </remarks> | ||
/// </summary> | ||
public interface IClientOnlyMonoBehaviour | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So if those interfaces are tightly coupled to monobehaviour and netcode, any reason we wouldn't just have an abstract class that inherits from NetworkBehaviour and has SetEnabled as abstract method? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An earlier version of this used inheritance, with a single class inheriting NetworkBehavior with a protected field telling if it was meant for a server or a client. The disabling/enabling was handled by that abstract class in its Awake, OnSpawn and OnDespwn events. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. Yeah makes sense. I wonder if there could be a way to dynamically add the enabler without requiring us to remember to add it. It's too bad "RequireComponent" doesn't work on interfaces. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @LukeStampfli @pdeschain @fernando-cortez what do you guys think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could add "RequireComponent" to the classes implementing these interfaces themselves I suppose, but it's still not as plug-and-play as I hoped it could be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thinking back on it, would adding this recommendation as remarks in the interface descriptions be sufficient? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think using an interface here is better than using inheritance. With the updated xml docs on the interfaces I think it is easy enough to understand how to use this. |
||
{ | ||
public void SetEnabled(bool enable); | ||
} | ||
|
||
/// <summary> | ||
/// Classes implementing this interface get disabled on Awake by the OnSpawnBehaviorEnabler, then only enabled when | ||
/// it is spawned on a server. | ||
///<remarks> | ||
/// Any class implementing this should add the "[RequireComponent(typeof(OnSpawnBehaviourEnabler))]" attribute | ||
/// </remarks> | ||
/// </summary> | ||
public interface IServerOnlyMonoBehaviour | ||
{ | ||
public void SetEnabled(bool enable); | ||
} | ||
|
||
|
||
/// <summary> | ||
/// Disables a list of MonoBehaviours on Awake, then only enables them when spawning based on whether this game instance | ||
/// is a client or a server (or both in case of a client-hosted session). | ||
/// </summary> | ||
public class OnSpawnBehaviourEnabler : NetworkBehaviour | ||
{ | ||
List<IClientOnlyMonoBehaviour> m_ClientOnlyMonoBehaviours; | ||
List<IServerOnlyMonoBehaviour> m_ServerOnlyMonoBehaviours; | ||
|
||
void Awake() | ||
{ | ||
m_ClientOnlyMonoBehaviours = new List<IClientOnlyMonoBehaviour>(); | ||
m_ServerOnlyMonoBehaviours = new List<IServerOnlyMonoBehaviour>(); | ||
foreach (var behaviour in gameObject.GetComponents<IClientOnlyMonoBehaviour>()) | ||
{ | ||
m_ClientOnlyMonoBehaviours.Add(behaviour); | ||
} | ||
foreach (var behaviour in gameObject.GetComponents<IServerOnlyMonoBehaviour>()) | ||
{ | ||
m_ServerOnlyMonoBehaviours.Add(behaviour); | ||
} | ||
// Disable everything here to prevent those MonoBehaviours to be updated before this one is spawned. | ||
DisableAll(); | ||
} | ||
|
||
public override void OnNetworkSpawn() | ||
{ | ||
if (IsClient) | ||
{ | ||
foreach (var behaviour in m_ClientOnlyMonoBehaviours) | ||
{ | ||
behaviour.SetEnabled(true); | ||
} | ||
} | ||
|
||
if (IsServer) | ||
{ | ||
foreach (var behaviour in m_ServerOnlyMonoBehaviours) | ||
{ | ||
behaviour.SetEnabled(true); | ||
} | ||
} | ||
} | ||
|
||
public override void OnNetworkDespawn() | ||
{ | ||
// Disable everything and wait until it is spawned again to enable them again | ||
DisableAll(); | ||
} | ||
|
||
void DisableAll() | ||
{ | ||
foreach (var behaviour in m_ClientOnlyMonoBehaviours) | ||
{ | ||
behaviour.SetEnabled(false); | ||
} | ||
|
||
foreach (var behaviour in m_ServerOnlyMonoBehaviours) | ||
{ | ||
behaviour.SetEnabled(false); | ||
} | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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.
This file will be moved to the Utilities package when the PR will leave the draft status. I kept it here to make testing and iterating easier since ParrelSync doesn't sync the packages folder automatically