- {
- "AssetList" : [{
- "Name" : "Chair 1",
- "Source" : "Prefabs/Chair001.unity3d",
- "Position" : [2,0,-5],
- "Rotation" : [0.0,60.0,0.0]
- },
- {
- "Name" : "Chair 2",
- "Source" : "Prefabs/Chair001.unity3d",
- "Position" : [1,0,-5],
- "Rotation" : [0.0,0.0,0.0]
- },
- {
- "Name" : "Vanity",
- "Source" : "Prefabs/vanity001.unity3d",
- "Position" : [0,0,-4],
- "Rotation" : [0.0,0.0,0.0]
- },
- {
- "Name" : "Writing Table",
- "Source" : "Prefabs/writingTable001.unity3d",
- "Position" : [0,0,-7],
- "Rotation" : [0.0,0.0,0.0],
- "AssetList" : [{
- "Name" : "Lamp",
- "Source" : "Prefabs/lamp001.unity3d",
- "Position" : [-0.5,0.7,-7],
- "Rotation" : [0.0,0.0,0.0]
- }]
- }]
- }
AssetList:场景中资源的列表,每一个资源都对应一个unity3D的gameobject
Name:gameobject的名字,一个场景中不应该重名
Source:资源的物理路径及文件名
Position:gameobject的坐标
Rotation:gameobject的旋转角度
你会注意到Writing Table里面包含了Lamp,这两个对象是父子的关系。配置文件应该是由程序生成的,手工也可以修改。另外在游戏上线后,客户端接收到的配置文件应该是加密并压缩过的。
主程序:
|
这里面用到了C#的事件机制,大家可以看看我以前
- 。。。
- private MainMonoBehavior mainMonoBehavior;
- private string mResourcePath;
- private Scene mScene;
- private Asset mSceneAsset;
- private ResourceManager() {
- mainMonoBehavior = GameObject.Find("Main Camera").GetComponent<MainMonoBehavior>();
- mResourcePath = PathUtil.getResourcePath();
- }
- public void LoadSence(string fileName) {
- mSceneAsset = new Asset();
- mSceneAsset.Type = Asset.TYPE_JSON;
- mSceneAsset.Source = fileName;
- mainMonoBehavior.UpdateEvent += OnUpdate;
- }
- 。。。
在LoadSence方法里先创建一个Asset的对象,这个对象是对应于配置文件的,设置type是Json,source是传进来的“Scenes/MyDemoSence.txt”。然后注册MainMonoBehavior的update事件。
|
OnUpdate方法里调用LoadAsset加载配置文件对象及所有资源对象。每一帧都要判断是否加载结束,如果结束清空mScene和mSceneAsset对象为下一次加载做准备,并且取消update事件的注册。
最核心的LoadAsset方法:
|
传进来的是要加载的资源对象,先得到它的物理地址,mResourcePath是个全局变量保存资源服务器的网址,得到fullFileName类似
- 。。。
- if (asset.Type == Asset.TYPE_JSON) { //Json
- if (mScene == null) {
- string jsonTxt = mSceneAsset.www.text;
- mScene = JsonMapper.ToObject<Scene>(jsonTxt);
- }
- //load scene
- foreach (Asset sceneAsset in mScene.AssetList) {
- if (sceneAsset.isLoadFinished) {
- continue;
- } else {
- LoadAsset(sceneAsset);
- if (!sceneAsset.isLoadFinished) {
- return null;
- }
- }
- }
- }
- 。。。
代码能够运行到这里,说明资源都已经下载完毕了。现在开始加载处理资源了。第一次肯定是先加载配置文件,因为是Json格式,用JsonMapper类把它转换成C#对象,我用的是LitJson开源类库。然后循环递归处理场景中的每一个资源。如果没有完成,返回null,等待下一帧处理。
继续LoadAsset方法:
|
终于开始处理真正的资源了,从缓存中找到www对象,调用Instantiate方法
- private void UpdateGameObject(GameObject go, Asset asset) {
- //name
- go.name = asset.Name;
- //position
- Vector3 vector3 = new Vector3((float)asset.Position[0], (float)asset.Position[1], (float)asset.Position[2]);
- go.transform.position = vector3;
- //rotation
- vector3 = new Vector3((float)asset.Rotation[0], (float)asset.Rotation[1], (float)asset.Rotation[2]);
- go.transform.eulerAngles = vector3;
- }
这里只设置了gameobject的3个属性,眼力好的同学一定会发现这些对象都是“死的”,因为少了
- public class Scene {
- public List<Asset> AssetList {
- get;
- set;
- }
- }
- public class Asset {
- public const byte TYPE_JSON = 1;
- public const byte TYPE_GAMEOBJECT = 2;
- public Asset() {
- //default type is gameobject for json load
- Type = TYPE_GAMEOBJECT;
- }
- public byte Type {
- get;
- set;
- }
- public string Name {
- get;
- set;
- }
- public string Source {
- get;
- set;
- }
- public double[] Bounds {
- get;
- set;
- }
- public double[] Position {
- get;
- set;
- }
- public double[] Rotation {
- get;
- set;
- }
- public List<Asset> AssetList {
- get;
- set;
- }
- public bool isLoadFinished {
- get;
- set;
- }
- public WWW www {
- get;
- set;
- }
- public GameObject gameObject {
- get;
- set;
- }
- }
代码就讲完了,在我实际测试中,会看到gameobject一个个加载并显示在屏幕中,并不会影响到游戏操作。代码还需要进一步完善适合更多的资源类型,如动画资源,文本,字体,图片和声音资源。
动态加载资源除了网络游戏必需,对于大公司的游戏开发也是必须的。它可以让游戏策划(负责场景设计),美工和程序3个角色独立出来,极大提高开发效率。试想如果策划改变了什么NPC的位置,美工改变了某个动画,或者改变了某个程序,大家都要重新倒入一遍资源是多么低效和麻烦的一件事。
- {
- "AssetList" : [{
- "Name" : "Chair 1",
- "Source" : "Prefabs/Chair001.unity3d",
- "Position" : [2,0,-5],
- "Rotation" : [0.0,60.0,0.0]
- },
- {
- "Name" : "Chair 2",
- "Source" : "Prefabs/Chair001.unity3d",
- "Position" : [1,0,-5],
- "Rotation" : [0.0,0.0,0.0]
- },
- {
- "Name" : "Vanity",
- "Source" : "Prefabs/vanity001.unity3d",
- "Position" : [0,0,-4],
- "Rotation" : [0.0,0.0,0.0]
- },
- {
- "Name" : "Writing Table",
- "Source" : "Prefabs/writingTable001.unity3d",
- "Position" : [0,0,-7],
- "Rotation" : [0.0,0.0,0.0],
- "AssetList" : [{
- "Name" : "Lamp",
- "Source" : "Prefabs/lamp001.unity3d",
- "Position" : [-0.5,0.7,-7],
- "Rotation" : [0.0,0.0,0.0]
- }]
- }]
- }
AssetList:场景中资源的列表,每一个资源都对应一个unity3D的gameobject
Name:gameobject的名字,一个场景中不应该重名
Source:资源的物理路径及文件名
Position:gameobject的坐标
Rotation:gameobject的旋转角度
你会注意到Writing Table里面包含了Lamp,这两个对象是父子的关系。配置文件应该是由程序生成的,手工也可以修改。另外在游戏上线后,客户端接收到的配置文件应该是加密并压缩过的。
主程序:
|
这里面用到了C#的事件机制,大家可以看看我以前
- 。。。
- private MainMonoBehavior mainMonoBehavior;
- private string mResourcePath;
- private Scene mScene;
- private Asset mSceneAsset;
- private ResourceManager() {
- mainMonoBehavior = GameObject.Find("Main Camera").GetComponent<MainMonoBehavior>();
- mResourcePath = PathUtil.getResourcePath();
- }
- public void LoadSence(string fileName) {
- mSceneAsset = new Asset();
- mSceneAsset.Type = Asset.TYPE_JSON;
- mSceneAsset.Source = fileName;
- mainMonoBehavior.UpdateEvent += OnUpdate;
- }
- 。。。
在LoadSence方法里先创建一个Asset的对象,这个对象是对应于配置文件的,设置type是Json,source是传进来的“Scenes/MyDemoSence.txt”。然后注册MainMonoBehavior的update事件。
|
OnUpdate方法里调用LoadAsset加载配置文件对象及所有资源对象。每一帧都要判断是否加载结束,如果结束清空mScene和mSceneAsset对象为下一次加载做准备,并且取消update事件的注册。
最核心的LoadAsset方法:
|
传进来的是要加载的资源对象,先得到它的物理地址,mResourcePath是个全局变量保存资源服务器的网址,得到fullFileName类似
- 。。。
- if (asset.Type == Asset.TYPE_JSON) { //Json
- if (mScene == null) {
- string jsonTxt = mSceneAsset.www.text;
- mScene = JsonMapper.ToObject<Scene>(jsonTxt);
- }
- //load scene
- foreach (Asset sceneAsset in mScene.AssetList) {
- if (sceneAsset.isLoadFinished) {
- continue;
- } else {
- LoadAsset(sceneAsset);
- if (!sceneAsset.isLoadFinished) {
- return null;
- }
- }
- }
- }
- 。。。
代码能够运行到这里,说明资源都已经下载完毕了。现在开始加载处理资源了。第一次肯定是先加载配置文件,因为是Json格式,用JsonMapper类把它转换成C#对象,我用的是LitJson开源类库。然后循环递归处理场景中的每一个资源。如果没有完成,返回null,等待下一帧处理。
继续LoadAsset方法:
|
终于开始处理真正的资源了,从缓存中找到www对象,调用Instantiate方法
- private void UpdateGameObject(GameObject go, Asset asset) {
- //name
- go.name = asset.Name;
- //position
- Vector3 vector3 = new Vector3((float)asset.Position[0], (float)asset.Position[1], (float)asset.Position[2]);
- go.transform.position = vector3;
- //rotation
- vector3 = new Vector3((float)asset.Rotation[0], (float)asset.Rotation[1], (float)asset.Rotation[2]);
- go.transform.eulerAngles = vector3;
- }
这里只设置了gameobject的3个属性,眼力好的同学一定会发现这些对象都是“死的”,因为少了
- public class Scene {
- public List<Asset> AssetList {
- get;
- set;
- }
- }
- public class Asset {
- public const byte TYPE_JSON = 1;
- public const byte TYPE_GAMEOBJECT = 2;
- public Asset() {
- //default type is gameobject for json load
- Type = TYPE_GAMEOBJECT;
- }
- public byte Type {
- get;
- set;
- }
- public string Name {
- get;
- set;
- }
- public string Source {
- get;
- set;
- }
- public double[] Bounds {
- get;
- set;
- }
- public double[] Position {
- get;
- set;
- }
- public double[] Rotation {
- get;
- set;
- }
- public List<Asset> AssetList {
- get;
- set;
- }
- public bool isLoadFinished {
- get;
- set;
- }
- public WWW www {
- get;
- set;
- }
- public GameObject gameObject {
- get;
- set;
- }
- }
代码就讲完了,在我实际测试中,会看到gameobject一个个加载并显示在屏幕中,并不会影响到游戏操作。代码还需要进一步完善适合更多的资源类型,如动画资源,文本,字体,图片和声音资源。
动态加载资源除了网络游戏必需,对于大公司的游戏开发也是必须的。它可以让游戏策划(负责场景设计),美工和程序3个角色独立出来,极大提高开发效率。试想如果策划改变了什么NPC的位置,美工改变了某个动画,或者改变了某个程序,大家都要重新倒入一遍资源是多么低效和麻烦的一件事。