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 即可

Photon自定义加载Resource之外的资源的更多相关文章

  1. 05.Spring 资源加载 - Resource

    基本概念 Spring 把所有能记录信息的载体,如各种类型的文件.二进制流等都称为资源. 对 Spring 开发者来说,最常用的资源就是 Spring 配置文件(通常是一份 XML 格式的文件). S ...

  2. Java类加载机制及自定义加载器

    转载:https://www.cnblogs.com/gdpuzxs/p/7044963.html Java类加载机制及自定义加载器 一:ClassLoader类加载器,主要的作用是将class文件加 ...

  3. spring3: 4.4 使用路径通配符加载Resource

    4.4.1  使用路径通配符加载Resource 前面介绍的资源路径都是非常简单的一个路径匹配一个资源,Spring还提供了一种更强大的Ant模式通配符匹配,从能一个路径匹配一批资源. Ant路径通配 ...

  4. Android 自定义View修炼-自定义加载进度动画XCLoadingImageView

    一.概述 本自定义View,是加载进度动画的自定义View,继承于ImageView来实现,主要实现蒙层加载进度的加载进度效果. 支持水平左右加载和垂直上下加载四个方向,同时也支持自定义蒙层进度颜色. ...

  5. Android:webView加载h5网页视频,播放不了,以及横屏全屏的问题和实现自定义加载进度条的效果

    1.webView加载h5网页视频,播放不了,android3.0之后要在menifest添加硬件加速的属性 android:hardwareAccelerated="true". ...

  6. Entity Framework 无法加载指定的元数据资源。

    ADO.NET Entity Framework发布以来,本人也一直在用,深感好用,忍不住地要感谢微软啊!由于项目结构创建完成后,没怎么改动过,所以一直没出题过问题,可最近由于改动了下命名空间,问题来 ...

  7. [转] Entity Framework 无法加载指定的元数据资源。

    Entity Framework 发布以来,本人也一直在用,深感好用,忍不住地要感谢微软啊!由于项目结构创建完成后,没怎么改动过,所以一直没出题过问题,可最近由于改动了下命名空间,问题来了,正是标题中 ...

  8. asp.net读取用户控件,自定义加载用户控件

    1.自定义加载用户控件 ceshi.aspx页面 <html> <body> <div id="divControls" runat="se ...

  9. 关于document.write()加载JS等静态资源 和 异步async加载JS

    现流行浏览器对于静态资源的预加载 传统的浏览器,对于静态资源加载,会阻塞 HTML 解析器的线程进行,无论内联还是外链. 例如: <script src="test1.js" ...

随机推荐

  1. 词根:lun = moon, 表示“月亮”

    词根:lun = moon, 表示“月亮” lunar [lun月亮,-ar形容词后缀,…的] 月亮的,太阴的,似月的,新月形的 semilunar [semi-半,lun月亮,-ar形容词后缀,…的 ...

  2. 【c # 数据库】存储过程

    可理解存储过程是方法,快速调用,方便使用. 数据库建立新的存储过程: CREATE PROCEDURE myProc -- Add the parameters for the stored proc ...

  3. mysql学习3:mysql之my.cnf详解

    mysql之my.cnf详解 本文转自:https://www.cnblogs.com/panwenbin-logs/p/8360703.html 以下是 my.cnf 配置文件参数解释: #*** ...

  4. LAB8 android

    妈的,标签名字能改成自己的名字,我也是个神人嘞. 明明是去掉两个括号,怎么变成3个了,醉了. 点组件,attribute,可以修改对应的值.非常直观?. content_mail.XML要设置ID才能 ...

  5. Vue --1

    1.2 vue.js库的基本使用 在github下载:https://github.com/vuejs/vue/releases 在官网下载地址: https://cn.vuejs.org/v2/gu ...

  6. Oracle数值处理函数

    1.绝对值:abs()    select abs(-2) value from dual; 2.取整函数(大):ceil()    select ceil(-2.001) value from du ...

  7. Visual Studio Code 如何将新项目发布到GIT服务器

    1.在VSCode中新建或打开未添加源码管理的文件夹 2.按Ctrl+Shift+G切换到"源控件"视图,点击右上方的[初始化储存库]按钮 3.输入消息内容,然后点击右上方的[提交 ...

  8. 矩阵游戏(game)

    矩阵游戏(game) --九校联考24OI__D1T1 问题描述 LZK发明一个矩阵游戏,大家一起来玩玩吧,有一个N行M列的矩阵.第一行的数字是1,2,-M,第二行的数字是M+1,M+2-2*M,以此 ...

  9. win10无法访问服务器上的共享文件夹怎么设置,提示:你不能访问此共享文件夹,因为你组织的安全策略阻止未经身份验证的来宾访问

    此问题需要修改Win10 网络策略 按window+R键输入gpedit.msc 来启动本地组策略编辑器. 依次找到“计算机配置-管理模板-网络-Lanman工作站”这个节点,在右侧内容区可以看到“启 ...

  10. Java学习笔记:多线程(二)

    与线程生命周期相关的方法: sleep 调用sleep方法会进入计时等待状态,等待时间到了,进入就绪状态. yield 调用yield方法会让别的线程执行,但是不确保真正让出.较少使用,官方注释都说 ...