using System.Collections.Generic; using Fusion.Analyzer; using UnityEngine; namespace Fusion { #if UNITY_EDITOR using UnityEditor; #endif /// /// Automatically adds a for each indicated component. /// These indicated components will be limited to no more than one enabled instance when running in Multi-Peer mode. /// [AddComponentMenu("Fusion/Enable On Single Runner")] public class EnableOnSingleRunner : Fusion.Behaviour { /// /// If more than one runner instance is visible, this indicates which peer's clone of this entity should be visible. /// [InlineHelp] [SerializeField] #pragma warning disable IDE0044 // Add readonly modifier public RunnerVisibilityLink.PreferredRunners PreferredRunner; #pragma warning restore IDE0044 // Add readonly modifier /// /// Collection of components that will be marked for Multi-Peer mode as objects that should only have one enabled instance. /// [InlineHelp] public UnityEngine.Component[] Components = new Component[0]; /// /// Prefix for the GUIDs of components which are added at runtime. /// [HideInInspector] [SerializeField] private string _guid = System.Guid.NewGuid().ToString().Substring(0, 19); /// /// At runtime startup, this adds a for each component reference to this GameObject. /// internal void AddNodes(List existingNodes) { for(int i = 0; i < Components.Length; ++i) { var found = false; foreach (var existingNode in existingNodes) { if (existingNode.Component == Components[i]) { found = true; break; } } if (found) continue; var node = Components[i].gameObject.AddComponent(); node.Guid = _guid + i; node.Component = Components[i]; node.SetupOnSingleRunnerLink(PreferredRunner); existingNodes.Add(node); } } /// /// Finds visual/audio components on this GameObject, and adds them to the Components collection. /// [EditorButton("Find on GameObject", EditorButtonVisibility.EditMode, dirtyObject: true)] public void FindRecognizedTypes() { Components = FindRecognizedComponentsOnGameObject(gameObject); } /// /// Finds visual/audio nested components on this GameObject and its children, and adds them to the Components collection. /// [EditorButton("Find in Nested Children", EditorButtonVisibility.EditMode, dirtyObject: true)] public void FindNestedRecognizedTypes() { Components = FindRecognizedNestedComponents(gameObject); } [StaticField(StaticFieldResetMode.None)] private static readonly List reusableComponentsList = new List(); [StaticField(StaticFieldResetMode.None)] private static readonly List reusableComponentsList2 = new List(); private static Component[] FindRecognizedComponentsOnGameObject(GameObject go) { try { go.GetComponents(reusableComponentsList); reusableComponentsList2.Clear(); foreach (var comp in reusableComponentsList) { var type = comp.GetType(); if (type.IsRecognizedByRunnerVisibility()) { reusableComponentsList2.Add(comp); } } return reusableComponentsList2.ToArray(); } finally { reusableComponentsList.Clear(); reusableComponentsList2.Clear(); } } private static Component[] FindRecognizedNestedComponents(GameObject go) { try { go.transform.GetNestedComponentsInChildren(reusableComponentsList, true); reusableComponentsList2.Clear(); foreach (var comp in reusableComponentsList) { var type = comp.GetType(); if (type.IsRecognizedByRunnerVisibility()) { reusableComponentsList2.Add(comp); } } return reusableComponentsList2.ToArray(); } finally { reusableComponentsList.Clear(); reusableComponentsList2.Clear(); } } } }