简述一下什么是unity asset 下载

常见面试题
这些面试是我之前总结的 ,认为还不错,就贴出来与大家分享一下。其中有不少问题,也是我曾经被面试官问过的问题,还有一些基础问题总结(既然是基础知识 ,必然是成为一名的 Android 开发人员 所必须掌握的 )。有多个问题,我都替你试过了,这样回答面试官,还可以啊,嘿嘿
这些面试是我之前总结的 ,认为还不错,就贴出来与大家分享一下。其中有不少问题,也是我曾经被面试官问过的问题,还有一些基础问题总结(既然是基础知识 ,必然是成为一名的
开发人员 所必须掌握的 )。有多个问题,我都替你试过了,这样回答面试官,还可以啊,嘿嘿
1、 Android中四大及其作用?
1、Activity:activity是用户和应用程序交互的窗口,一个activity相当于我们实际中的一个网页,当打开一个屏幕时,之前的那一个屏幕会被置为暂停状态,并且压入历史堆栈中,用户可以通过回退操作返回到以前打开过的屏幕。activity的生命周期:即“产生、运行、销毁”,但是这其中会调用许多方法onCreate(创建) 、onStart(激活)、onResume(恢复)、onPause(暂停)、onStop(停止)、onDestroy(销毁)、onRestart(重启)。
2、Service:Service是一种程序,它可以运行很长的时间,相当于后台的一个服务,通过startService(Intent service)可以启动一个Service,通过Context.bindService()可以绑定一个Service。
3、BroadCastRecevicer:接受一种或者多种Intent作触发事件,接受相关消息,做一些简单处理,转换成一条Notification,统一了Android的事件广播模型。可以使用BroadcastReceiver来让应用对外一个外部的事件作出响应。Broadcast Receiver通过NotificationManager来通知用户这些事情发生了,BroadcastReceiver注册的有两种方式,一种是可以在AndroidManifest.xml中注册,另一种可以在运行时的代码中使用Context.registerReceiver()进行注册。用户还可以通过Context.sendBroadcast()将他们自己的intent broadcasts广播给其他的应用程序。
4、Content provider:内容提供者,可通过它来共享自己的数据给外部调用,给第三方应用提供数据访问的接口。
2、ListView的优化方案?
1、如果自定义适配器,那么在getView方法中要考虑方法传进来的参数contentView是否为null,如果为null就创建contentView并返回,如果不为null则直接使用。在这个方法中尽可能少创建view。
2、给contentView设置tag(setTag()),传入一个viewHolder对象, 用于缓存要显示的数据,可以达到图像数据异步加载的效果。
3、如果listview需要显示的item很多,就要考虑分页加载。比如一共要 显示100条或者更多的时候,我们可以考虑先加载20条,等用户拉到列表 底部的时候再去加载接下来的20条。分页加载还没学习。
3、Android中五种数据存储方式分别是什么?他们的特点?
Android提供了五种存取数据的方式
(1)SharedPreference,存放较少的五种类型的数据,只能在同一个包内使
用,生成XML的格式存放在设备中
(2) SQLite,存放各种数据,是一个轻量级的嵌入式数据库
(3) File文件,通过读取写入方式生成文件存放数据
(4) ContentProvider,主要用于让其他应用程序使用保存的数据
(5)通过网络获取数据和写入数据到网络存储空间
4、列举Android中的主要五种常用布局?
最常用的布局有以下这几种:
第一种:帧布局(框架布局)FrameLayout
第二种:线性布局LinearLayout
第三种:绝对布局AbsoluteLayout
第四种:相对布局RelativeLayout
第五种:表格布局TableLayout
5、叙述学过的提供的Adapter?说明自定义Adapter与系统Adapter的区别?
采用ArrayAdapter、SimpleAdapter和SimpleCursorAdapter这些系统自带的适配器,对于事件的响应只能局限在一个行单位。 假设一行里面有一个按钮控件,它们之间的响应操作是不一样的。若采用系统自带的适配器,就不能精确到每个控件的响应事件。这时,我们一般采取自定义适配器来实现这个比较精确地请求。
6、Android中asset文件夹和raw文件夹区别?
res/raw和assets的相同点:
两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制。
res/raw和assets的不同点:
(1)res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源ID即 R.raw.filename;assets文件夹下的文件不会被映射到R.java中,访问的时候需要AssetManager类。
(2)res/raw不可以有目录结构,而assets则可以有目录结构,也就是assets目录下可以再建立文件夹
(3)读取文件资源举例:
读取res/raw下的文件资源,通过以下方式获取输入流来进行写操作
InputStream is = getResources().openRawResource(R.raw.filename);
读取assets下的文件资源,通过以下方式获取输入流来进行写操作
AssetManager am =
am = getAssets();
InputStream is = am.open(“filename”);
7、显式Intent和隐式Intent区别?
Intent是一种在不同组件之间传递的请求消息,是应用程序发出的请求和意图。对于明确指出了目标组件名称的Intent,我们称之为显式Intent。对于没有明确指出目标组件名称的Intent,则称之为隐式Intent。Android系统使用IntentFilter 来寻找与隐式Intent相关的对象。
显式Intent直接用组件的名称定义目标组件,这种方式很直接。但是由于开发人员往往并不清楚别的应用程序的组件名称,因此,显式Intent更多用于在应用程序内部传递消息。比如在某应用程序内,一个Activity启动一个Service。
隐式Intent恰恰相反,它不会用组件名称定义需要激活的目标组件,它更广泛地用于在不同应用程序之间传递消息。
8、简要描述AIDL的实现步骤?
服务器端:
1:服务器端写AIDL
2:服务器端继承Service,重写3个方法
3:服务器端实例化一个AIDL定义接口的Stub对象,并实现接口的抽象方法;
4:配置文件
1:拷贝AIDL文件
2:绑定与Service端的服务
3:实现ServiceConnection,在实现的过程中通过Service端传递过来的IBinder得到Stub对象;例如:接口名.Stub.asInterface(service);
4:通过Stub对象调用相应方法
9、 谈谈Service的生命周期,以及两种方式的区别?
*Service的生命周期由使用Service两种方式决定,启动方式不同生命周期不同。
(1)Start方式启动Service的生命周期:
onCreate()—onStartCommond()—onDestroy()
调用者和服务之间没有任何的联系,即使调用者退出,那么服务也仍然进行。
(2)Bind方式启动Service的生命周期:onCreate()-&onBind()-&&&onUnbind() -& onDestroy()
调用者和服务绑定在一起,调用者退出,服务即便退出。
10、 叙述学过的系统提供的Adapter(说明自定义Adapter与系统Adapter的区别)?
采用ArrayAdapter、SimpleAdapter和SimpleCursorAdapter这些系统自带的适配器,对于事件的响应只能局限在一个行单位。假设一行里面有一个按钮控件,它们之间的响应操作是不一样的。若采用系统自带的适配器,就不能精确到每个控件的响应事件。这时,我们一般采取自定义适配器来实现这个比较精确地请求。
11、写出ListView优化的代码,已知自定义ListView中自定义布局文件为list_item.xml里面有ImageView和TextView两个组件,其id为item_image、item_text。
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder viewH
if(convertView==null){
viewHolder=new ViewHolder();
convertView=LayoutInflater.from(c).inflate(R.layout.list_item, null);
viewHolder.text=(TextView) convertView.findViewById(R.id.item_text);
viewHolder.image=(ImageView) convertView.findViewById(R.id.item_image);
convertView.setTag(viewHolder);
viewHolder=(ViewHolder) convertView.getTag();
viewHolder.text.setText(list.get(position).getText());
viewHolder.image.setImageResource(list.get(position).getImage());
return convertV
static class ViewHolder{
12、 描述通过contentResolver获取ContentProvider内容的基本步骤 ?
第一:得到ContentResolver类对象
ContentResolver cr=getContentResolver();
第二:定义要查询的字段String数组
第三:使用cr.query();返回一个Cursor对象
第四:使用while循环得到Cursor里面的内容
13、 描述一下自定义ContentProvider的步骤。
自定义contentprovider步骤
1)继承Android的ContentProvider基类实现自己的ContentProvider类。
2)实现 ContentProvider里的onCreate方法,创建provider的数据,一般为数据库sqlite,那么我们在onCreate里实例化一个SqliteOpenHelper。
3)在ContentProvider 里面重写insert/delete/update/query增删改查这些方法。在每个方法里面实现相应的功能。
4)在AndroidManifest.xml文件中注册该ContentProvider类,为ContentProvider指定Uri。
14、 如何实现一个帧动画?
在布局文件中添加ImageView组件,设置background为res/anim/fram.xml动画效果
通过ImageView对象的getBackground()方法得到AnimationDrawable对象
通过AnimationDrawable对象的start()来启动帧动画,stop()来停止动画
15、 res/raw与assets目录的区别?
两者都会原封不动的保存在apk包中,不会被编译成二进制码。
1、raw目录下只能存放文件,不能存放下一级的文件夹,而assets可以存放下一级的文件夹。
2、raw目录下的资源会映射到R.java中生成资源id。而assets不会。
3、获得资源的方法不同。代码如下:
this.getAssets().open(“xml/channels.xml”)
this.getResources().openRawResource(R.raw.students)
this.getClassLoader().getResourceAsStream(“student.xml”)
16、 简述Handler机制原理?
*Andriod提供了 Handler 和 Looper 来满足线程间的通信。
Android不允许UI线程之外的线程改变UI组件的值,所以要想在其他线程里面改变UI组件的值,必须使用Handler来实现。
Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
Handler: 你可以构造Handler对象来与Looper沟通,以便push(上传)新消息到Message Queue里;或者接收Looper从Message Queue取出的消息。
Message Queue(消息队列,特点:先进先出):用来存放线程放入的消息。
线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。
Handler、Looper、MessageQueue的初始化流程如下所示。
Hander持有对UI主线程消息队列UI_MQ和消息循环Looper的引用,子线程可以通过Handler将消息发送到UI线程的消息队列UI_MQ中。
Handler处理消息
UI主线程通过Looper循环查询消息队列UI_MQ,当发现有消息存在时会将消息从消息队列中取出。首先分析消息,通过消息的参数判断该消息对应的Handler,然后将消息分发到指定的Handler进行处理。
17、在android中如何使用SqliteOpenHelper?
1、建立一个类继承SqliteOpenHelper,声明一个构造方法,参数包括(Context,name,CursorFactory,version);创建数据库
2、实现其oncreate() 创建表
3:通过onupgrade() 版本号更新时执行;
4、实例化所建类对象,对其进行读写操作,执行sql语句创建数据库(当对其使用读写时会判断数据库是否存在,如果存在,则不执行oncreate,不存在则执行)。
18、使用SqliteOpenHelper和SqliteDatabase进行增删改查具体的方法和参数?
1、通过SqliteOpenHelper得到SqliteDataBase的实例化对象(分为读写两种);
2、调用execSQL()执行增删改的SQL语句,传入SQL语句及需要填充的参数;
调用Cursor cursor = rawQuery()执行查询的语句
3、对执行SQL语句返回的游标,进行遍历;
4、及时关闭SqliteDataBase。
19、Sqlite和sharedPreference的区别
(1)Sqlite是嵌入式SQL数据库引擎SQLite(SQLite Embeddable SQL Database Engine)的一个扩展。SQLite是一个实现嵌入式SQL数据库引擎的 C语言库(C library)。用SQLite连接的程序可以使用SQL数据库,但不需要运行一个单独的关系型数据库管理系统进程(separate RDBMS process)。SQLite直接读写(reads and writes directly)在硬盘上的数据库文件。
(2)SharedPreferences也是一种轻型的数据存储方式,它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息。其存储位置在/data/data/&包名&/shared_prefs目录下。SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。
20、为什么要用ContentProvider?它与sql在实现上有何区别
Sql只能在该工程的内部共享数据,ContentProvider能在工程之间实现数据共享。
21、描述ContentProvider URI有哪几部分组成
URI由是部分组成:
content://com.example.transportation/trains/122
A,标准的前缀: ContentProvider(内容提供者)的scheme已经由Android所规定, scheme为:content://
B,唯一标识整个Content Provider: 主机名(或叫Authority)用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
C,描述了数据的路径,确定返回哪类数据: 路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定
D,ID唯一标注请求的数据: 我们要请求数据的ID
22、如何通过contentResolver扫描sdcard所有多媒体文件?
1) 通过ContentResolver访问系统多媒体提供的ContentProvider,得到多媒体音乐的cursor
2) 解析cursor,通过cursor得到对应文件列表
3) 设置listView,根据格式不同展示不同图片,进行使用
23、.描述一下开发ContentProvider的步骤
自定义contentprovider步骤
继承Android的ContentProvider基类实现自己的ContentProvider类。
实现 ContentProvider里的onCreate方法,创建provider的数据,一般为数据库sqlite,那么我们在onCreate里实例化一个SqliteOpenHelper。
在ContentProvider 里面重写insert/delete/update/query增删改查这些方法。在每个方法里面实现相应的功能。
在AndroidManifest.xml文件中注册该ContentProvider类,为ContentProvider指定Uri。
24、.Android中如何访问自定义ContentProvider?
1:得到ContentResolver类对象:ContentResolver cr = getContentResolver();
2:定义要查询的字段String数组。
3:使用cr.query(URI,字段数组,null, null,null);,返回一个Cursor对象。
4:使用while循环得到Cursor里面的内容。
25、 Android中五种数据存储方式分别是什么?他们的特点?
Android提供了五种存取数据的方式
(1)SharedPreference,存放较少的五种类型的数据,只能在同一个包内使用,生成XML的格式存放在设备中
(2) SQLite数据库,存放各种数据,是一个轻量级的嵌入式数据库
(3) File文件,通过读取写入方式生成文件存放数据
(4) ContentProvider,主要用于让其他应用程序使用保存的数据
(5)通过网络获取数据和写入数据到网络存储空间
26、 android中的动画有哪几类,它们的特点和区别是什么?
Android中动画可以分为两大类:帧动画、补间动画
1)补间动画:(你定义一个开始和结束,中间的部分由程序运算得到。就是对场景里的对象不断的进行图像变化来产生动画效果(旋转、平移、放缩和渐变))AlphaAnimation(渐变型动画)、scaleAnimation(缩放型动画)、 TranslateAnimation(平移型动画)、 RotateAnimation(旋转型动画)、
2)逐帧动画:Frame(把一连串的图片进行系列化连续播放,如同放电影的效果),它是通过播放一张一张图片来达到动画的效果;
27、、 补间动画的两种实现方式(四种可选择一种来举例)
1、XML配置:
1)在res/anim文件夹下配置动画对应标签,配置对应参数,包含初始值,动画结束值,以及动画时间
2)通过AnimationUtils.loadAnimation加载XML动画文件
3)调用startAnimation方法开启动画
2、代码实现:
1)直接New出需要的补间动画的对象,传递相应的参数
2)调用startAnimation方法开启动画
28、 如何用MediaPlayer实现音频播放功能,音乐播放器的开发需注意什么?
*用MediaPlayer实现音频播放功能主要有两种方法。
(方法一):在res下建立一个raw包,把文件放入包中。在activity中声明
一个MediaPlayer对象,然后onCreate()方法中用
MediaPlayer.create(context,R.raw.资源名)方法实例化该对象。然后调用
MediaPlayer的start()、pause()和stop()方法进行开始、暂停和停止的
操作。最后在activity的onDestroy()中调用MediaPlayer的release()
方法进行资源的释放。此方法的缺点是每次运行程序时都要加载raw里的资
源文件,使安装过程速度减慢。
(方法二):资源放在sdcard中。在activity中声明一个MediaPlayer对象,
实例化 MediaPlayer()。使用Environment.getExternalStorageDirectory().getAbsolutePath()方法获得path,然后path+=File.separator+资源名或”包名/资源名”。然后调用MediaPlayer的setDataSource(path)进行资源设置。然后先调用prepare()方法,在后再调用start()方法播放,调用pause()方法和stop()方法进行暂停和停止的操作。最后在activity的onDestroy()中用release()方法进行资源的释放。
注意事项,使用方法二时,设置完资源路径后要先调用prepare()方法,调
用start()、pause()、stop()方法前腰先进行一些判断,不然一次性调用
多次同样的方法容易出错。调用stop()后在调用start()方法时要先调用prepare()方法。
29、 Android中播放小的音乐文件soundpool如何使用?
SoundPlayer 播放音频的实现步骤:
1) new出一个实例 ; new SoundPool(4, AudioManager.STREAM_MUSIC, 100);第一个参数是允许有多少个声音流同时播放,第2个参数是声音类型,第三个参数是声音的品质;
2) loadId = soundPool.load(context, R.raw.himi_ogg, 1);
3) 使用实例调用play方法传入对应的音频文件id即可
30、 Android中视频播放的三种方式?
1、系统自带android视频播放(最简单的视频播放器)
1) new Intent,配置隐式意图
2) 通过Uri.parse获取指定文件Uri
3) 给Intent添加Uri及type
4) 启动Intent
2、VideoView android提供给我们的一个供我们进行视频播放的组件
VideoView 是android 系统提供的一个媒体播放显示和控制的控件。
若需要控制栏,需要加上MediaController
3、surfaceView+MediaPlayer
1) 构建surfaceView
2) 获取surfaceHolder,设置分辨率
3) 对surfaceHolder添加回调接口(SurfaceHolder.Callback ) surfaceHolder.addCallback(this);
4) 实现接口内部三个方法
(surfaceCreated ,surfaceChanged,surfaceDestroyed等),对Mediaplayer添加Display(控制管理器)
5) 对按钮添加点击事件
31、 Timer及AlertManager
Timer是在一个应用运行期间进行的定时操作,当应用退出则定时操作也同时被取消。
AlarmManager是系统级的定时器,主要用来对Activity,Service,BroadCastReciver三大组件进行定时的操作,当应用退出后这个定时操作仍然可以按时进行,并且通过使用可唤醒的参数可以达到在系统休眠状态下仍可以完成定时操作。
32、Android中拍照功能如何实现?
有两种方法实现拍照功能:
1、通过camera打开照相机进行拍照调用系统camera执行拍照:
1)、首先创建surfaceView
2)、得到surfaceView对应控制器,并添加surfaceView的回调事件(surfaceView创建以及销毁分别执行的操作,当surfaceView创建时,初始化camera,当surfaceView销毁时,释放camera的资源)
3)、设置分辨率
4)、设置不维护缓存
5) 点击调用camera的takePicture传入回调拍照的实例化PictureCallback对象
2、系统拍照:通过Intent启动,设置ACTION_IMAGE_CAPTURE,startActivity开启
33、ListView的优化方案?
1:判断contentView是否为null
2:使用viewHolder缓存数据,实现一步加载
3:分页加载:
1)如果自定义适配器,那么在getView方法中要考虑方法传进来的参数contentView是否为null,如果为null就创建contentView并返回,如果不为null则直接使用。在这个方法中尽可能少创建view。
2)给contentView设置tag(setTag()),传入一个viewHolder对象,用于缓存要显示的数据,可以达到数据异步加载的效果。
3)如果listview需要显示的item很多,就要考虑分页加载。比如一共要显示100条或者更多的时候,我们可以考虑先加载20条,等用户拉到列表底部的时候再去加载接下来的20条。分页加载还没学习。
34、 MVC设计模式在Android中的应用?
1.模型层(model):对数据库操作,对网络等操作都应在model中处理,对业务的计算等操作都应在该层。可以简单的理解为Android中的源文件
2.视图层(view):一般采用XML进行描述,使用的时候可以方便的引入,可以简单的理解为Android中Layout文件。 Android中也可以用+HTML 等方式作为view 层。
3.控制层(controller):控制model和view的协调工作。简单的理解为Android中manifest文件。AssetBundle中的一个坑-DeterministicAssetBundle与文件名
这两天,家中来了客人,暂时住公司几天,顺便加班做一些东西,记录一下做动态更新时遇到的AssetBundle的一个坑:
为了确保AssetBundle打出来的资源具有唯一性,做两方面考虑:
在做Assetbunlde包依赖时,必须这么选择(PushAssetDependencies,PopAssetDependencies)
在资源更新时,只有确保资源不会每次Build时都会产生不同的MD5值,才能确保资源的增量更新BuildPipeline.BuildAssetBundle&
在build的时候添加一个选项 |
BuildAssetBundleOptions.DeterministicAssetBundle&这样就能确保这份资源的唯一性。
遇到的问题:
DA目录下面的FA文件名为x.prefab,DB目录下面的FB文件名字也叫x.prefab。。在build
Asset包的时候在StreamingAssets目录下面建立了DA和DB目录。
打包的时候FA文件打成了x.assetbundle放在DA目录下面;&
FB达成了x.AssetBundle 放在DB目录下面,根据常理知识:在不同的文件系统下面的两个文件应该不会冲突的。
然而在用www加载的时候:
www 先加载 DA下面的 x.assetbundle,(没有问题)
www 再加载DB下面的x.assetbundle(提示:can't be loaded because another
asset bundle with the same files are already)
(多么的让人恼火啊,可能是我没有找到相关的文献,我翻了很多的文章也没有找到类似的问题和解决办法,如果有的话,也希望有人帮忙指一下~~)
解决办法:
如果不想破坏目录的结构也可保留但是要确保文件的唯一性,将DA下的x.assetbundle 更名为
da_x.DB下的x.assetbundle更名为:db_x.assetbundle
在执行的时候就不会有问题了。
(我尝试过,在build完之后
手动的把x文件改名,结果还是报错,这应该是build的时候在assetbundle文件里写入了文件名字的信息,就算手动改名文件内的名称也是不会改变的)
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。本篇讲解的是3D游戏的场景资源打包方式,首先简单的分析一下场景中所包含的资源的类型。
场景资源一般包含:地表模型(或者是Unity Terrain),非实例化物体(摄像机、空气墙、光源、各种逻辑物体之类的)、场景物体(花草树木、房子箱子之类的)。
因为场景物体大多是公用的,所以将场景物体都打成单独的包,将地表模型、非实例化物体打包到场景包中。
那么场景TestScene所对应的资源就包括:场景包TestScene.unity3d、场景资源配表TestSceneXML.xml。
打包场景单个物体的具体细节在前面的帖子中已有讲解,此处不再赘述,本帖主要分享场景本身的打包和场景资源的序列化。
(1)打包一个场景
打包当前场景的代码如下所示,使用BuildStreamedSceneAssetBundle和BuildPlayer函数都可以实现此功能。
public class PackScene
public static void Execute(UnityEditor.BuildTarget target)
string assetPath = SceneAssetProcesser.GetPlatformPath(target);
string exportPath = assetPath + "Scene/";
if (Directory.Exists(exportPath) == false)
Directory.CreateDirectory(exportPath);
string currentScene = EditorApplication.currentS
string currentSceneName = currentScene.Substring(currentScene.LastIndexOf('/') + 1, currentScene.LastIndexOf('.') - currentScene.LastIndexOf('/') - 1);
string fileName = exportPath + currentSceneName + ".unity3d";
BuildPipeline.BuildStreamedSceneAssetBundle(new string[1] { EditorApplication.currentScene }, fileName, target);
// 另外一种方式
// BuildPipeline.BuildPlayer(new string[1] { EditorApplication.currentScene }, fileName, target, BuildOptions.BuildAdditionalStreamedScenes);
将TestScene打包成TestScene.unity3d的包。
(2)序列化场景物体
对于一个场景物体,主要序列化其下列信息:
(1)Transform信息:位置、朝向、缩放
(2)Mesh信息:Shader名字
        主颜色Color
        光照贴图信息:是否为static对象(static的对象才有光照贴图属性)、LightmapIndex、LightmapTilingOffset
