using FishNet.Documenting; using FishNet.Serializing.Helping; using FishNet.Utility.Constant; using System.Runtime.CompilerServices; using UnityEngine; [assembly: InternalsVisibleTo(UtilityConstants.CODEGEN_ASSEMBLY_NAME)] namespace FishNet.Object { /// /// Scripts which inherit from NetworkBehaviour can be used to gain insight of, and perform actions on the network. /// public abstract partial class NetworkBehaviour : MonoBehaviour { /// /// True if this NetworkBehaviour is initialized for the network. /// public bool IsSpawned => _networkObjectCache.IsSpawned; /// /// /// [SerializeField, HideInInspector] private byte _componentIndexCache = byte.MaxValue; /// /// ComponentIndex for this NetworkBehaviour. /// public byte ComponentIndex { get => _componentIndexCache; private set => _componentIndexCache = value; } #if UNITY_EDITOR /// /// NetworkObject automatically added or discovered during edit time. /// [SerializeField, HideInInspector] private NetworkObject _addedNetworkObject; #endif /// /// /// [SerializeField, HideInInspector] private NetworkObject _networkObjectCache; /// /// NetworkObject this behaviour is for. /// public NetworkObject NetworkObject => _networkObjectCache; /// /// Initializes this script. This will only run once even as host. /// /// /// internal void InitializeOnce_Internal() { InitializeOnceSyncTypes(); InitializeOnceRpcLinks(); } /// /// Serializes information for network components. /// internal void SerializeComponents(NetworkObject nob, byte componentIndex) { _networkObjectCache = nob; ComponentIndex = componentIndex; } /// /// Manually initializes network content for the NetworkBehaviour if the object it's on is disabled. /// internal void InitializeIfDisabled() { if (gameObject.activeInHierarchy) return; NetworkInitializeIfDisabled(); } /// /// Long name is to prevent users from potentially creating their own method named the same. /// [CodegenMakePublic] [APIExclude] internal virtual void NetworkInitializeIfDisabled() { } #region Editor. protected virtual void Reset() { #if UNITY_EDITOR if (Application.isPlaying) return; TryAddNetworkObject(); #endif } protected virtual void OnValidate() { #if UNITY_EDITOR if (Application.isPlaying) return; TryAddNetworkObject(); #endif } /// /// Resets this NetworkBehaviour so that it may be added to an object pool. /// internal void ResetForObjectPool() { ResetSyncTypes(); ClearReplicateCache(); ClearBuffedRpcs(); } /// /// Tries to add the NetworkObject component. /// private NetworkObject TryAddNetworkObject() { #if UNITY_EDITOR if (Application.isPlaying) return _addedNetworkObject; if (_addedNetworkObject != null) { AlertToDuplicateNetworkObjects(_addedNetworkObject.transform); return _addedNetworkObject; } /* Manually iterate up the chain because GetComponentInParent doesn't * work when modifying prefabs in the inspector. Unity, you're starting * to suck a lot right now. */ NetworkObject result = null; Transform climb = transform; while (climb != null) { if (climb.TryGetComponent(out result)) break; else climb = climb.parent; } if (result != null) { _addedNetworkObject = result; } //Not found, add a new nob. else { _addedNetworkObject = transform.root.gameObject.AddComponent(); Debug.Log($"Script {GetType().Name} on object {gameObject.name} added a NetworkObject component to {transform.root.name}."); } AlertToDuplicateNetworkObjects(_addedNetworkObject.transform); return _addedNetworkObject; //Removes duplicate network objects from t. void AlertToDuplicateNetworkObjects(Transform t) { NetworkObject[] nobs = t.GetComponents(); //This shouldn't be possible but does occur sometimes; maybe a unity bug? if (nobs.Length > 1) { //Update added to first entryt. _addedNetworkObject = nobs[0]; string useMenu = " You may also use the Fish-Networking menu to automatically remove duplicate NetworkObjects."; string sceneName = t.gameObject.scene.name; if (string.IsNullOrEmpty(sceneName)) Debug.LogError($"Prefab {t.name} has multiple NetworkObject components. Please remove the extra component(s) to prevent errors.{useMenu}"); else Debug.LogError($"Object {t.name} in scene {sceneName} has multiple NetworkObject components. Please remove the extra component(s) to prevent errors.{useMenu}"); } } #else return null; #endif } #endregion } }