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

时间:2021-12-31 04:19:03

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&period;Spring 资源加载 - Resource

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

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

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

  3. spring3&colon; 4&period;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. &lbrack;转&rsqb; Entity Framework 无法加载指定的元数据资源。

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

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

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

  9. 关于document&period;write&lpar;&rpar;加载JS等静态资源 和 异步async加载JS

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

随机推荐

  1. 走进AngularJs&lpar;三&rpar;自定义指令-----(上)

    一.有感而发的一些话 在学习ng之前有听前辈说过,angular上手比较难,初学者可能不太适应其语法以及思想.随着对ng探索的一步步深入,也确实感觉到了这一点,尤其是框架内部的某些执行机制,其复杂程度 ...

  2. 冲刺阶段 day 8

    项目进展:教师部分包括教师所属系别.工号.姓名.性别.电话.邮箱.地址.我们已经基本完成窗体的构建和代码编写.可以实现教师信息的增加查询. 代码如下: using System; using Syst ...

  3. 【ArcGIS二次开发】CreateFeature报错(HRESULT E&lowbar;FAIL)

    在VS2010下基于ArcGIS 10.1做二次开发时遇到个奇怪的问题,对于MXD工程文档中已经存在的图层,获取其FeatureClass可以调用CreateFeature()函数生成要素,但是对于通 ...

  4. Java日期格式化

    翻译人员: 铁锚 翻译时间: 2013年11月17日 原文链接:   Simple example to show how to use Date Formatting in Java 代码示例如下, ...

  5. Ubuntu下安装搜狗拼音输入法

    Ubuntu默认输入法是ibus输入法,其实用着也可以了,但是说句实话在某些情况下真的不怎么智能.习惯了搜狗所以,查阅资料测试成功后整理如下, 1.安装搜狗拼音 sudo apt-add-reposi ...

  6. 使用Pushlet来实现服务器端向客户端推送信息

        使用Pushlet来实现服务器端向客户端推送信息 1.   实现方式: 有两种实现方式: 1.         通过配置文件来实现定时的从服务器端向客户端推送信息 2.         通过A ...

  7. 什么是UDP

  8. SpringJPA主键生成采用自定义ID,自定义ID采用年月日时间格式

    自定义主键生成策略 在entity类上添加注解 @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "custom ...

  9. shell中与C语言中的区别

    shell中为啥与C语言有区别呢?弄成一样的不是很好么,其实不然,shell提供很多操作,这些操作不单单是执行程序或者命令,在很多时候是执行脚本的,简单的shell就是脚本编程,它的主要目的是处理文件 ...

  10. 转载 javascript中&lpar;function&lpar;&dollar;&rpar;&lbrace;&period;&period;&period;&rcub;&rpar;&lpar;jQuery&rpar;写法是什么意思

    javascript中(function($){...})(jQuery)写法是什么意思   这里实际上是匿名函数function(arg){...}这就定义了一个匿名函数,参数为arg 而调用函数 ...