纳金网
标题:
unity3d动态加载及生成配置文件(二)
[打印本页]
作者:
奔跑的小兔
时间:
2012-5-10 15:12
标题:
unity3d动态加载及生成配置文件(二)
这里面用到了C#的事件机制,大家可以看看我以前翻译过的国外一个牛人的文章。C# 事件和Unity3D
在 start方法里调用ResourceManager,先加载配置文件。每一次调用update方法,MainMonoBehavior会把update 事件分发给ResourceManager,因为ResourceManager注册了MainMonoBehavior的update事件。
辅助类:ResourceManager.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using LitJson;
using System.Net;
public class ResourceManager
{
// Use this for initialization
private MainMonoBehavior mainMonoBehavior;
private string mResourcePath;
private Scene mScene;
private Asset mSceneAsset;
private static ResourceManager resourceManager=new ResourceManager();//如果没有new 会出现没有实例化的错误
private Dictionary<string ,WWW > wwwCacheMap=new Dictionary<string,WWW>();//这个新添加的原文代码中没有定义它 应该是个字典
public static ResourceManager getInstance( )
{
return resourceManager;//静态函数中不能使用非静态成员
}
public ResourceManager()
{
mainMonoBehavior = GameObject.Find("Main Camera").GetComponent<MainMonoBehavior>();
mResourcePath ="file://"+Application.dataPath+"/..";
}
public void LoadSence(string fileName)
{
//Debug.Log(fileName);
mSceneAsset = new Asset();
mSceneAsset.Type = Asset.TYPE_JSON;//后面类型判断有用
mSceneAsset.Source = fileName;
mainMonoBehavior.UpdateEvent += OnUpdate;//添加监听函数
}
public void OnUpdate(GameObject dispatcher)//该函数是监听函数,每帧都会被调用(它的添加是在MainMonoBehavior的start函数中通过调用本地LoadSence函数)
{
if (mSceneAsset != null)//表示已经通过了new操作分配类内存空间但是资源还没有加载完
{
LoadAsset(mSceneAsset);//这个函数里面会通过判断,使www的new操作只执行一次
if (!mSceneAsset.isLoadFinished)//C#中 bool类型默认是false
{
return;
}
mScene = null;
mSceneAsset = null;
}
mainMonoBehavior.UpdateEvent -= OnUpdate;//当所有资源被加载后,删除监听函数。
}
//最核心的函数
private Asset LoadAsset(Asset asset)
{
string fullFileName =mResourcePath+"/"+ asset.Source;// mResourcePath + "/" + asset.Source;
Debug.Log("fullFileName=" + fullFileName);
//if www resource is new, set into www cache
if (!wwwCacheMap.ContainsKey(fullFileName))
{//自定义字典 查看开头的定义
if (asset.www == null)
{//表示www还没有new操作
asset.www = new WWW(fullFileName);
return null;
}
if (!asset.www.isDone)
{
return null;
}
wwwCacheMap.Add(fullFileName, asset.www); //该字典是作为缓存的作用,如果之前已经加载过同样的Unity3D格式文件,那么不需要在加载,直接拿来用就行了。
}
if (asset.Type == Asset.TYPE_JSON)
{ //Json 表示当txt文件被首次加载时的处理
if (mScene == null)
{
string jsonTxt = mSceneAsset.www.text;
Debug.Log("jsonTxt=" + jsonTxt);
mScene = JsonMapper.ToObject<Scene>(jsonTxt);//mScene是个Asset对象列表,也就是Json文件需要一个AssetList列表对象,注意名字的统一,列表中Asset对象中的成员名称要和txt //文件中的相关名称统一 不然JsonMapper无法找到
}
//load scene
foreach (Asset sceneAsset in mScene.AssetList)
{
if (sceneAsset.isLoadFinished)
{
continue;
}
else
{
LoadAsset(sceneAsset);//这里的处理就是 下面 Asset.TYPE_GAMEOBJECT的处理方式,注意是递归函数的调用
if (!sceneAsset.isLoadFinished)
{
return null;
}
}
}
}
else if (asset.Type == Asset.TYPE_GAMEOBJECT)//处理文件中具体信息,嵌套关系或者直接是一个GameObject对象,与上面的代码有联系,Asset创建时候的构造函数中设置成
//TYPE_GAMEOBJECT类型
{ //Gameobject
if (asset.gameObject == null)//如果不为null 表示已经通过wwwCacheMap加载了资源包中所包含的资源(fullFileName仅仅是一个文件,资源包中资源是分散的GameObject对象),不需要在重新加载
{
wwwCacheMap[fullFileName].assetBundle.LoadAll();//已经通过new WWW操作完成了加载,该函数用来加载包含着资源包中的资源
GameObject go = (GameObject)GameObject.Instantiate(wwwCacheMap[fullFileName].assetBundle.mainAsset);
UpdateGameObject(go, asset);
asset.gameObject = go;
}
if (asset.AssetList != null)//有嵌套关系
{
foreach (Asset assetChild in asset.AssetList)
{
if (assetChild.isLoadFinished)
{
continue;
}
else
{
Asset assetRet = LoadAsset(assetChild);
if (assetRet != null)//这个if else 语句是为了防止你的配置文件中的GameObject对象路径不正确,导致访问空指针。
{
assetRet.gameObject.transform.parent = asset.gameObject.transform;
}
else
{
return null;
}
}
}
}
}
asset.isLoadFinished = ***e;
return asset;
}
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;
}
}
Asset.cs类:
using UnityEngine;
using System.Collections.Generic;
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;
}
}
Scene.cs类:
using System.Collections.Generic;
public class Scene
{
public List<Asset> AssetList
{
get;
set;
}
}
生成.unity3d代码:
using UnityEngine;
using UnityEditor;
using System.IO;
using System;
using System.Text;
using System.Collections.Generic;
using LitJson;
public class BuildAssetBundlesFromDirectory
{
static List<JsonResource> config=new List<JsonResource>();
static Dictionary<string, List<JsonResource>> assetList=new Dictionary<string, List<JsonResource>>();
[@MenuItem("Asset/Build AssetBundles From Directory of Files")]//这里不知道为什么用"@",添加菜单
static void ExportAssetBundles ()
{//该函数表示通过上面的点击响应的函数
assetList.Clear();
string path = AssetDatabase.GetAssetPath(Selection.activeObject);//Selection表示你鼠标选择激活的对象
Debug.Log("Selected Folder: " + path);
if (path.Length != 0)
{
path = path.Replace("Assets/", "");//因为AssetDatabase.GetAssetPath得到的是型如Assets/文件夹名称,且看下面一句,所以才有这一句。
Debug.Log("Selected Folder: " + path);
string [] fileEntries = Directory.GetFiles(Application.dataPath+"/"+path);//因为Application.dataPath得到的是型如 "工程名称/Assets"
string[] div_line = new string[] { "Assets/" };
foreach(string fileName in fileEntries)
{
j++;
Debug.Log("fileName="+fileName);
string[] sTemp = fileName.Split(div_line, StringSplitOptions.RemoveEmptyEntries);
string filePath = sTemp[1];
Debug.Log(filePath);
filePath = "Assets/" + filePath;
Debug.Log(filePath);
string localPath = filePath;
UnityEngine.Object t = AssetDatabase.LoadMainAssetAtPath(localPath);
//Debug.Log(t.name);
if (t != null)
{
Debug.Log(t.name);
JsonResource jr=new JsonResource();
jr.Name=t.name;
jr.Source=path+"/"+t.name+".unity3d";
Debug.Log( t.name);
config.Add(jr);//实例化json对象
string bundlePath = Application.dataPath+"/../"+path;
if(!File.Exists(bundlePath))
{
Directory.CreateDirectory(bundlePath);//在Asset同级目录下相应文件夹
}
bundlePath+="/" + t.name + ".unity3d";
Debug.Log("Building bundle at: " + bundlePath);
BuildPipeline.BuildAssetBundle(t, null, bundlePath, BuildAssetBundleOptions.CompleteAssets);//在对应的文件夹下生成.unity3d文件
}
}
assetList.Add("AssetList",config);
for(int i=0;i<config.Count;i++)
{
Debug.Log(config.Source);
}
}
string data=JsonMapper.ToJson(assetList);//序列化数据
Debug.Log(data);
string jsonInfoFold=Application.dataPath+"/../Scenes";
if(!Directory.Exists(jsonInfoFold))
{
Directory.CreateDirectory(jsonInfoFold);//创建Scenes文件夹
}
string fileName1=jsonInfoFold+"/json.txt";
if(File.Exists(fileName1))
{
Debug.Log(fileName1 +"already exists");
return;
}
UnicodeEncoding uni=new UnicodeEncoding();
using( FileStream fs=File.Create(fileName1))//向创建的文件写入数据
{
fs.Write(uni.GetBytes(data),0,uni.GetByteCount(data));
fs.Close();
}
}
}
来自互联网
欢迎光临 纳金网 (http://rs.narkii.com/club/)
Powered by Discuz! X2.5