主体代码如下所示:
  public static void ExportXML(string savePath)
// 所有的动态加载的物体都挂在ActiveObjectRoot下面
GameObject parent = GameObject.Find("ActiveObjectRoot");
if (parent == null)
Debug.LogError("No ActiveObjectRoot Node!");
XmlDocument XmlDoc = new XmlDocument();
XmlElement XmlRoot = XmlDoc.CreateElement("Root");
XmlRoot.SetAttribute("level", EditorApplication.currentScene);
XmlDoc.AppendChild(XmlRoot);
foreach (Transform tranGroup in parent.transform)
XmlElement xmlGroupNode = XmlDoc.CreateElement("Group");
XmlRoot.AppendChild(xmlGroupNode);
CreateTransformNode(XmlDoc, xmlGroupNode, tranGroup);
foreach (Transform tranNode in tranGroup.transform)
XmlElement xmlNode = XmlDoc.CreateElement("Node");
xmlGroupNode.AppendChild(xmlNode);
CreateTransformNode(XmlDoc, xmlNode, tranNode);
CreateMeshNode(XmlDoc, xmlNode, tranNode);
string path = savePath + "Scene/";
if (Directory.Exists(path) == false)
Directory.CreateDirectory(path);
string levelPath = EditorApplication.currentS
string levelName = levelPath.Substring(levelPath.LastIndexOf('/') + 1, levelPath.LastIndexOf('.') - levelPath.LastIndexOf('/') - 1);
XmlDoc.Save(path + "Xml" + levelName + ".xml");
XmlDoc = null;
private static void CreateTransformNode(XmlDocument XmlDoc, XmlElement xmlNode, Transform tran)
if (XmlDoc == null || xmlNode == null || tran == null)
XmlElement xmlProp = XmlDoc.CreateElement("Transform");
xmlNode.AppendChild(xmlProp);
xmlNode.SetAttribute("name", tran.name);
xmlProp.SetAttribute("posX", tran.position.x.ToString());
xmlProp.SetAttribute("posY", tran.position.y.ToString());
xmlProp.SetAttribute("posZ", tran.position.z.ToString());
xmlProp.SetAttribute("rotX", tran.eulerAngles.x.ToString());
xmlProp.SetAttribute("rotY", tran.eulerAngles.y.ToString());
xmlProp.SetAttribute("rotZ", tran.eulerAngles.z.ToString());
xmlProp.SetAttribute("scaleX", tran.localScale.x.ToString());
xmlProp.SetAttribute("scaleY", tran.localScale.y.ToString());
xmlProp.SetAttribute("scaleZ", tran.localScale.z.ToString());
private static void CreateMeshNode(XmlDocument XmlDoc, XmlElement xmlNode, Transform tran)
if (XmlDoc == null || xmlNode == null || tran == null)
XmlElement xmlProp = XmlDoc.CreateElement("MeshRenderer");
xmlNode.AppendChild(xmlProp);
foreach (MeshRenderer mr in tran.gameObject.GetComponentsInChildren&MeshRenderer&(true))
if (mr.material != null)
XmlElement xmlMesh = XmlDoc.CreateElement("Mesh");
xmlProp.AppendChild(xmlMesh);
// 记录Mesh名字和Shader
xmlMesh.SetAttribute("Mesh", mr.name);
xmlMesh.SetAttribute("Shader", mr.material.shader.name);
// 记录主颜色
XmlElement xmlColor = XmlDoc.CreateElement("Color");
xmlMesh.AppendChild(xmlColor);
bool hasColor = mr.material.HasProperty("_Color");
xmlColor.SetAttribute("hasColor", hasColor.ToString());
if (hasColor)
xmlColor.SetAttribute("r", mr.material.color.r.ToString());
xmlColor.SetAttribute("g", mr.material.color.g.ToString());
xmlColor.SetAttribute("b", mr.material.color.b.ToString());
xmlColor.SetAttribute("a", mr.material.color.a.ToString());
// 光照贴图信息
XmlElement xmlLightmap = XmlDoc.CreateElement("Lightmap");
xmlMesh.AppendChild(xmlLightmap);
// 是否为static,static的对象才有lightmap信息
xmlLightmap.SetAttribute("IsStatic", mr.gameObject.isStatic.ToString());
xmlLightmap.SetAttribute("LightmapIndex", mr.lightmapIndex.ToString());
xmlLightmap.SetAttribute("OffsetX", mr.lightmapTilingOffset.x.ToString());
xmlLightmap.SetAttribute("OffsetY", mr.lightmapTilingOffset.y.ToString());
xmlLightmap.SetAttribute("OffsetZ", mr.lightmapTilingOffset.z.ToString());
xmlLightmap.SetAttribute("OffsetW", mr.lightmapTilingOffset.w.ToString());
生成的配表结构如下:
......&Node name="TestObject"&
&Transform posX="-25.13055" posY="12.99786" posZ="26.41202" rotX="0" rotY="180.6732" rotZ="0" scaleX="1.293338" scaleY="1.293338" scaleZ="1.293338" /&
&MeshRenderer&
&Mesh Mesh="TestMesh01" Shader="Diffuse"&
&Color hasColor="False" /&
&Lightmap IsStatic="True" LightmapIndex="3" OffsetX="0." OffsetY="0." OffsetZ="0." OffsetW="0.4391975" /&
&Mesh Mesh="TestMesh02" Shader="AlphaTest"&
&Color hasColor="True" r="0.5429823" g="0.8897059" b="0.6888453" a="1" /&
&Lightmap IsStatic="True" LightmapIndex="2" OffsetX="0.1435547" OffsetY="0.1435547" OffsetZ="0.3969002" OffsetW="-0." /&
&/MeshRenderer&
&/Node&......
&下一篇讲解根据上述配表生成场景的具体实现...
阅读(...) 评论()

我要回帖

更多关于 asset store下载路径 的文章

 

随机推荐