unity3d apk 资源提取游戏提取资源工具怎么用

Unity3D游戏开发者-大红花
此博客主要记录我在Unity3D游戏开发中的一些经验和我对Unity3D游戏开发的一些理解。
unity3D其实也有命令行参数,可能好多人并不知道。其实在unity游戏开发的时候命令行参数有时挺有用的,特别在做工具开发的时候。下面就是unity3d的一些命令行参数。-batchmode&&&在&批处理模式下运行Unity。应始终与其他命令行参数一起使用,因为它确保不会弹出窗口,无需任何人为的干预。当脚本代码在执行过程中发生异常,资源服务&器更新失败或其他操作失败时Unity将立即退出,并返回代码为1。请注意,在批处理模式下, Unity将向控制台发送输出版本最小的日志。当然,日志文件将包含完整的日志信息。-quit&&&其他命令执行完毕后将退出Unity编辑器。请注意,这可能会导致错误消息被隐藏(但他们将显示在Editor.log文件)-buildWindowsPlayer &pathname&&&&建立一个单独的Windows游戏(例如:-buildWindowsPlayer path/to/your/build.exe)-buildOSXPlayer &pathname&&&&建立Mac游戏(例如:-buildOSXPlayer path/to/your/build.app)-importPackage &pathname&&&&导入提供的package,不会显示导入对话框-createProject &pathname&&&&根据提供的路径建立一个空项目-projectPath &pathname&&&&打开指定路径的项目-logFile &pathname&&&&指定将要被写入编辑的log文件-assetServerUpdate &IP[:port] projectName username password [r&&revision&]&&&&可&通过ip端口强制更新资源服务器的项目。端口是可选的,如果不是的话可以假定一个标准端口(10733)。最好使用此命令配合- projectpath参数确保你在正确的项目里工作。如果没有提供项目名字是那么就是最后一个Unity打开的项目。如果没有选择项目的路径则由- projectpath自动创建。-exportPackage &exportAssetPath exportFileName&&&&根&据路径导出package。exportAssetPath是一个文件夹(相对Unity项目的根目录)为了导出Unity项目并且 exportFileName是package的名称。目前,此选项只能在同一个时间导出整个文件夹。这个命令通常需要使用- projectpath参数-nographics (Windows only)&&&当运行在批处理模式,不会初始化显卡设备。这使得它可以在你的机器上自动按工作流程运行,甚至它没有GPU。-executeMethod &ClassName.MethodName&&&&在 Unity启动的同时会执行静态方法,该项目是开放的并且是在可选资源服务器更新完成之后。这可以用来不断的整合,进行单元测试,制作模型,准备一些数据&等。如果你想通过命令行返回一个错误,你可以抛出一个异常,会引发代码为1的Unity关闭或其他引发EditorApplication.Exit非零&代码。使用executeMethod,你需要在编辑文件夹有一个脚本并且类里有一个静态函数。-batchmode&&&在&headless&模式下运行游戏。游戏将不显示任何内容,或接受用户输入。这对运行网络游戏的服务器有很大的作用的。-force-opengl (Windows only)&&&让游戏使用OpenGL进行渲染,即使有可用的Direct3D。通常情况是使用Direct3D,但如果是Direct3D 9.0c的不可用的话则会选用OpenGL。-single-instance (Windows only)&&&在同一时候只允许一个游戏实例运行。如果另一个实例已在运行,然后再次通过&-single-instance启动它的话会调节到现有的这个实例。-nolog (Windows only)&&&不产生输出日志。&通常output_log.txt被写在游戏输出目录下的*_Data文件夹中&,在debug.log中打印输出的地方。-force-d3d9-ref (Windows only)&&&使游戏运行在Direct3D的&Reference&软件渲染模式,必须要安装DirectX SDK才能使其工作。这主要是用于建立自动化测试对象,这样您可以确保不管是使用什么显卡,其渲染效果是完全一样的。-adapter N (Windows only)&&&允许游戏全屏运行在另一台显示器上,其中N表示显示的号码。-popupwindow (Windows only)&&&这个窗口将以弹出的方式创建(没有框架)这么多命令行可以根据实际情况来使用,我自己是在写打包工具的时候使用的。欢迎大家加入Unity技术交流群:3112035
&&&&&&&&&&&&&&&&&&&&&&&&————大红花
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
有人可能要问游戏开发和批处理命令行发邮件有什么关系。那我要告诉你们,还真没有什么关系。其实我用这个功能主要用在一键打包的基础功能上,打包后自动发送APK到相关测试人员的邮箱中,以便测试员测试。我大概找了2种命令行工具blat、sendEmail并且都已经测试成功了。下面我就介绍blat工具。
1、在网上下载最新办的blat命令行工具,直接解压。2、在blat.exe同级目录新建一个SendEmail.bat的文本文件,addressee.txt用于填写收件人地址(一行一个地址),body.txt用于填写邮件的内容。3、SendEmail.bat的代码如下
set pass=xxxxx
set to=addressee.txt
set subj=&测试&
set mail=body.txt
set server=
set debug=-log blat.log -timestamp&-debug
:::::::::::::::::&运行blat&:::::::::::::::::
echo Sending Attach:%attach%
blat %mail%&-tf&%to%&-base64&-charset Gb2312 -subject&%subj%&-attach&%attach%&&-server&%server%&-port 25 -try 1 -f&%from%&-u&%user%&-pw&%pass%&%debug%
其中要注意的是:163的附件大小不能超过50M,超过就会被服务器拒绝,所以想发大文件就要用rar命令行压缩工具把文件分卷压缩然后再发邮件。登录密码是163后台账户设置里面获取的第三方邮件软件登录的一个授权码,并不是你的邮箱登录密码。还有就是在发邮件的时候不要乱发,我就是发多了账户被限制了。其他的命令就查他们的文档吧或者命令行blat都会显示。
欢迎大家加入Unity技术交流群:3112035 &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&————&大红花
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
在unity通过AssetBunld和Resource方式加载的基础图片其实都是Texture2D对象,但是在unity加入Sprite类型后,应该可以发现Sprite和Texture2D完全是两个不同的东西,并没有相关性。但是我们可能需要有这样个需求就是我们需要把我们加载到的Texture2D资源转化成Sprite类型后赋值给SpriteRenderer的sprite来显示我们的图片。那么怎么做呢?
由于Texture2D和Sprite没有相关性,所以unity给我们提供了一个由Texture2D来创建Sprite对象的接口Sprite.Create,这个接口重载了好几个方法,最常用的应该是public static Sprite Create(Texture2D texture, Rect rect, Vector2 pivot);
SpriteRenderer iconSpriteRenderer = prefab.GetComponentsInChildren&SpriteRenderer&(true)[0];
&&&&&&&&&&&&&&&&&&& Texture2D icon =&(Texture2D)
&&&&&&&&&&&&&&&&&&& Sprite iconSprite = Sprite.Create(icon, new Rect(0, 0, icon.width, icon.height), Vector2.one / 2.0f);
&&&&&&&&&&&&&&&&&&& iconSpriteRenderer.sprite = iconS
注意:Vector2 pivot这个参数,这个是中心点的意思。基本值是(0,0)&(0.5,0.5)(1,1)(0,1)(1,0)(1,-1)(-1,1)(-1,-1)……
代表了图片的中心点的对齐方式。跟NGUI和UGUI的对齐方式一样。
欢迎大家加入Unity技术交流群:3112035 &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&————&大红花
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
在国内大部分使用Android开发的人都会有升级Android SDK的需求,但是在国内升级是很困难的一件事情。
所以在这里记录一下一个比较靠谱的办法和镜像网站。
1、打开SDK Manager ——& Tools——&Options
在HTTP Proxy Server里面填入国内镜像网址:mirrors.
在HTTP Proxy Port里面填入端口号:80
2、勾选Fore https://... sources to be fetched using
完成上述步骤后即可通过国内的镜像网站来更新下载SDK了&速度还不错,如果上述的镜像网站关闭了,那就去找其他的吧。
欢迎大家加入Unity技术交流群:3112035 &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&————&大红花
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
在项目开发过程中,需要团队协作,一般我们通过SVN来进行版本控制和代码托管。
那么如果自己有私人项目或者代码怎么做好呢?
当然我们可以在自己家里面的电脑搭建成SVN服务器,但是如果电脑重装系统怎么办呢!
其实我想说另一种途径就是利用osChina(http://git.oschina.net)的代码托管功能,跟SVN很相似。
其实github也是可以的,但是github只能建公开的代码托管,不能建私人的,而osChina则允许建私人的代码托管,别人看不见自己的代码或者项目。
需要与osChina中建的项目链接需要下载2个东西:msysgit,TortoiseGit新手直接默认安装即可。安装完成后需要设置与osChina的项目链接。
具体的设置步骤:http://www.jb51.net/article/55440.htm
最后说一下就是:在提交更改文件的时候其实是提交到本地的版本控制中,在提交完成后需要手动“推送”更新的资源,这样才能在网页端看见上传的文件。
欢迎大家加入Unity技术交流群:3112035 &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&————&大红花
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
前段时间在开源站上找了一个开源vpn,然后下下来改了改,加了自己需要的功能,然后可以自由自在的翻墙Google了。
在修改好程序后,我用vs发布始终发布不出来,原来是作者使用了密匙证书的,其他人无权发布,所以我只能找另一个方法了,第一呢,我总不能用debug版吧,每次考的文件太多了。第二呢想了想发布出来还要安装也是麻烦的不行。所以干脆把dll合并到一个exe里面,运行的时候直接用一个exe文件就OK了。
然后在网上找了一些资料,找到一个合并工具叫ILMerge,这个是微软官方出的一个dll合并exe的一个工具。其他的杂七杂八的也不说了吧。直接说说我的使用方法。
1、首先把自己的程序的Release版本中的exe、dll文件拷贝到同一个目录中。
2、然后通过ILMerge对这些文件进行打包。
下载安装好ILMerge后,打开cmd窗口,把命令路径指向ILMerge安装文件夹。如:C:\Program Files (x86)\Microsoft\ILMerge
然后输入打包命令:
C:\Program Files (x86)\Microsoft\ILMerge&ilmerge&/ndebug&/target:winexe&/targetplatform:v4&/out:C:\Users\Administrator\Desktop\a\ShadowsocksNew.exe C:\Users\Administrator\Desktop\a\Shadowsocks.exe C:\Users\Administrator\Desktop\a\HtmlAgilityPack.dll C:\Users\Administrator\Desktop\a\Microsoft.Threading.Tasks.dll C:\Users\Administrator\Desktop\a\Microsoft.Threading.Tasks.Extensions.Desktop.dll C:\Users\Administrator\Desktop\a\Microsoft.Threading.Tasks.Extensions.dll C:\Users\Administrator\Desktop\a\Newtonsoft.Json.dll C:\Users\Administrator\Desktop\a\System.IO.dll C:\Users\Administrator\Desktop\a\System.Net.Http.dll C:\Users\Administrator\Desktop\a\System.Runtime.dll C:\Users\Administrator\Desktop\a\System.Threading.Tasks.dll C:\Users\Administrator\Desktop\a\Bmob-Windows.dll /allowDup
这个打包命令主要包含2个部分:
1、ILMerge 基本的打包命令包括打包类型&平台&输出路径
2、要打包的exe,还有dll
注意:在打包过程中你可能会遇到各种各样的问题,找ILMerge命令研究一下吧。还有在打包过程中遇到存在冲突类需要&/allowDup命令。
欢迎大家加入Unity技术交流群:3112035 &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&————&大红花
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
在unity项目开发中,为了团队协作开发,我们经常会用到版本管理工具SVN。但是有的时候我们通过SVN本身的命令操作有点步骤复杂化,为了简便的使用SVN的命令功能我们可以写成批处理命令来使用SVN的功能。
例如较常用的命令:上传、更新
新建批处理文件的步骤如下:
1、新建一个text文档然后把后缀名改为.bat
2、参照下面代码编写自己的SVN执行命令
代码事例:
@echo /*************************
@echo&回车更新全部
@echo 0、update Bin &&&&&&& 00:commit Bin
@echo 1、update Scr &&&&&&& 11:commit Scr
@echo 2、update CeHua &&&&&&
@echo&*************************/
@set/p option=输入:
if &%option%&==&& goto UPDATE_ALL
if &%option%&==&0& goto UPDATE_BIN
if&&%option%&==&1& goto UPDATE_SRC
if &%option%&==&2& goto UPDATE_CEHUA
if &%option%&==&00& goto COMMIT_BIN
if&&%option%&==&11& goto COMMIT_SRC
:UPDATE_BIN
&C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe&&/command:update /path:&E:\CDHUnityWorkSpace\DefanseWork\Bin&&/closeonend:0
:UPDATE_SRC
&C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe&&/command:update /path:&E:\CDHUnityWorkSpace\DefanseWork\Src&&/closeonend:0
:UPDATE_CEHUA
&C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe&&/command:update /path:&E:\CDHUnityWorkSpace\DefanseWork\CeHua&&/closeonend:0
:UPDATE_ALL
&C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe&&/command:update /path:&E:\CDHUnityWorkSpace\DefanseWork\Bin*E:\CDHUnityWorkSpace\DefanseWork\Src*E:\CDHUnityWorkSpace\DefanseWork\CeHua&&/closeonend:0
:COMMIT_BIN
&C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe&&/command:commit /path:&E:\CDHUnityWorkSpace\DefanseWork\Bin&&/closeonend:0
:COMMIT_SRC
&C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe&&/command:commit /path:&E:\CDHUnityWorkSpace\DefanseWork\Src&&/closeonend:0
注:如果想同时更新或上传多个路径的资源,可以通过&*&号把多个路径连接成一个路径,这样SVN只会打开一个命令面板,反之则会打开多个。
欢迎大家加入Unity技术交流群:3112035 &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&————&大红花
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
在用unity开发2D游戏的时候,我们避免不了的会使用精灵动画。
在unity中现在比较热门并且比较好用的UI插件应该是NGUI了,但是在NGUI中有一个遗憾就是精灵动画支持的不好,只有一个很简单的精灵动画组件。可能很简单的精灵动画没有什么问题,但是稍微复杂一点的精灵动画就显得力不从心了。
在以前的2D开发过程中,我使用过一个叫做ex2D的插件,这个插件有自己的图集、精灵方式,和NGUI是2种不一样的方式,但是他对精灵动画支持的十分的强大,可以说他的精髓就在精灵动画的支持并且他提供了精灵动画编辑器也十分的强大,所有的步骤都能够可视化的操作完成。他还支持帧事件,就是在某一帧插入一个事件,当动画执行到这一帧的时候就会执行相应的事件。但是ex2D不像NGUI那样开源,所以内部的代码我们无从知道。
ex2D是国人自己开发的插件,他的动画播放方式跟Unity3点几的动画系统类似,我感觉真的很不错,因为最近2年我在开发3D游戏,所以对他关注也是十分的少,只知道他们在开发2.0版本的,前一段时间我找了一下开发这个插件的开发者才知道他们不再更新这个插件并且把他开源了。当时我就在想是不是把这套动画系统移植到NGUI当中去。
NGUI是我看着成长起来的,最开始我用的时候还在1点几的版本吧,现在都快到4.0版本了。现在的NGUI成熟了很多了,用起来比以前也好多了。但是唯一遗憾的是他对精灵动画的支持一直都没变过,还是那样的简单。
真不好意思,听我啰唆了那么多,接下来我会把这套移植的动画系统分享出来并介绍一下怎么使用。
---------------------------正文开始-------------------
首先我介绍了一下我在移植过程中对ex2D做了哪些改动。
接下来讲解一下移植后的ex2D动画系统怎么使用。
ex2D和NGUI的图集、精灵渲染、结构都完全不一样,所以在移植之前必须先搞懂这2个插件的工作方式和原理,最主要的需要了解清楚图集和精灵的数据存储方式和工作方式还有编辑方式。
ex2D中的图集方式是分别把精灵信息存储在单个的asset文件中,而NGUI则是把图集精灵信息通过序列化特性直接存储在预置上面的,所以在NGUI中找不到精灵信息存储文件,但是NGUI是支持text格式的精灵信息存储文件方式的。
所以鉴于他们的区别我改造了ex2D的编辑器功能、精灵渲染和动画存储结构,并支持同一个AnimationClip中的不同精灵可以在不同的图集中。全部改为支持NGUI的方式,在这个过程中并没有改过NGUI的代码。所以如果需要使用这个扩展,只需要先导入NGUI包,再导入我提供的ex2D扩展包就OK了。
----------------------------------------分割线---------------------------------
@ex2D Animation System To NGUI
下面我来讲解一下这个动画系统的使用方法。
1、先导入NGUI包,再导入ex2D Animation System To NGUI扩展包
2、通过NGUI的图集方式把序列帧制作成图集。
3、在project视图中创建一个动画剪辑 exSpriteAnimationClip,并对这个动画剪辑进行编辑,添加精灵和帧事件。
4、创建一个exSpriteAnimation动画对象,然后把需要用到的动画剪辑添加到这个动画对象上面,通过对这个动画对象的控制来控制不同的动画剪辑。
-----------------------------
第一步:(略过)
第二步:NGUI制作图集我就不用多说了,我展示一下我制作的图集。
第三步:在project视图中创建一个动画剪辑 exSpriteAnimationClip,并对这个动画剪辑进行编辑,添加精灵和帧事件。
1、在project视图中点击Create选择exSpriteAnimationClip添加一个动画剪辑,然后选中动画剪辑在检视面板中点Edit
2.点击Edit后会出现一个动画剪辑的编辑窗口。如下图
3.然后找到事先做好的NGUI的图集预制体,往时间线视图中拖就会出现一个精灵的选择窗口。在精灵选择窗口中点击精灵就会自动的加入到动画剪辑当中,再次点击已经选中的精灵就会从动画剪辑中删除。
4.选择精灵后,你能看到编辑窗口的FramInfo List选项卡中可以看到多个精灵关键帧,每个关键帧都有一个Atlas和Sprite,你可以通过这个单独设置这个关键帧的图集和精灵。如图
5.如果你要删除某一个关键帧的话只需要在时间线预览窗口中选中某一个精灵然后按退格键或者Delete键就能把选中的精灵删除。或者在FrameInfo List 中找到此关键帧点击前面的“-”按钮就能删除。选中某一个精灵的时候FrameInfo List中关键帧的颜色会发生相应的改变。如图
6.如果你要调换某2个精灵关键帧的位置的话,先选中需要调换的一个精灵然后拖动这个精灵的位置即可。如图
7.当你选中某一个精灵后,点击拉动出现的红色矩形边框的时候就能改变这个关键帧的帧数,同时发现此帧在时间线中的视图宽度已经变宽。如图
8.然后你可以设置这个动画剪辑的一些参数
speed:播放速度
weap Mode:播放方式
Stop Action:播放停止后的操作
&&&&注:defaultsprite是停止播放后直接变为默认精灵。其他的很好理解
FrameRate:帧率
9.添加帧事件。在时间线上选择要加入事件的时间点,再点击添加事件按钮,即可加上一个帧事件,然后在EventInfo List选项卡里面能够看到所添加的事件,并且能够对所添加的事件进行设置。如图
10.点击开始预览按钮,在动画预览试图区就能看到整个动画的运行情况了。如图
OK那么我们就制作好了我们的一个动画剪辑,接下来我们就要创建动画对象对我们的动画剪辑进行控制播放了。
1.在菜单栏点击NGUI-&Creat-&exSprite Animation创建一个动画对象,然后你在检视面板中可以看到这个对象上面有UISprite 和 exSpriteAnimation 两个组件。如图
2.把我们第二步中创建的动画剪辑拖到动画对象的Animations列表中。如图
3.设置一个默认的动画剪辑或者不设置也可以。设置了默认动画剪辑并勾选PlayAutomatically就能在激活这个动画对象的时候自动播放默认动画剪辑,当然前提是默认动画剪辑必须在Animations列表中。如图
4.在UIsprite 组件中设置一张默认的精灵。如图
5.最后就可以编写代码并获取到exSpriteAnimation对象对设置的动画剪辑进行播放操作了。
使用方法就是上面所述的了。
下面是扩展包(里面带了示例),可以下载来学习。
/02e705afd70c16e792d8ab
希望大家有什么好的想法或者不错的功能需求也可以给我说,我也可以更好的完善这套动画系统。
现在这个动画系统有一个缺陷就是不能使用unity的动画状态机,如果我们也有一套自己的状态机系统是不是特别棒呢。如果要使用unity的动画状态机我们只能提取他的状态机信息然后组装成我们自己的状态机或者呢多花点时间自己写一套状态机。这个等我有时间的时候在弄吧,毕竟现在比较忙。
大家有什么不懂或者有什么好的想法再或者bug什么的可以反馈给我,加这个交流群:3112035
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&——&&大红花
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
在Unity开发过程中,可能很多同学会遇到获取IOS设备唯一码的需求,一般网上有openudid、广告标示符等。但是如果不把获取到的唯一码放入keychain的话,当玩家删除APP后唯一码会改变,所以只要在不还原设备的情况下,保存到keychain中的唯一码是不会改变的。下面提供一个object-c代码工具类,有需要的朋友可以看看。
1、首先创建SvUDIDTools.h、SvUDIDTools.m两个文件,代码如下。当创建好了上述的两个文件后最重要的一步就是配置keychain,下面就是在Unity导出的Xcode工程中配置keychain。
2、在Class文件夹下创建一个KeychainAccessGroups.plist文件
3、对KeychainAccessGroups.plist文件进行配置,如图:红色划线的地方换成你自己的值,格式是:(.XX.XX)&&注:teamID在你发布账号中能够查看到,必须用你的发布账号的teamID.
4、把SvUDIDTools.m中static const char kKeyChainUDIDAccessGroup[]&=&&.XX.XX&;中的&.XX.XX&换成你自己的值就OK了。如图
5、然后在Code Signing中配置keychain的plist。如图
6、当配置好了以后就可以写一个object-c接口提供给Unity调用,然后就可以在Unity里面获取到一个唯一码了。如何写接口提供给Unity请看我相关的博客。
欢迎大家加入Unity技术交流群:3112035 &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&————&大红花&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
SvUDIDTools.h文件代码
#import &Foundation/Foundation.h&
@interface SvUDIDTools : NSObject
+&(NSString*)UDID;
SvUDIDTools.m文件代码
#import &SvUDIDTools.h&
#import&&Security/Security.h&
#include&&sys/socket.h&
#include&&sys/sysctl.h&
#include&&net/if.h&
#include&&net/if_dl.h&
// replace the identity with your company's domain
static const char kKeychainUDIDItemIdentifier[]&&=&&UUID&;
static const char kKeyChainUDIDAccessGroup[]&=&&.skyangel.taopianyi&;
@implementation SvUDIDTools
+&(NSString*)UDID
&&& NSString *udid&=&[SvUDIDTools getUDIDFromKeyChain];
&&& if (!udid)&{
&&&&&&& NSString *sysVersion&=&[UIDevice currentDevice].systemV
&&&&&&& CGFloat version =&[sysVersion floatValue];
&&&&&&& if (version&&= 7.0)&{
&&&&&&&&&&& udid =&[SvUDIDTools _UDID_iOS7];
&&&&&&& else if (version&&= 2.0)&{
&&&&&&&&&&& udid =&[SvUDIDTools _UDID_iOS6];
&&&&&&&&[SvUDIDTools settUDIDToKeyChain:udid];
&* iOS 6.0
&* use wifi's mac address
+&(NSString*)_UDID_iOS6
&&& return [SvUDIDTools getMacAddress];
&* iOS 7.0
&* Starting from iOS 7, the system always returns the value 02:00:00:00:00:00
&* when you ask for the MAC address on any device.
&* use identifierForVendor + keyChain
&* make sure UDID consistency atfer app delete and reinstall
+&(NSString*)_UDID_iOS7
&&& return [[UIDevice currentDevice].identifierForVendor UUIDString];
#pragma mark -
#pragma mark Helper Method for Get Mac Address
// from /questions/677530/how-can-i-programmatically-get-the-mac-address-of-an-iphone
+&(NSString *)getMacAddress
&&& int &&&&&&&&&&&&&&& mgmtInfoBase[6];
&&& char &&&&&&&&&&&&&&&*msgBuffer&= NULL;
&&& size_t &&&&&&&&&&&&
&&& unsigned char &&&&& macAddress[6];
&&& struct if_msghdr &&&*interfaceMsgS
&&& struct sockaddr_dl &*socketS
&&& NSString &&&&&&&&&&&*errorFlag&=
&&&&// Setup the management Information Base (mib)
&&& mgmtInfoBase[0]&= CTL_NET;&&&&&&&&// Request network subsystem
&&& mgmtInfoBase[1]&= AF_ROUTE;&&&&&&&// Routing table info
&&& mgmtInfoBase[2]&= 0;
&&& mgmtInfoBase[3]&= AF_LINK;&&&&&&&&// Request link layer information
&&& mgmtInfoBase[4]&= NET_RT_IFLIST;&&// Request all configured interfaces
&&&&// With all configured interfaces requested, get handle index
&&& if ((mgmtInfoBase[5]&= if_nametoindex(&en0&))&== 0)
&&&&&&& errorFlag =&@&if_nametoindex failure&;
&&&&&&&&// Get the size of the data available (store in len)
&&&&&&& if (sysctl(mgmtInfoBase, 6, NULL,&&length, NULL, 0)&& 0)
&&&&&&&&&&& errorFlag =&@&sysctl mgmtInfoBase failure&;
&&&&&&& else
&&&&&&&&&&&&// Alloc memory based on above call
&&&&&&&&&&& if ((msgBuffer&= malloc(length))&== NULL)
&&&&&&&&&&&&&&& errorFlag =&@&buffer allocation failure&;
&&&&&&&&&&& else
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&// Get system information, store in buffer
&&&&&&&&&&&&&&& if (sysctl(mgmtInfoBase, 6, msgBuffer,&&length, NULL, 0)&& 0)
&&&&&&&&&&&&&&&&&&& errorFlag =&@&sysctl msgBuffer failure&;
&&&&&&&&&&&&}
&&&&// Befor going any further...
&&& if (errorFlag&!= NULL)
&&&&&&& NSLog(@&Error:&%@&, errorFlag);
&&&&&&& if (msgBuffer)&{
&&&&&&&&&&& free(msgBuffer);
&&&&&&& return errorF
&&&&// Map msgbuffer to interface message structure
&&& interfaceMsgStruct =&(struct if_msghdr *) msgB
&&&&// Map to link-level socket structure
&&& socketStruct =&(struct sockaddr_dl *)&(interfaceMsgStruct&+ 1);
&&&&// Copy link layer address data in socket structure to an array
&&& memcpy(&macAddress, socketStruct-&sdl_data + socketStruct-&sdl_nlen, 6);
&&&&// Read from char array into a string object, into traditional Mac address format
&&& NSString *macAddressString&=&[NSString stringWithFormat:@&%02X:%02X:%02X:%02X:%02X:%02X&,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& macAddress[0], macAddress[1], macAddress[2],
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& macAddress[3], macAddress[4], macAddress[5]];
&&& NSLog(@&Mac Address:&%@&, macAddressString);
&&&&// Release the buffer memory
&&& free(msgBuffer);
&&& return macAddressS
#pragma mark -
#pragma mark Helper Method for make identityForVendor consistency
+&(NSString*)getUDIDFromKeyChain
&&& NSMutableDictionary *dictForQuery&=&[[NSMutableDictionary alloc] init];
&&&&[dictForQuery setValue:(id)kSecClassGenericPassword forKey:(id)kSecClass];
&&&&// set Attr Description for query
&&&&[dictForQuery setValue:[NSString stringWithUTF8String:kKeychainUDIDItemIdentifier]
&&&&&&&&&&&&&&&&&&& forKey:kSecAttrDescription];
&&&&// set Attr Identity for query
&&& NSData *keychainItemID&=&[NSData dataWithBytes:kKeychainUDIDItemIdentifier
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& length:strlen(kKeychainUDIDItemIdentifier)];
&&&&[dictForQuery setObject:keychainItemID forKey:(id)kSecAttrGeneric];
&&&&// The keychain access group attribute determines if this item can be shared
&&&&// amongst multiple apps whose code signing entitlements contain the same keychain access group.
&&& NSString *accessGroup&=&[NSString stringWithUTF8String:kKeyChainUDIDAccessGroup];
&&& if (accessGroup&!= nil)
#if TARGET_IPHONE_SIMULATOR
&&&&&&&&// Ignore the access group if running on the iPhone simulator.
&&&&&&&&//
&&&&&&&&// Apps that are built for the simulator aren't signed, so there's no keychain access group
&&&&&&&&// for the simulator to check. This means that all apps can see all keychain items when run
&&&&&&&&// on the simulator.
&&&&&&&&//
&&&&&&&&// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
&&&&&&&&// simulator will return -25243&(errSecNoAccessForItem).
&&&&&&&&[dictForQuery setObject:accessGroup forKey:(id)kSecAttrAccessGroup];
&&&&[dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecMatchCaseInsensitive];
&&&&[dictForQuery setValue:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
&&&&[dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
&&& OSStatus queryErr &&= noE
&&& NSData &&*udidValue&=
&&& NSString *udid&&&&&&=
&&& queryErr = SecItemCopyMatching((CFDictionaryRef)dictForQuery,&(CFTypeRef*)&udidValue);
&&& NSMutableDictionary *dict&=
&&&&[dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];
&&& queryErr = SecItemCopyMatching((CFDictionaryRef)dictForQuery,&(CFTypeRef*)&dict);
&&& if (queryErr&== errSecItemNotFound)&{
&&&&&&& NSLog(@&KeyChain Item:&%@ not found!!!&,&[NSString stringWithUTF8String:kKeychainUDIDItemIdentifier]);
&&& else if (queryErr&!= errSecSuccess)&{
&&&&&&& NSLog(@&KeyChain Item query Error!!! Error code:%ld&, queryErr);
&&& if (queryErr&== errSecSuccess)&{
&&&&&&& NSLog(@&KeyChain Item:&%@&, udidValue);
&&&&&&& if (udidValue)&{
&&&&&&&&&&& udid =&[NSString stringWithUTF8String:udidValue.bytes];
&&&&[dictForQuery release];
+&(BOOL)settUDIDToKeyChain:(NSString*)udid
&&& NSMutableDictionary *dictForAdd&=&[[NSMutableDictionary alloc] init];
&&&&[dictForAdd setValue:(id)kSecClassGenericPassword forKey:(id)kSecClass];
&&&&[dictForAdd setValue:[NSString stringWithUTF8String:kKeychainUDIDItemIdentifier] forKey:kSecAttrDescription];
&&&&[dictForAdd setValue:@&UUID& forKey:(id)kSecAttrGeneric];
&&&&// Default attributes for keychain item.
&&&&[dictForAdd setObject:@&& forKey:(id)kSecAttrAccount];
&&&&[dictForAdd setObject:@&& forKey:(id)kSecAttrLabel];
&&&&// The keychain access group attribute determines if this item can be shared
&&&&// amongst multiple apps whose code signing entitlements contain the same keychain access group.
&&& NSString *accessGroup&=&[NSString stringWithUTF8String:kKeyChainUDIDAccessGroup];
&&& if (accessGroup&!= nil)
#if TARGET_IPHONE_SIMULATOR
&&&&&&&&// Ignore the access group if running on the iPhone simulator.
&&&&&&&&//
&&&&&&&&// Apps that are built for the simulator aren't signed, so there's no keychain access group
&&&&&&&&// for the simulator to check. This means that all apps can see all keychain items when run
&&&&&&&&// on the simulator.
&&&&&&&&//
&&&&&&&&// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
&&&&&&&&// simulator will return -25243&(errSecNoAccessForItem).
&&&&&&&&[dictForAdd setObject:accessGroup forKey:(id)kSecAttrAccessGroup];
&&& const char *udidStr&=&[udid UTF8String];
&&& NSData *keyChainItemValue&=&[NSData dataWithBytes:udidStr length:strlen(udidStr)];
&&&&[dictForAdd setValue:keyChainItemValue forKey:(id)kSecValueData];
&&& OSStatus writeErr = noE
&&& if ([SvUDIDTools getUDIDFromKeyChain])&{&&&&&&&&// there is item in keychain
&&&&&&&&[SvUDIDTools updateUDIDInKeyChain:udid];
&&&&&&&&[dictForAdd release];
&&&&&&& return YES;
&&& else {&&&&&&&&&&// add item to keychain
&&&&&&& writeErr = SecItemAdd((CFDictionaryRef)dictForAdd, NULL);
&&&&&&& if (writeErr&!= errSecSuccess)&{
&&&&&&&&&&& NSLog(@&Add KeyChain Item Error!!! Error Code:%ld&, writeErr);
&&&&&&&&&&&&
&&&&&&&&&&&&[dictForAdd release];
&&&&&&&&&&& return NO;
&&&&&&& else {
&&&&&&&&&&& NSLog(@&Add KeyChain Item Success!!!&);
&&&&&&&&&&&&[dictForAdd release];
&&&&&&&&&&& return YES;
&&&&[dictForAdd release];
&&& return NO;
+&(BOOL)removeUDIDFromKeyChain
&&& NSMutableDictionary *dictToDelete&=&[[NSMutableDictionary alloc] init];
&&&&[dictToDelete setValue:(id)kSecClassGenericPassword forKey:(id)kSecClass];
&&& NSData *keyChainItemID&=&[NSData dataWithBytes:kKeychainUDIDItemIdentifier length:strlen(kKeychainUDIDItemIdentifier)];
&&&&[dictToDelete setValue:keyChainItemID forKey:(id)kSecAttrGeneric];
&&& OSStatus deleteErr = noE
&&& deleteErr = SecItemDelete((CFDictionaryRef)dictToDelete);
&&& if (deleteErr&!= errSecSuccess)&{
&&&&&&& NSLog(@&delete UUID from KeyChain Error!!! Error code:%ld&, deleteErr);
&&&&&&&&[dictToDelete release];
&&&&&&& return NO;
&&& else {
&&&&&&& NSLog(@&delete success!!!&);
&&&&[dictToDelete release];
&&& return YES;
+&(BOOL)updateUDIDInKeyChain:(NSString*)newUDID
&&& NSMutableDictionary *dictForQuery&=&[[NSMutableDictionary alloc] init];
&&&&[dictForQuery setValue:(id)kSecClassGenericPassword forKey:(id)kSecClass];
&&& NSData *keychainItemID&=&[NSData dataWithBytes:kKeychainUDIDItemIdentifier
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& length:strlen(kKeychainUDIDItemIdentifier)];
&&&&[dictForQuery setValue:keychainItemID forKey:(id)kSecAttrGeneric];
&&&&[dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecMatchCaseInsensitive];
&&&&[dictForQuery setValue:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
&&&&[dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];
&&& NSDictionary *queryResult&=
&&& SecItemCopyMatching((CFDictionaryRef)dictForQuery,&(CFTypeRef*)&queryResult);
&&& if (queryResult)&{
&&&&&&& NSMutableDictionary *dictForUpdate&=&[[NSMutableDictionary alloc] init];
&&&&&&&&[dictForUpdate setValue:[NSString stringWithUTF8String:kKeychainUDIDItemIdentifier] forKey:kSecAttrDescription];
&&&&&&&&[dictForUpdate setValue:keychainItemID forKey:(id)kSecAttrGeneric];
&&&&&&& const char *udidStr&=&[newUDID UTF8String];
&&&&&&& NSData *keyChainItemValue&=&[NSData dataWithBytes:udidStr length:strlen(udidStr)];
&&&&&&&&[dictForUpdate setValue:keyChainItemValue forKey:(id)kSecValueData];
&&&&&&& OSStatus updateErr = noE
&&&&&&&&// First we need the attributes from the Keychain.
&&&&&&& NSMutableDictionary *updateItem&=&[NSMutableDictionary dictionaryWithDictionary:queryResult];
&&&&&&&&// Second we need to add the appropriate search key/values.
&&&&&&&&// set kSecClass is Very important
&&&&&&&&[updateItem setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
&&&&&&& updateErr = SecItemUpdate((CFDictionaryRef)updateItem,&(CFDictionaryRef)dictForUpdate);
&&&&&&& if (updateErr&!= errSecSuccess)&{
&&&&&&&&&&& NSLog(@&Update KeyChain Item Error!!! Error Code:%ld&, updateErr);
&&&&&&&&&&&&
&&&&&&&&&&&&[dictForQuery release];
&&&&&&&&&&&&[dictForUpdate release];
&&&&&&&&&&& return NO;
&&&&&&& else {
&&&&&&&&&&& NSLog(@&Update KeyChain Item Success!!!&);
&&&&&&&&&&&&[dictForQuery release];
&&&&&&&&&&&&[dictForUpdate release];
&&&&&&&&&&& return YES;
&&&&[dictForQuery release];
&&& return NO;
在游戏开发中,很多时候会用到IOS的库功去获取某一些数据到unity游戏中或者在接入SDK的时候会经常用到数据的传递。当然unity提供了一个方法(UnitySendMessage)来把IOS中的数据回调到unity的游戏内部。下面我们不介绍这种方法,我们介绍直接在unity内部通过调用具有返回值IOS的方法把IOS中的数据传入unity中。
当然IOS中的NString类型不能直接传入unity中,我们需要把IOS的字符类型经过一些处理成字符类型后存入内存中然后再转成unity识别的string类型。其他的int、bool等基本类型不用特殊处理。
一、首先在IOS中我们需要一个NString类型处理函数。
char* _MakeStringCopy( const char* string){&&& if (NULL&== string)&{&&&&&&& return NULL;&&&&}&&& char* res =&(char*)malloc(strlen(string)+1);&&& strcpy(res, string);&&&}&
二、然后就可以返回一切的NString类型到unity中了。下面是在unity中调用的函数。
const char* getUDID(){&&& return _MakeStringCopy([[APService registrationID] UTF8String]);}&
三、在unity中调用示例
&&[DllImport(&__Internal&)]
private static extern string getUDID();&&
& public static string GetUdid(){&&& return getUDID();}
最后就能获取到需要的数据了。
欢迎大家加入Unity技术交流群:3112035 &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&————&大红花&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

我要回帖

更多关于 unity资源提取工具 的文章

 

随机推荐