• Photon自定义加载Resource之外的资源


    PhotonNetwork.cs 结尾添加如下代码:

        #region >>> Photon自定义异步加载GameObject
    
        public delegate void CustomLoader(string prefabName, Action<UnityEngine.Object> ac);
        public static CustomLoader _loader;
        public static void RegisterCustomLoaderToPhoton(CustomLoader loader)
        {
            _loader = loader;
        }
    
        public static bool InstantiateCustom(string prefabName, Vector3 position, Quaternion rotation, byte group, object[] data, Action<GameObject> callback)
        {
            if (!connected || (InstantiateInRoomOnly && !inRoom))
            {
                Debug.LogError("Failed to Instantiate prefab: " + prefabName + ". Client should be in a room. Current connectionStateDetailed: " + PhotonNetwork.connectionStateDetailed);
                return false;
            }
    
            GameObject prefabGo;
            if (!UsePrefabCache || !PrefabCache.TryGetValue(prefabName, out prefabGo))
            {
                _loader(prefabName, (ab) =>
                {
                    prefabGo = (GameObject)(ab);
    
                    if (UsePrefabCache)
                    {
                        PrefabCache.Add(prefabName, prefabGo);
                    }
    
                    if (prefabGo == null)
                    {
                        Debug.LogError("Failed to Instantiate prefab: " + prefabName + ". Verify the Prefab is in a Resources folder (and not in a subfolder)");
                        callback.Invoke(null);
                    }
    
                    // a scene object instantiated with network visibility has to contain a PhotonView
                    if (prefabGo.GetComponent<PhotonView>() == null)
                    {
                        Debug.LogError("Failed to Instantiate prefab:" + prefabName + ". Prefab must have a PhotonView component.");
                        callback.Invoke(null);
                    }
    
                    Component[] views = (Component[])prefabGo.GetPhotonViewsInChildren();
                    int[] viewIDs = new int[views.Length];
                    for (int i = 0; i < viewIDs.Length; i++)
                    {
                        //Debug.Log("Instantiate prefabName: " + prefabName + " player.ID: " + player.ID);
                        viewIDs[i] = AllocateViewID(player.ID);
                    }
    
                    // Send to others, create info
                    Hashtable instantiateEvent = networkingPeer.SendInstantiate(prefabName, position, rotation, group, viewIDs, data, false);
    
                    // Instantiate the GO locally (but the same way as if it was done via event). This will also cache the instantiationId
                    callback.Invoke(networkingPeer.DoInstantiate(instantiateEvent, networkingPeer.LocalPlayer, prefabGo));
                });
                return true;
            }
            if (prefabGo != null)
            {
                // a scene object instantiated with network visibility has to contain a PhotonView
                if (prefabGo.GetComponent<PhotonView>() == null)
                {
                    Debug.LogError("Failed to Instantiate prefab:" + prefabName + ". Prefab must have a PhotonView component.");
                    callback.Invoke(null);
                }
    
                Component[] views = (Component[])prefabGo.GetPhotonViewsInChildren();
                int[] viewIDs = new int[views.Length];
                for (int i = 0; i < viewIDs.Length; i++)
                {
                    //Debug.Log("Instantiate prefabName: " + prefabName + " player.ID: " + player.ID);
                    viewIDs[i] = AllocateViewID(player.ID);
                }
    
                // Send to others, create info
                Hashtable instantiateEvent = networkingPeer.SendInstantiate(prefabName, position, rotation, group, viewIDs, data, false);
                callback.Invoke(networkingPeer.DoInstantiate(instantiateEvent, networkingPeer.LocalPlayer, prefabGo));
                return true;
            }
            return false;
        }
    
        #endregion
    

      

    NetworkingPeer.cs 结尾添加如下代码:

        #region >>> Photon自定义异步加载GameObject
    
        public delegate void CustomInstantiatedHandler(PhotonPlayer photonPlayer, GameObject go);
        public static event CustomInstantiatedHandler OnCustomInstantiated;
    
        internal void DoInstantiateCustom(Hashtable evData, PhotonPlayer photonPlayer, GameObject resourceGameObject, Action<GameObject> callback)
        {
            // some values always present:
            string prefabName = (string)evData[(byte)0];
            int serverTime = (int)evData[(byte)6];
            int instantiationId = (int)evData[(byte)7];
    
            Vector3 position;
            if (evData.ContainsKey((byte)1))
            {
                position = (Vector3)evData[(byte)1];
            }
            else
            {
                position = Vector3.zero;
            }
    
            Quaternion rotation = Quaternion.identity;
            if (evData.ContainsKey((byte)2))
            {
                rotation = (Quaternion)evData[(byte)2];
            }
    
            byte group = 0;
            if (evData.ContainsKey((byte)3))
            {
                group = (byte)evData[(byte)3];
            }
    
            short objLevelPrefix = 0;
            if (evData.ContainsKey((byte)8))
            {
                objLevelPrefix = (short)evData[(byte)8];
            }
    
            int[] viewsIDs;
            if (evData.ContainsKey((byte)4))
            {
                viewsIDs = (int[])evData[(byte)4];
            }
            else
            {
                viewsIDs = new int[1] { instantiationId };
            }
    
            object[] incomingInstantiationData;
            if (evData.ContainsKey((byte)5))
            {
                incomingInstantiationData = (object[])evData[(byte)5];
            }
            else
            {
                incomingInstantiationData = null;
            }
    
            // SetReceiving filtering
            if (group != 0 && !this.allowedReceivingGroups.Contains(group))
            {
                if (callback != null)
                {
                    callback.Invoke(null);
                }
                return; // Ignore group
            }
    
            if (ObjectPool != null) // 使用对象池的情况
            {
                GameObject go = ObjectPool.Instantiate(prefabName, position, rotation);
    
                PhotonView[] photonViews = go.GetPhotonViewsInChildren();
                if (photonViews.Length != viewsIDs.Length)
                {
                    throw new Exception("Error in Instantiation! The resource's PhotonView count is not the same as in incoming data.");
                }
                for (int i = 0; i < photonViews.Length; i++)
                {
                    photonViews[i].didAwake = false;
                    photonViews[i].viewID = 0;
    
                    photonViews[i].prefix = objLevelPrefix;
                    photonViews[i].instantiationId = instantiationId;
                    photonViews[i].isRuntimeInstantiated = true;
                    photonViews[i].instantiationDataField = incomingInstantiationData;
    
                    photonViews[i].didAwake = true;
                    photonViews[i].viewID = viewsIDs[i];    // with didAwake true and viewID == 0, this will also register the view
                }
    
                // Send OnPhotonInstantiate callback to newly created GO.
                // GO will be enabled when instantiated from Prefab and it does not matter if the script is enabled or disabled.
                go.SendMessage(OnPhotonInstantiateString, new PhotonMessageInfo(photonPlayer, serverTime, null), SendMessageOptions.DontRequireReceiver);
                if (callback != null)
                {
                    callback.Invoke(go);
                    if (OnCustomInstantiated != null)
                    {
                        OnCustomInstantiated.Invoke(photonPlayer, go);
                    }
                }
                return;
            }
            else
            {
                // load prefab, if it wasn't loaded before (calling methods might do this)
                if (resourceGameObject == null)
                {
                    if (!NetworkingPeer.UsePrefabCache || !NetworkingPeer.PrefabCache.TryGetValue(prefabName, out resourceGameObject))
                    {
                        //resourceGameObject = (GameObject)Resources.Load(prefabName, typeof(GameObject));
                        PhotonNetwork._loader(prefabName, (ab) =>
                        {
                            resourceGameObject = (GameObject)ab;
                            if (NetworkingPeer.UsePrefabCache)
                            {
                                NetworkingPeer.PrefabCache.Add(prefabName, resourceGameObject);
                            }
                            if (resourceGameObject == null)
                            {
                                Debug.LogError("PhotonNetwork error: Could not find the bundle [" + prefabName + "]. Please verify you have this gameobject in a StreamingAssets/Res folder.");
                                if (callback != null)
                                {
                                    callback.Invoke(null);
                                }
                                return;
                            }
    
                            // now modify the loaded "blueprint" object before it becomes a part of the scene (by instantiating it)
                            PhotonView[] resourcePVs = resourceGameObject.GetPhotonViewsInChildren();
                            if (resourcePVs.Length != viewsIDs.Length)
                            {
                                throw new Exception("Error in Instantiation! The resource's PhotonView count is not the same as in incoming data.");
                            }
    
                            for (int i = 0; i < viewsIDs.Length; i++)
                            {
                                // NOTE instantiating the loaded resource will keep the viewID but would not copy instantiation data, so it's set below
                                // so we only set the viewID and instantiationId now. the instantiationData can be fetched
                                resourcePVs[i].viewID = viewsIDs[i];
                                resourcePVs[i].prefix = objLevelPrefix;
                                resourcePVs[i].instantiationId = instantiationId;
                                resourcePVs[i].isRuntimeInstantiated = true;
                            }
    
                            this.StoreInstantiationData(instantiationId, incomingInstantiationData);
    
                            // load the resource and set it's values before instantiating it:
                            GameObject go = (GameObject)GameObject.Instantiate(resourceGameObject, position, rotation);
    
                            for (int i = 0; i < viewsIDs.Length; i++)
                            {
                                // NOTE instantiating the loaded resource will keep the viewID but would not copy instantiation data, so it's set below
                                // so we only set the viewID and instantiationId now. the instantiationData can be fetched
                                resourcePVs[i].viewID = 0;
                                resourcePVs[i].prefix = -1;
                                resourcePVs[i].prefixBackup = -1;
                                resourcePVs[i].instantiationId = -1;
                                resourcePVs[i].isRuntimeInstantiated = false;
                            }
    
                            this.RemoveInstantiationData(instantiationId);
    
                            // Send OnPhotonInstantiate callback to newly created GO.
                            // GO will be enabled when instantiated from Prefab and it does not matter if the script is enabled or disabled.
                            go.SendMessage(OnPhotonInstantiateString, new PhotonMessageInfo(photonPlayer, serverTime, null), SendMessageOptions.DontRequireReceiver);
                            if (callback != null)
                            {
                                callback.Invoke(go);
                                if (OnCustomInstantiated != null)
                                {
                                    OnCustomInstantiated.Invoke(photonPlayer, go);
                                }
                            }
                            return;
    
                        });
                    }
                    else
                    {
                        // now modify the loaded "blueprint" object before it becomes a part of the scene (by instantiating it)
                        PhotonView[] resourcePVs = resourceGameObject.GetPhotonViewsInChildren();
                        if (resourcePVs.Length != viewsIDs.Length)
                        {
                            throw new Exception("Error in Instantiation! The resource's PhotonView count is not the same as in incoming data.");
                        }
    
                        for (int i = 0; i < viewsIDs.Length; i++)
                        {
                            // NOTE instantiating the loaded resource will keep the viewID but would not copy instantiation data, so it's set below
                            // so we only set the viewID and instantiationId now. the instantiationData can be fetched
                            resourcePVs[i].viewID = viewsIDs[i];
                            resourcePVs[i].prefix = objLevelPrefix;
                            resourcePVs[i].instantiationId = instantiationId;
                            resourcePVs[i].isRuntimeInstantiated = true;
                        }
    
                        this.StoreInstantiationData(instantiationId, incomingInstantiationData);
    
                        // load the resource and set it's values before instantiating it:
                        GameObject go = (GameObject)GameObject.Instantiate(resourceGameObject, position, rotation);
    
                        for (int i = 0; i < viewsIDs.Length; i++)
                        {
                            // NOTE instantiating the loaded resource will keep the viewID but would not copy instantiation data, so it's set below
                            // so we only set the viewID and instantiationId now. the instantiationData can be fetched
                            resourcePVs[i].viewID = 0;
                            resourcePVs[i].prefix = -1;
                            resourcePVs[i].prefixBackup = -1;
                            resourcePVs[i].instantiationId = -1;
                            resourcePVs[i].isRuntimeInstantiated = false;
                        }
    
                        this.RemoveInstantiationData(instantiationId);
    
                        // Send OnPhotonInstantiate callback to newly created GO.
                        // GO will be enabled when instantiated from Prefab and it does not matter if the script is enabled or disabled.
                        go.SendMessage(OnPhotonInstantiateString, new PhotonMessageInfo(photonPlayer, serverTime, null), SendMessageOptions.DontRequireReceiver);
                        if (callback != null)
                        {
                            callback.Invoke(go);
                            if (OnCustomInstantiated != null)
                            {
                                OnCustomInstantiated.Invoke(photonPlayer, go);
                            }
                        }
                        return;
                    }
                }
            }
        }
    
        #endregion
    

      

    NetworkingPeer.cs 第2598行:

    屏蔽掉原有的 DoInstantiate 调用,改为 DoInstantiateCustom 调用

                    //this.DoInstantiate((Hashtable)photonEvent[ParameterCode.Data], originatingPlayer, null);
                    this.DoInstantiateCustom((Hashtable)photonEvent[ParameterCode.Data], originatingPlayer, null, (go) => {
                        SendMonoMessage(PhotonNetworkingMessage.OnPhotonInstantiate, new PhotonMessageInfo(originatingPlayer, 0, go.GetComponent<PhotonView>()));
                    });
    

    回调的意义在于你可以在初始Photon.MonoBehaviour中捕获全局的OnPhotonInstantiate网络物体初始回调,同样的你也可以通过OnCustomInstantiated事件来自定义回调事件行为

     

    之后记得调用 PhotonNetwork.RegisterCustomLoaderToPhoton 注册一个自定义的默认异步资源加载方法给 Photon 即可

  • 相关阅读:
    js基础 ---- 为什么定时器时间不准确
    vue 3.0 ---- reactive函数
    vue 3.0 ---- ref函数
    vue 3.0 ---- setup函数
    vue 3.0 ---- 什么是vite
    Vue warn]: Error in event handler for "click": "TypeError: fns.apply is not a function"
    vueJs 自动清除文本框的 空格
    vue 报错解决 -------- DOMException: Failed to execute 'insertBefore' on 'Node' --------------------"NotFoundError: Failed to execute 'insertBefore' on 'Node': The node before
    vue 中 uuid 的使用以及作用
    赞不绝口钉钉自动点赞器
  • 原文地址:https://www.cnblogs.com/kenkao/p/10276556.html
Copyright © 2020-2023  润新知