Unity3D(88)
中的Profile也是可以直接在链接安卓设备运行游戏下查看的,导出真机链接U3D的Profile看数据,这样能更好的测试具体原因。
大概看了下官方的做法,看了几张帖子顺带把做法记录下来。
用安卓真机调测Profile的数据,其实就两种方法,WIFI和ADB的方式。其实一般用的都是ADB方式,因为很少情况是你的电脑与手机是在同一子网WIFI下的。除非是你个人的网络。
1.以WIFI的方式。
这个方法需要电脑所在的网络和手机所在的网络在同一子网下才能进行。
(1)导出U3D项目的时候勾选Profile,***游戏到手机。
(2)打开游戏的时候,同时打开window-&profiler,然后选择选择输入IP,连上即可。
2.以ADB的方式。
注意防火墙是否屏蔽掉了端口,若屏蔽就打开。
(1)导出U3D项目的时候勾选Profile,***游戏到手机。
(2)打开CMD命令行,cd到adb根目录,然后输入以下命令。将下面&这里加你的包名&改为你游戏打包出来的名,即Bundle Identifier。例如:pany.aaa。
&&&&&adb forward tcp:54999 localabstract:Unity-这里加你的包名
(3)打开游戏的时候,同时打开window-&profiler,然后选择选择AndroidProfiler(ADB@127.0.0.1:54999),连上即可。
原文链接:.cn/s/blog_5b6cb9500101ehz0.html
-----------------------------------------------------
1. 通过adb devices命令获取所有online设备的serial number。
C:\Users\Administrator&adb devices
List of devices attached
emulator-5554 & device
SH0A6PL00243 & &device
上面表示,当前有两个设备online,第一个emulator-5554是模拟器,后一个是真机会SH0A6PL00243。
2. 通过adb -s &serial number& cmd向设备发送adb命令。
比如:运行命令shell。
C:\Users\Administrator&adb&-s SH0A6PL00243&shell
比如:down一个应用的数据库到本地f:\test目录下面。
C:\Users\Administrator&adb&-s SH0A6PL00243&pull
data/data/com.android.tencent/databases/AgendaDetails.db f:\test
555 KB/s (5120 bytes in 0.009s)
C:\Users\Administrator&
运行其它命令和运行pull命令一样的,只是在adb和cmd之间需要额外添加-s &serial number&即可。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:76804次
积分:1269
积分:1269
排名:千里之外
原创:14篇
转载:222篇
(2)(3)(3)(3)(3)(2)(3)(2)(1)(5)(2)(1)(2)(6)(15)(55)(1)(14)(11)(13)(7)(17)(10)(17)(12)(4)(19)(7)114网址导航1102人阅读
&&&& 之前做一个项目时,需要一个界面展示3D模型并进行交互。所以针对这个问题研究了很久,并总结了一些经验。在论坛中总遇到相同需求的人,也有很多人问我,所以写出这篇博客供大家参考。网上资料很少,即时有也比较模糊,所以接下来我尽量说的详细些,看完之后还有不懂得可以继续问我,QQ:.
&& 一、如果项目紧紧是展示3d模型,并进行简单的手势交互,这个时候,最好不要选择使用U3D和iOS混编,这个样做起来会比较麻烦,逻辑关系复杂,安全隐患严重。Opengl能很好的解决这个问题,iOS封装成GLView,用起来很简单实用(可以进行交互,缩放,旋转,增删,调整透视等)。附上Demo,弄懂里面的一些主要参数,变量,实现你要的效果不难。有参数不明白可以继续联系我,这个就不多说了,接下来讲解比较棘手的。
&& 二、项目要求3D效果比较绚丽,交互复杂,GLView已经不能满足我们的需求,这个时候我们可以考虑一下U3D和iOS混编。我把自己在这个过程中遇到的问题的感悟分享给大家。
&&&&&&&& 首先,Unity3d会导出一个工程文件,这个工程文件和我们的iOS项目结构很相似。拿到之后,用打开,并运行。如果遇到报错,
&&&&&&&& ld: warning: path '/Users/MAC/Desktop/ZiTest/Libraries/libiPhone-lib.a' following -L not a directory
&&&&&&&& ld: library not found for -liPhone-lib
&&&&&&&& clang: error: linker command failed with exit code 1 (use -v to see invocation)
&&&&&&& 不要紧张,虽然错很多,但只是一个问题。U3D导出的xcode工程文件不支持模拟器运行,换成真机运行,问题就没有了。如果真机感觉每次都是真机测试很麻烦,你可以让u3d导出一份可以模拟器运行的工程文件。
&&&&&&& 也有可能你会不能选择模拟器,找到TARGETS---Build Settings---& Supported Platforms&& 改成iOS。
& & && 解决混编的方法有很多种,总结起来就两大类,一个是u3d导入iOS,一个是iOS导入u3d中。这个可以看看我之前看的一些文章,试过好多,没有成功,大家可以参考下,即时不行,了解一下原理。版本不同,方法可能有些不同,但是原理是一样的。(目前自己找到资料仅仅只有这些,大家好好参考一下)
&&&&&&&&&&&&&&&&&&&&&&&&& .cn/s/blog_48a8afq.html
&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&& && 翻译:
&&&&&&&&&&&&&&&&&&&& & & 补充:
&&&&&&&&&&&&&&&&&&&& & & 其他参考:
&&&&&& u3d导入iOS中会比较麻烦一些,u3d产生的文件很大,setting的参数也要详细设置。
&&&&&& iOS导入u3d中相对简单,下面介绍这个方法。
&&&&&& 打开u3d导出的xcode工程文件,运行一下。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 文件是这个样子。
&& 运行的时候提示(报错200+个)
说明不支持模拟器运行,这个时候改用真机运行就可以了。最方便的办法就是让u3d导出可以真机运行的工程文件。
好了,能运行之后,拖入或者创建我们自己的ViewController。
打开Classes文件,找到UnityAppController(这个文件相当于我们认知的Appdelegate文件),找到这个方法,改变程序初始视图,由unityView改成我们自己的View。
改成这个样子:
- (void)applicationDidBecomeActive:(UIApplication*)application
&& &::printf(&-& applicationDidBecomeActive()\n&);
&&& static dispatch_once_t disO
&&& dispatch_once(&disOnce,& ^ {
&&& [self performSelector:@selector(startViewC:) withObject:application afterDelay:0];&& &
&&& NSLog(@&_window%@&,_window.rootViewController);
//&& &&& &[_snapshotView removeFromSuperview];
//&& &&& &_snapshotView =
&& &if(_unityAppReady)
&& &&& &if(UnityIsPaused())
&& &&& &&& &UnityPause(0);
&& &&& &&& &UnityWillResume();
&& &&& &UnitySetPlayerFocus(1);
&& &else if(!_startUnityScheduled)
//&& &&& &_startUnityScheduled =
//&& &&& &[self performSelector:@selector(startUnity:) withObject:application afterDelay:0];
&&&&& &&& &}
&& &_didResignActive =
-(void)startViewC:(UIApplication *)application{
&//我们自己需要进入的视图
&&& MyViewController *root = [[MyViewController alloc] init];
&&& _window.rootViewController =
&&& //[UnityGetMainWindow() makeKeyAndVisible];
现在程序启动之后,首先进入的就是我们的视图了,接下来就是怎么在我们的视图中进入到u3d界面视图。[self.UnityAC startUnity:[UIApplication sharedApplication]];方法只能调用一次,所以我们需要设置全局变量观察是第几次启动u3d界面。
//第一次启动
-(void)firstStarUnity{
&& [self.UnityAC startUnity:[UIApplication sharedApplication]];
//再次启动
-(void)againStarUnity{
&&& [self.UnityAC againStartUnity];
在UnityAppController里面实现再次启动打方法
//再次启动
-(void)againStartUnity{
&&& _window&& &&& &&& &= [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
&&& _window.rootViewController = _rootC
&&& _unityView&& &&& &= [self createUnityView];
&&& //[DisplayManager Initialize];
&&& _mainDisplay&& &= [DisplayManager Instance].mainD
&&& [_mainDisplay createWithWindow:_window andView:_unityView];
&&& [self createUI];
&&& [self preStartUnity];
&&& UnityPause(true);
&&& _didResignActive = YES;
&&& Profiler_UninitProfiler();
&&& NSLog(@&22222%@&,_window.rootViewController);
&&& [self showGameUI];
&&& [self createDisplayLink];
&&& [[[UnityGetMainWindow() rootViewController] view] setHidden:NO];
&&&&&&& if (_didResignActive) {
&&&&&&& UnityPause(false);
&&&&&&& _didResignActive = NO;
在UnityAppController---- (void)startUnity:(UIApplication*)application方法改成:
- (void)startUnity:(UIApplication*)application
&& &NSAssert(_unityAppReady == NO, @&[UnityAppController startUnity:] called after Unity has been initialized&);
&&& _window&& &&& &&& &= [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
&&& _unityView&& &&& &= [self createUnityView];
&&& //[DisplayManager Initialize];
&&& _mainDisplay&& &= [DisplayManager Instance].mainD
&&& [_mainDisplay createWithWindow:_window andView:_unityView];
&&& [self createUI];
&&& [self preStartUnity];
&& &UnityInitApplicationGraphics();
&& &// we make sure that first level gets correct display list and orientation
&& &[[DisplayManager Instance] updateDisplayListInUnity];
&& &UnityLoadApplication();
&& &Profiler_InitProfiler();
&& &[self showGameUI];
&& &[self createDisplayLink];
&& &UnitySetPlayerFocus(1);
现在我们就可从我们的界面进入u3d界面了,现在写在u3d退出后回到我们的界面中。
找到u3d预留的返回按钮的方法,在里面实现如何返回。在这里我没有用按钮,写在了UnityView.mm的touch的方法里。
在UnityAppController里实现:
//退出的方法
-(void)exitUnity{
&&& _window&& &&& &&& &= [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
&&& _unityView&& &&& &= [self createUnityView];
&&& //[DisplayManager Initialize];
&&& _mainDisplay&& &= [DisplayManager Instance].mainD
&&& [_mainDisplay createWithWindow:_window andView:_unityView];
&&& [self createUI];
&&& [self preStartUnity];
&&& UnityPause(true);
&&& _didResignActive = YES;
&&& Profiler_UninitProfiler();
&&& NSLog(@&1111%@&,_window.rootViewController);
&&& [[UnityGetMainWindow() rootViewController] view].hidden = YES;
//&&& _window&& &&& &&& &= [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
&&& self.myViewC = [[MyViewController alloc] init];
&&& _window.rootViewController = self.myViewC;
&&& NSLog(@&%@&,self.window);
&&& NSLog(@&33333%@&,_window.rootViewController);
&&& NSLog(@&%@&,self.myViewC);
&&& //[UnityGetMainWindow() makeKeyAndVisible];
好了,现在就可以都实现了。本人目前还不是很精通,但经过好几天日夜的研究,基本的已经没有问题。欢迎各位优化,并通知我QQ:,谢谢!
GLview Demo下载地址:http://download.csdn.net/detail/niuhailei/9463994。
iOS,u3d混编Demo下载地址:/cYX7fTFQXLeSc (提取码:ed6b)
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1306次
排名:千里之外U3D中的Profile也是可以直接在链接安卓设备运行游戏下查看的,导出真机链接U3D的Profile看数据,这样能更好的测试具体原因。
大概看了下官方的做法,看了几张帖子顺带把做法记录下来。
参考:/Documentation/Manual/Profiler.html
用安卓真机调测Profile的数据,其实就两种方法,WIFI和ADB的方式。其实一般用的都是ADB方式,因为很少情况是你的电脑与手机是在同一子网WIFI下的。除非是你个人的网络。
如果你需要导出的游戏在非导出的机子上PROFILE的话,最好在导出的机子随便先导个带PROFILE的空项目。这样才能很容易链接上,不然是很麻烦的事情。
1.以WIFI的方式。
这个方法需要电脑所在的网络和手机所在的网络在同一子网下才能进行。
(1)导出U3D项目的时候勾选Profile,***游戏到手机。
(2)打开游戏的时候,同时打开window-&profiler,然后选择选择输入IP,连上即可。
2.以ADB的方式。
注意防火墙是否屏蔽掉了端口,若屏蔽就打开。
(1)导出U3D项目的时候勾选Profile,***游戏到手机。
(2)打开CMD命令行,cd到adb根目录,然后输入以下命令。将下面"这里加你的包名"改为你游戏打包出来的名,即Bundle Identifier。例如:pany.aaa。
&&&&&adb forward tcp:54999 localabstract:Unity-这里加你的包名
(3)打开游戏的时候,同时打开window-&profiler,然后选择选择AndroidProfiler(ADB@127.0.0.1:54999),连上即可。
我们在使用Unity开发安卓游戏的时候,虽然可以很方便的在编辑器里直接启动查看运行效果,但是编辑器的环境始终比不上真机显示来的直接,而且有些操作,类似多点触控等等操作,必须要在手机端才能触发,如果我们不想一遍遍的编译apk***到手机上的话,Unity Remote会是一个很好的选择。
注意:Remote在手机上的运行结果并不能取代打包***之后运行的结果,他只是将编辑器的显示图像同步到了手机上,并通过手机接收输入而已。所以开发完成之后,还是要按照完整的流程进行测试。
1)使用Unity Remote的第一步是自己的机器上***Android SDK和你使用手机的驱动。SDK下载地址请自行baidu,手机驱动一般可以在对应品牌的官网找到。这里要注意,如果你的手机系统版本是4.1以上的,请将SDK中的adb升级至最新版本,目前最新版本为1.0.31,否则在adb连接手机的时候会出现设备始终offline的情况。
上面这些东西全部***完成之后,检测是否***正确的方法是通过SDK中adb程序来检测(在SDK目录platform-tools文件夹下),在控制台中进入到adb程序所在的目录后输入 adb devices 命令,如果看到设备正常连接,即所有准备工作***就绪。
注意:如果你的电脑上装有类似豌豆荚之类的PC端手机管理软件,请在任务管理器中将他们全部关闭,因为类似软件会劫持adb进程导致其无法正常工作。
2)关闭手机wifi(重要),打开手机的USB调试功能,在手机端***Unity Remote 并运行。
3)启动Unity并在编辑器中直接点击Play,不出以外的话你将会看到手机屏幕上也出现了相同的画面。
&&&&&&&&&&&& 华丽丽的分割线&&&&&&&&&&&&&&&&&&&&&&&&&&&&
上面我们介绍了不打包的情况下怎么在手机上看到运行结果,这毕竟不能代替真正的运行环境。有可能打包发布运行之后还会在手机上出现各种各样的问题,下面我们就将介绍如何在手机程序运行时查看Unity的日志文件。
其实,Unity在Android手机中运行时的所有日志可以通过Logcat捕获到,我们还是可以通过adb工具很方便的在pc上看到游戏运行时打出的Log信息。
1)首先第一步是在保证各种***环境都正常的情况下链接手机并运行游戏。
2)输入adb logcat -s Unity 即可看到游戏运行过程中通过Debug.log打出的所有日志信息。
目前貌似不支持断点调试,但可以通过日志打印(logcat)来跟踪。
&在android SDK中有个adb工具,使用此工具来跟踪运行的android应用:
adb&logcat&&
启动logcat,并将设备上运行的android应用的运行时信息全部打印出来。
adb&logcat&-s&Unity&&
如果只想打印Unity的输出信息,使用此命令。
adb&logcat&-d&&&logcat.txt&&
将打印信息输出为文件。
清除adb logcat缓存 &
adb&logcat&-c
当然,更直接的做法是在应用中集成自己的调试信息窗口,将如下代码关联到一个gameobject:
&p&using&UnityE&&
using&System.C&/p&&p&public&class&GuiTextDebug&:&MonoBehaviour&&&
&private&float&windowPosition&=&-440.0f;&&
&private&int&positionCheck&=&2;&&
&private&static&string&windowText&=&"";&&
&private&Vector2&scrollViewVector&=&Vector2.&&
&private&GUIStyle&debugBoxS&&
&private&float&leftSide&=&0.0f;&&
&private&float&debugWidth&=&420.0f;&&
&public&bool&debugIsOn&=&&&
&public&static&void&debug(string&newString)&&
&&windowText&=&newString&+&"\n"&+&windowT&&
&&UnityEngine.Debug.Log(newString);&&
&void&Start()&&&
&&debugBoxStyle&=&new&GUIStyle();&&
&&debugBoxStyle.alignment&=&TextAnchor.UpperL&&
&&leftSide&=&120;&&
&void&OnGUI()&&&
&&if&(debugIsOn)&&&
&&&&&&&&{&&
&&&GUI.depth&=&0;&&&&
&&&GUI.BeginGroup(new&Rect(windowPosition,&40.0f,&leftSide,&200.0f));&&
&&&scrollViewVector&=&GUI.BeginScrollView(new&Rect&(0,&0.0f,&debugWidth,&200.0f),&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&scrollViewVector,&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&new&Rect&(0.0f,&0.0f,&400.0f,&2000.0f));&&
&&&GUI.Box(new&Rect(0,&0.0f,&debugWidth&-&20.0f,&2000.0f),&windowText,&debugBoxStyle);&&
&&&GUI.EndScrollView();&&
&&&GUI.EndGroup&();&&
&&&if&(GUI.Button(new&Rect(leftSide,&0.0f,75.0f,40.0f),&"调试"))&&
&&&&&&&&&&&&{&&
&&&&if&(positionCheck&==&1)&&
&&&&&&&&&&&&&&&&{&&
&&&&&windowPosition&=&-440.0f;&&
&&&&&positionCheck&=&2;&&
&&&&else&&&
&&&&&&&&&&&&&&&&{&&
&&&&&windowPosition&=&leftS&&
&&&&&positionCheck&=&1;&&
&&&if&(GUI.Button(new&Rect(leftSide&+&80f,0.0f,75.0f,40.0f),"清除"))&&
&&&&&&&&&&&&{&&
&&&&windowText&=&"";&&
阅读(...) 评论()今天看啥 热点:
用UNITY开发手机游戏,背景图片和UI图片显示的比PC机上模糊很多,怎么解决??
在unity里选中资源&
1.TextureType 改成 Advanced
2.NonPower of 2 改成 non
3.把 generate Mip maps 的勾去掉
4.Format压缩格式 选中rgba32bit
5.保存下 apply&
/archives/1019 &在unity中播放视频 用到 moivetexture
删除多余内存垃圾
GC.Collect();卸载0代垃圾
GC.Collect(1);卸载1代垃圾
GC.Collect(2);卸载2代垃圾
Resources.UnloadUnusedAssets (卸载未使用的资源)
传个true作为参数貌似可以卸载所有的
Unity3d的Player setting中包括一个选项“Submit HW Statistics”,根据这个选项,Unity收集到了很多设备状态信息,并公开给大家形成参考资料。Mobile设备地址,1、iOS&http://t.cn/zRq6uXK&;2、Android&http://t.cn/zTqKwLr&;各位参考吧。
/mobile/index.html
/mobile/index-ios.html
Unity的C#脚本中GetComponentsInChildren&&()能够获取一个物体所有子物体的元素集合
Vector3的变量是Float,单精度浮点小数。
GameObject. AddComponent为新产生的物体添加一个脚本
发布Android应用时,PlayerSettings中必须更改Bundle Identifier
使用PlayerPrefs类提供的方法可以把当前游戏的数据保存到本地
想要在当前场景的基础上叠加加载一个新的场景,使用Application.LoadLevelAdditive();
如果是希望场景中某个对象不被释放:
DontDestroyOnLoad(GameObject.Find(&UI Root&));
Application.LoadLevel(&Home&);
在Edit→Preference中的General选项卡下勾选Always show Project Wizard可以使Unity在一台机器上启动多个程序实例
Camera.WorldToScreenPoint可以把物体的世界坐标转换成相机的屏幕坐标
需要添加到物体上的脚本必须继承自MonoBehavior
gameObject.transform内部机制相当于是find,一直觉得很扯蛋,不知道官方为什么要这么做,非要用户自己做一个引用变量,gameObject.transform这样不能是引用
面象对象的语言有自动垃圾销毁功能,但有的变量必须手动销毁,像某些情况下的数组里的元素,还有就是游戏对象,不用时也得手动销毁哦,制作游戏时敌人尽量保持一定的数量,达到动态平衡,而不是越来越多,最终导致死机。
u3d打包时 资源里面的它都打包 所以不必要的物件尽量删除 &
怎么去掉pc上开启游戏时候的
File - Build Settings -Pc and Mac Standalone -Player Settings -Resolution and Presentation -Display Resolution 选项改为 Dialog Disabled & & &
Edit-&Project setting-&player 下选中有windows标志的那个图标,在resolution and presentation下display resolution 为disable &
一些Unity的使用和优化心得(大部分内容摘自网络)&
下面由一个基础的问题引出全文(题目与解答由Jare师父提供):&
有两段代码,循环执行两个比较耗时的方法,假设语言和编译器相同,哪一段会比较快?&
for (int i = 0; i & 100; i++)&
&& &DoSomethingA();&
&& &DoSomethingB();&
for (int i = 0; i & 100; i++)&
&& &DoSomethingA();&
for (int i = 0; i & 100; i++)&
&& &DoSomethingB();&
相信有很多人一样,第一眼看起来认为第一段更快点。但实际上***是第二段快。原因如下:&
在这里性能的瓶颈不是循环本身。而是里面的方法。&
如果重复执行一个方法,那么CPU的寄存器、一级、二级缓存都很容易命中,比起到内存拿数据快多了。&
如果执行完一个执行另一个,那么缓存很可能就被替换掉了,只能到内存拿,甚至内存不够,要到硬盘上的虚拟内存拿。&
缓存组件查找(以下内容摘自网络)&
这种优化需要一些代码并且不是总有必要。但是如果你的代码真的很大,并且你需要尽可能的性能提升,它会是很好的优化。&
当你通过GetComponent获取一个组件或一个变量时,Unity必须从游戏物体里找到正确的组件。这时你便能通过一个缓存组件引用到一个私有变量。&
void Update () {&
&& &transform.Translate(new Vector3(0, 0, 5));&
private Transform myT&
void Awake () {&
&& &myTransform =&
void Update () {&
&& &myTransform.Translate(new Vector3(0, 0, 5));&
后面的代码运行较快,因为Unity不用在每一帧寻找变换组件。同样,支持脚本组件。你可以使用GetComponent获取组件或其他快捷属性。&
一个Mesh 建议使用的面数在 之间。&
一个 Mesh 建议只用一个 Material。&
注意:两个Mesh结合成一个Mesh,但是却使用两个Material,并不会提高效能。&
如果要提高效能必须把这两个Mesh的Material也合并成一个。&
换句话说,一个Mesh使用多个Material 和一个Material 使用多个render,其实耗能是差不多的。&
所以,尽可能的让物件共用相同的Texture 才是提升效能的根本之道。&
把物体设为static可以提高渲染效率,缺点是不能使用动态uv(可能还有别的缺点,不过没试过)&
&1. 尽量避免每帧处理&
function Update() { DoSomeThing(); }&
可改为每5帧处理一次:&
function Update() { if(Time.frameCount % 5 == 0) { DoSomeThing(); } }&
2. 定时重复处理用 InvokeRepeating 函数实现&
比如,启动0.5秒后每隔1秒执行一次 DoSomeThing 函数:&
function Start() { InvokeRepeating(&DoSomeThing&, 0.5, 1.0); }&
3. 优化 Update, FixedUpdate, LateUpdate 等每帧处理的函数&
函数里面的变量尽量在头部声明。&
function Update() { var pos: Vector3 = transform. }&
private var pos: Vector3; function Update(){ pos = transform. }&
4. 主动回收垃圾&
给某个 GameObject 绑上以下的代码:&
function Update() { if(Time.frameCount % 50 == 0) { System.GC.Collect(); } }
5. 运行时尽量减少 Tris 和 Draw Calls&
预览的时候,可点开 Stats,查看图形渲染的开销情况。特别注意 Tris 和 Draw Calls 这两个参数。&
一般来说,要做到:&
Tris 保持在 7.5k 以下&
Draw Calls 保持在 20 以下&
6. 压缩 Mesh&
导入 3D 模型之后,在不影响显示效果的前提下,最好打开 Mesh Compression。&
Off, Low, Medium, High 这几个选项,可酌情选取。&
7. 避免大量使用 Unity 自带的 Sphere 等内建 Mesh&
Unity 内建的 Mesh,多边形的数量比较大,如果物体不要求特别圆滑,可导入其他的简单3D模型代替。&
8. 优化数学计算&
比如,如果可以避免使用浮点型(float),尽量使用整形(int),尽量少用复杂的数学函数比如 Sin 和 Cos 等等。&
使用#pragma strict&
现在问题是,你通常不会意识到你在使用动态类型。#pragma strict可以解决这个问题!简单的添加#pragma strict在脚本顶部,之后Unity将禁用脚本的动态类型,强制你使用静态类型。如果有一个类型未知,Unity将报告编译错误。下面,foo将在编译时报错:&
#pragma strict&
function Start ()&
&& &var foo = GetComponent(MyScript);&
&& &foo.DoSomething();&
使用内置数组&
内置数组是非常快的。ArrayList或Array类很容易使用,你能轻易添加元件。但是他们有完全不同的速度。 内置数组有固定长度,并且大多时候你会事先知道最大长度然后填充它。内置数组最好的一点是他们直接嵌入结构数据类型在一个紧密的缓存里,而不需要任何额外类型信息或其他开销。因此,在缓存中遍历它是非常容易的,因为每个元素都是对齐的。&
privatevar positions : Vector3[];&
function Awake () {&
&& &positions = new &Vector3[100];&
&& &for (var i=0;i&100;i++)&
&& &positions = &Vector3.&
未选中物体变灰色:
改变物体shader中最后计算出来的rgb值即可,将其转换成lab,然后用(l,l,l)来代表其最终的rgb即可,对于选中的物体不需要进行处理,这样就会出现上述的视觉效果了&
代码如何控制是否使用lightmaps
unity是通过shader来加载lightmap的,你可以设置一个全局参数来控制是否需要lightmap进行最后的光照计算,然后通过白天还是夜晚控制这个全局参数即可。
billboard:
公告版.transform.LookAt(new Vecter3(Camera.main.transform.position.x,公告版.transform.position.y,Camera.main.transform.z))。这个方法hog在论坛里发过&
1、角色模型制作
unity3d支持Skin动画 &但是不支持Physique动画 &会发现Physique动画在unity里严重变形 &
因此在模型的骨骼动画的制作上面 &要用Skin &
当然也可以做成Physique &然后用插件转换一下 &3dsmax的插件PhyToSkin
3dsmax中转换之前 &为了避免出错 &先隐藏骨骼 & 然后对绑定了骨骼的模型进行单独转换 &因为批量也会出错
转换以后在修改面板中加入可编辑网格 &同时为了避免出错 &检查一下uv是否贴反了
2、角色模型导出
确保导出的模型是已经绑定了骨骼的 &在导出设置中根据需要选择是否导出Animation &
以及3dsmax和unity3d中的单位关系
& & &备注:max中导出戴有骨骼动画的mesh:
1 导出时需包含骨骼信息和mesh,mesh包含对应的skin影响器,physique不支持。
2 导出时在导出面板勾选导出动画,并设置要导出的动画时间长度
& & max中单位: &按1unit=1m制作,之后导出设置单位为M,这样缩放因子在1则为正确。fbx进入unity中后,模型要将缩放因子由0.01 改为1,则单位与max中 的单位以及真实世界的单位对齐了
3、官方CharacterCustomization中的模型
从官方换装demo中会发现他的一个角色模型里包含了要换装的多个模型 &比如有两个衣服模型、三个头发模型等
那我们在美术制作的过程中是不是也要这样进行“模型叠加”呢 & 其实没必要
demo这样的目的是为了使得模型公用一套骨骼 &那么我们在角色模型的制作过程中 &就确保模型使用的是同一套骨骼
比如男性角色使用一套 &女性角色使用另一套 &当进入创建角色场景后 &根据玩家选择角色的性别 &显示不同的动画即可
4、角色模型打包技巧
前面提到 &官方demo里换装的实现 &原因是因为公用了一套骨骼 &
那么我们在打包的时候 &就将骨骼和模型分离 &将模型各个部件(比如头发、手臂等)分开打包 &
比如一个男性的角色 &将他的基础骨骼打进一个包 & 再将身体各个部分的模型分别打包 &
如果一个模型由头、脸、身体、手臂、脚五个部分组成 &那么打包后将会有六个资源包 &分别是基础骨骼、头、脸、身体、手臂、脚
这样游戏的创建角色过程中 &就可以单独地对模型的身体部位进行切换
打包的过程和官方demo的打包大同小异 &只不过这里作者在打包时捎带生成了换装的配置表
6、角色模型的加载
unity3d中使用www进行资源的加载 &如果将资源放在了http服务器上的话(包括本机的IIS) &则需要一个crossdomain的xml配置 &本地则不需要
加载时应该首先去加载基础骨骼 &加载完以后再去加载要显示的默认角色模型 &比如新手模型
在加载完以后 &则要提取各个模型中所记录的骨骼信息 &根据这些信息将模型挂到对应的骨骼上
为了避免模型之间出现缝隙 &应当进行模型网格的合并 &
完成以上工作以后模型的加载就已经实现了
7、角色模型的换装
回到角色模型打包的话题 &
设想一个男性角色有10套服装用来更换 &而公用的骨骼是一套 &
因此在打包时仍然将这一套骨骼单独打包 &然后再将其他所有的模型打包 &
一句话总结就是 & 一套骨骼对应N个模型 &这N个模型都公用这一套骨骼
换装的实现实际上就是将相应的身体部分进行更换 &
比如要换一个手臂 &则将新的手臂与身体上除了手臂以外的模型再进行一次网格合并
换句话说 &要更换身体某一个部位 &实际上就是更新了整个角色模型
这里需要注意的一点是 &基础的骨骼不用再去更新 &
设想一下 &换装时候 &一般角色都会有个“站立”或者“呼吸”的动作在播放 &那么如果同时去更新了一遍基础骨骼 &那么结果势必会让本来连贯的动作有“一闪”的现象
这是因为 &之前的动画还没播放完 &然后就更新了骨骼 &那么动画又重头开始播 &这之间没有过渡 &肯定会有点问题
控制抗锯齿
设置Edit---ProjectSettings---Quality
我们主要使用3dsmax2010进行制作,输出FBX的类型导入Unity3D中。
默认情况下,3dsmax8可以和U3D软件直接融合,自动转换为FBX物体。
注意事项如下:
1.面数控制
在MAX软件中制作单一GameObject物体的面数不能超过65000个三角形,即32500个多边形Poly,如果超过这个数量的物体不会显示出来,这就需要我们合理分布多边形和模型数量。
打开MAX场景,选择File/Properties/SummaryInfo可以打开文件属性记录。
其中Faces可以看到每个物体的实际数量,个体数量不能超过65000个Faces面。
2.建模控制
Unity3D软件支持Line渲染和编辑之后所产生的模型。大部分模型都依靠Polygon进行制作。在模型表面可以承认多出四边形的面,但不渲染交错的面。
默认情况下,U3D引擎是不承认双面材质的,除非使用植物材质球Nature类型。
所以在制作窗户、护栏等物体,如果想在两面都能看到模型,那需要制作出厚度,或者复制两个面翻转其中一个的Normal法线。
3.文件的放置
模型可以继承MAX的材质,但是文件的设置要按照以下形式进行放
在项目的Assets文件夹内,新创建一个Object文件夹。
并在其中创建Materials和Texture文件夹(分别自动存放材质球和贴图)。
模型物体并列保存在Object文件夹内。
这个规律模式不要打乱,否则会破坏整个系统逻辑。
4.材质数量控制
如果一个物体给与一个材质球,那么Unity3D对于材质数量和贴图数量没有任何的限制。
如果一个物体给与多个材质球,我们需要用Multi/SubObject来实现,但是这种罗列的材质球的数量没有严格的控制,但尽量保持在10以内,过多的数量会导致一些错误。
如果不使用Multi/SubObject材质球,也可以选择一些面,然后给与一个材质球。这样系统会自动将其转换成Multi/SubObject材质。
综合而言Unity3D软件对于材质的兼容还是很好的。
5.物体的质感
Diffuse Bumped
Bumped Specular
这三种类型为常用类型,其中Bumped需要增加Normal法线贴图来实现凹凸。
这种材质为贴花材质,即相当于Mask类型,可以再Decal(RGBA)贴与一个带有Alpha通道的图像,形成和原图像相叠加的效果
Diffuse Detail
这种材质可以创造出污迹和划痕的效果,即相当于Blend混合材质。
Reflective
其中各种类型可以创造出金属反射效果,需要增加Cubmap贴图。
Transparent
其中各种类型可以创造出透明的效果,需要增加具有Alpha的通道贴图。
注意:如果要做玻璃贴图,Alpha如果全是灰色或黑色(即要求全透明),那么Alpha就会失效,如果要全透明,材质Alpha其中必须至少有1像素为白色。
其中SoftOcclusion Leaves类型主要应用于片状的树叶材质。
6.物体尺寸
默认情况下U3D系统单位1等于1米,等于软件1单位。如果我们制作是按照实际大小比例制作,那么导入U3D引擎会自动变成原来的1%的大小。
因为默认情况下,U3D的FBXImporter中的Scale Factor的数值为0.01。
那个我们可以将ScaleFactor的数值恢复为1,但是这样会占用模型资源,比较消耗物理缓存。
我们也可以将这个物体从Hierarchy中选择,并使用Scale放大100倍,这种设置可以有很多好处,并且还能通过用脚本制作动画。
7.关于复制
场景中的灯光布局,重复的模型物体都可以使用系统Prefab进行关联复制,这样可以改变一个参数的同时将所有关联物体属性改变。
8.山脉控制
在创建山脉之后,选择Terrain/Set Resolution可以设置山脉的大小和属性。
需要注意的是,默认情况下TerrainWidth和Terrain Height为1000米。如果设置这个数值太小,那么绘制草的时候会产生偏移,因为草的尺寸必须减少到0.1的单位。
也就是说,山脉在处理0.1单位的时候会产生0.01的偏差,如果模型太小,这种偏差是显而易见的,所以建议用户不要让模型过小。
9.光晕控制
光晕又称为Lens Flare即灯光光效。
可以选择一个GameObject物体给与Component/Rendering/LensFlare,并在Flare中增加一个StandardAssets/Light Flares/50mm Zoom项目。这样在运行之后就会产生光晕。
但有时候如果光晕太远太高却看不到。
一种办法是将光晕离近,另一种办法是将所有摄影机Camera的Far clip plane的数值增加。
10.摄影机控制
如果场景中有多架摄影机,那么如何确定第一打开时间所显示的摄影机,就需要设置Camera属性中的Depth数值,数值越大的摄影机越优先显示。
下面给你提供写方法以剥离减小包的大小,有些我也没试过:
降低的播放机大小主要有两个途径:一是更改Xcode内的Active Build Configuration,二是更改Unity的Stripping级别。
在发布模式下生成
你可以在 Xcode的Active Build Configuration下拉菜单中的调试和发布选项之间进行选择。根据自身游戏的大小,选择发布模式生成的player会比选择调试模式减少2-3MB的大小。
在发布模式下,player会去掉任何的调试信息进行生成,所以如果你的游戏崩溃或有其他问题,将是没有可用的、可输出的堆栈跟踪信息。这适合发布已完成的游戏,但你更应该在开发过程中使用调试模式。
iOS Stripping级别(Advanced License feature)
尺寸优化工作可通过以下几种方式被剥离机制激活:
Strip assemblies级别:通过分析脚本的字节码,来将这些脚本没有引用的类和方法从 Dll 中删除,从而使其不进入 AOT编译阶段。这种优化减少了主要的二进制以及相应 Dll的大小。在不使用反射的条件下,这种优化是安全的。
Strip ByteCode级别:任何.Net Dll(存储数据文件夹中)将从元数据中被剥离出来。这是可能的,因为所有的代码都已经 AOT阶段被预编译并链接到主要的二进制文件中
使用micro mscorlib级别:使用一种特殊的、较小的mscorlib版本。某些部件将从此库中被移除,例如,安全,Reflection.Emit,远程处理,非公历日历等组件都将被删除。此外,内部组件之间的相互依赖性也会被降至最低。该种优化减少了主要的二进制以及mscorlib.dll的大小,但不能与一些系统和 System.Xml程序集类兼容。因此,小心地使用它。
这些级别是累积的,第3级优化隐式地包含级别 2和级别1,而第 2级优化则包含级别1。
Micro mscorlib是核心库的最低级版本。只有这些项目是目前Unity中的Mono运行库所需要的。使用micro mscorlib的最佳做法是不使用任何你的应用程序所不需要的.Net的类或其他功能。GUID就是一个你可以忽略的例子,她可以轻松地被自定义的伪 Guid所替代,这样做将产生更好的性能和更小的应用程序。
如何处理使用反射机制的Strip
Strip程度取决于静态代码的分析,但有时侯,这种分析并不是很有效,特别是针对使用类似反射一样的动态功能的代码。在这种情况下,有必要给出一些提示来指出哪些类是不应该被触动的。Unity支持对于每个项目都给出一个自定义Strip黑名单。使用黑名单是创建 link.xml 文件并将它放入Assets文件夹的一个简单方法。以下是一个的 link.xml文件的示例。其中有保留标记的类将不会被Strip:
有时侯,我们很难确定哪些类会被进行错误的Strip。通常你可以通过在模拟器上运行已被Strip的应用程序和检查 Xcode 控制台的错误消息来获取有用的信息。
简单的清单,使你的发布版本尽可能地小
1.最小化你的资源(assets):启用 PVRTC压缩纹理,并尽可能低降低其分辨率。此外,尽量缩减无损压缩的音频的个数。这里还有一些额外的缩减文件大小的提示。
2.设置iOSStrip级别为Use micro mscorlib。
3.设置脚本调用优化级别为Fast but no exceptions。
4.不要让你的任何代码与System.dll或 System.Xml.dll有关联,因为这些库并不兼容micro mscorlib。
5.去掉不必要的代码关联。
6.将API兼容性级别设置为.Net 2.0子集。请注意.Net 2.0子集与其他库与兼容性比较有限。
7.设置目标平台为armv6 (OpenGL ES1.1)。
8.不要使用 JS阵列。
9.避免泛型容器与结构等类型相结合。
我能用Unity创造出低于 20 mb的应用程序吗?
当然可以。如果所有优化被都关掉,一个空项目在AppStore中大小大致为 13 MB左右。这在游戏中为你提供了大约7 MB的压缩资源预算。如果你拥有先进的许可证(并因此获得Strip选项),那么只含有主相机的空场景在AppStore中可压缩到大约 6 MB (zipped和 DRM连接),这样,你就可以有大约 14 MB可用空间用于压缩资源。
为什么我的应用程序发布到AppStore后大小增加了?
当他们发布你的应用程序时,苹果首先对二进制文件进行加密,然后将它通过 zip压缩。最常见的,苹果 DRM会使二进制文件大小增加大约 4 MB左右。作为一般规则,你应预见到的文件最终大小大致为所有文件(除了可执行文件)的 zip压缩大小,再加上未压缩的可执行文件的大小。
boxcollider或者其他任何collider 都是为物理碰撞或者碰撞检测做准备。
刚体属性组件,在任何物体下的Add component (添加零件、添加组件)可添加。
物体勾了tigger 那个属性,或者是地面勾了那个属性。tigger是能进入内部的,通常做判断触发范围
------------------------------------------
通常在变换场景后,上个场景中除了使用 DontDestroyOnLoad() 保留的物件,将会被释放掉,但如果在没有变换场景的情形下,想把未使用的资源卸载掉,该如何做呢?
一般情况下,我们会利用 Unity 的编辑器来部属每个关卡或场景中的物件,这些物件在载入场景后都是必要的,也不太会持续增加物件数,在关卡结束后即转换到下个场景,所以原本场景中的物件 将不再需要,所以 Unity 将会自动将前一场景的物件都销毁掉,所以我们通常不太需要去管理记忆体的使用或是否释放,但如果你的游戏全部是在单一个场景中运行的,那?物件的?生、销 毁、释放资源等等的动作就变得格外重要。
我做了一个宝石类型的游戏,画面上除了 GUI 及背景外就只有宝石,所以我事先将宝石做成 Prefabs ,在需要时利用 Instantiate() ?生,我在不同的关卡利用 renderer.material.mainTexture 变更背景图,利用 GetComponent(MeshFilter).sharedMesh 变更宝石的形状以及利用 renderer.material.color 变更宝石?色,如此一个Prefabs 可以重复无限使用,所以在游戏场景中只设置了简单几个场景物件,在这种场景不需要变化太多的情况下,每个关卡都换场景重新配置一样的物件似乎有点多?,所
以这个游戏便只有一个场景,在需要时?生宝石,然后再视情况使用 Destroy() 销毁掉,这样看起来只要在?生宝石时控制画面上的物件数量,那?也就不用担心记忆体使用过量或没释放掉的问题。
但是,这个游戏在连续玩好几个关卡后,也就是连续玩一段时间后,会发生停顿或画面变慢的问题,游戏刚开始玩时是相当顺畅的,但长时间执行将使效能降低,直 觉上的判断应该是记忆体累积到一定程度造成的,每个物件在不使用时都使用 Destroy() 销毁掉,那?,堆积的记忆体是从哪?来的呢?
打开 Profiler 视窗看看,会发现其中的 Memory 的 Total Object Count 数值,不断的增减变化,但随着时间的增加会慢慢的往上累积,查看官网 (/support/documentation/Manual/Profiler.html) 是这样说的 &If this number rises over time then it means your game is creating some objects that are never destroyed.&,有些物件未销?,很奇怪吧!都有使用
Destroy(),那?何还有未销毁的物件?其实,主要是因?我这?有对 renderer.material 设置改变其内容,在这个执行时期并不会真的去改变 Project 中的 material,而是?生这个物件实例(instance) 的材质实例以供该物件使用,所以如果只是 Destroy(gameObject) 的话,将会残留部份物件数,每个?生的物件都残留一点点的话,慢慢的长时间下来将会累积相当多,记忆体将会不敷使用,所以在 Destroy(gameObject) 的同时,应该也要 Destroy(renderer.material)
如果程式结构简单,给物件使用的 Script 档案也不多的话,也许多加一句并不困难,但我们有时候无法确定是否有在适当时机?每个物件做到完整的销毁,也许还有残留别的东西也会有这种情形持续累积记 忆体,这时又该寻找更简单统一的方法了,於是我们可以在每个关卡开始前或结束时执行一句 Resources.UnloadUnusedAssets() ,让 Unity 自行去卸载掉不使用的资源,如此在平时物件销毁时,我们已经先行释放掉大部份不使用的资源,然后再由 Resources.UnloadUnusedAssets()
卸载我们未清理掉的部份,如此的话查看 Profiler 视窗的 Memory 的 Total Object Count 数值就可以维持在一定范围内起伏,而不再随着时间增加,当然我们在关卡设置上都会有难度上的差异,在某些关卡?,玩家可能必须花较多时间才能完成关卡,所 以如果我们只在关卡开始或结束时使用 Resources.UnloadUnusedAssets() 也许会不够,此时也可另外定义每过一段时间就执行 Resources.UnloadUnusedAssets() ,如此将可避免掉系统资源不足的问题。&
.cn/s/blog_6af6af4b0100yy7n.html
在做项目过程中,经常会遇到一种情况:
场景中有不同种类的实例对象,这些实例可以是不同的3D物体。当我们需要点击其中一个物体(GameObject)时,希望他能够自动删除自己,并且将也要把对应的数组记录删除,保证数据统一。要实现以上所说的,需要建立一种自调用方法来实现。/unity3d-destroy-gameobject.html
相关搜索:
相关阅读:
相关频道:
Android教程最近更新