那位大神知PNG新款电动三轮车大小这款游戏能试玩吗,能赚钱吗?

&img src=&/v2-cacf93a4a56d21a_b.jpg& data-rawwidth=&600& data-rawheight=&414& class=&origin_image zh-lightbox-thumb& width=&600& data-original=&/v2-cacf93a4a56d21a_r.jpg&&&p&商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处。&/p&&p&原文地址:&a href=&/?target=http%3A///lab/view/324.html%3Ffrom%3Dcontent_zhihu& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&/lab/view/324.html&i class=&icon-external&&&/i&&/a&&/p&&p&&br&&/p&&h2&&b&WeTest 导读&/b&&/h2&&p&随着Unity、cocos2dx等优秀跨平台游戏引擎的出现,开发者可以把自己从繁重的Android、iOS原生台开发中解放出来,把精力放在游戏的创作。原来做一款跨平台的游戏可能需要开发者懂得Java、Objective-C、C#甚至是C、C++,现在借助Unity我们开发者只需要懂得很少的原生应用开发知识就能够打造一款优秀的游戏。特别是在鹅厂,有了Apollo这样的组件,原生的接入更加简单,可能每个项目组只需要有1-2个人懂Android,iOS开发就够了。但是也正因为如此,很多同事有了充足的理由不去学习、接触Android和iOS的开发,等到真正需要做接入的时候才开始找人找资料,难免会踩坑。基于此,本文的目的就是通过介绍基础的Android开发知识以及部分的实际操作,让大家有一定的Android基础知识储备。又或者是当作一份Unity接入Android SDK/插件的基础教程,只要照着做,就基本上不会错了。&/p&&p&&br&&/p&&p&本文将会从大家熟悉的Unity为出发点来介绍如何将自己写的或者第三方的Android插件集成到自己的游戏中。&/p&&p&1. Unity是怎么打包APK文件的?&/p&&p&2. 安装及配置Android Studio&/p&&p&3. Android开发基础以及导入到Unity&/p&&p&&br&&/p&&p&&b&一 Unity是怎么打包APK文件的?&/b&&/p&&p&大家看过一些第三方组件的接入文档都知道,在Unity里面有几个特殊的文件夹是跟打包APK有关的。首先我们就来了解一下,这些文件夹里面的内容是经历了哪些操作才被放到APK里面的呢?&/p&&p&在Unity的Assets目录下,Plugins/Android无疑是其中的重中之重,首先我们先来看一个常见的Plugins/Android目录是什么样子的。&/p&&p&&br&&/p&&img src=&/v2-468e234f8f617f7ef1c1_b.png& data-rawwidth=&1127& data-rawheight=&244& class=&origin_image zh-lightbox-thumb& width=&1127& data-original=&/v2-468e234f8f617f7ef1c1_r.png&&&p&&br&&/p&&p&后面的四个是Android工程的文件。前面两个文件夹是我们引用的第三方库,他们也会被打包到APK中。我们这个时候如果点进去前两个文件夹,我们会发现他们的目录结构跟Android这个目录也很像,大概是一下这个样子的。&/p&&p&&br&&/p&&img src=&/v2-186aeba33a00adf64f225ac_b.png& data-rawwidth=&1130& data-rawheight=&182& class=&origin_image zh-lightbox-thumb& width=&1130& data-original=&/v2-186aeba33a00adf64f225ac_r.png&&&p&&br&&/p&&p&比较上下两层的目录接口我们可以发现有很多相似的部分,如:libs、res、assets文件夹以及AndroidManifest.xml文件。这些其实都是一个标准的Android项目的所需要的文件。Unity自带的Android打包工具的作用就是把上述这几个文件夹里面的内容以固定的方式组织起来压缩到APK文件里面。&/p&&p&&br&&/p&&p&&b&接下来我们分别来看看Android打包工具都会做什么样的操作。&/b&&/p&&p&&br&&/p&&p&● libs文件夹里面有很多*.jar文件,以及被放在固定名字的文件夹里面的*.so文件。*.jar文件是Java编译器把.java代码编译后的文件,Android在打包的时候会把项目里面的所有jar文件进行一次合并、压缩、重新编译变成classes.dex文件被放在APK根目录下。当应用被执行的时候Android系统内的Java虚拟机(Dalvik或者Art),会去解读classes.dex里面的字节码并且执行。把众多jar包编译成classes.dex文件是打包Android应用不可或缺的一步。&/p&&p&&br&&/p&&p&看到这里有人可能会想不对啊,这一步只将jar包打成dex文件,那之前的java文件生成jar文件难道不是在这一步做吗?没错,这里用的jar包一般是由其他Android的IDE生成完成后再拷贝过来的。本文后面的部分会涉及到怎么使用Android的IDE并且生成必要的文件。&/p&&p&&br&&/p&&p&● libs文件夹的*.so文件则是可以动态的被Android系统加载的库文件,一般是由C/C++撰写而成然后编译成的二进制文件。要注意的是,由于实际执行这些二进制库的CPU的架构不一样,所以同样的C\C++代码一般会针对不同的CPU架构生成几分不同的文件。这就是为什么libs文件夹里面通常都有armeabi-v7a、armeabi、x86等几个固定的文件夹,而且里面的.so文件也都是有相同的命名方式。Java虚拟机在加载这些动态库的时候会根据当前CPU的架构来选择对应的so文件。有时候这些so文件是可以在不同的CPU架构上执行的,只是在不对应的架构上执行速度会慢一些,所以当追求速度的时候可以给针对每个架构输出对应的so文件,当追求包体大小的时候输出一个armeabi的so文件就可以了。&/p&&p&&br&&/p&&p&● assets文件夹,这个里面的东西最简单了,在打包APK的时候,这些文件里面的内容会被原封不动的被拷贝到APK根目录下的assets文件夹。这个文件夹有几个特性。&/p&&p&&br&&/p&&p&√ 里面的文件基本不会被Android的打包工具修改,应用里面要用的时候可以读出来。&/p&&p&√ 打出包以后,这个文件夹是只读的,不能修改。&/p&&p&√ 读取这个文件夹里面的内容的时候要通过特定的Android API来读取,参考getAssets()。&/p&&p&√ 基于上述两点,在Unity中,要读取这部分内容要通过WWW来进行加载。&/p&&p&&br&&/p&&p&除了Plugins/Android内的所有assets文件夹里面的文件会连同StreamingAssets目录下的文件一起被放到APK根目录下的assets文件夹。&/p&&p&&br&&/p&&p&● res文件夹里面一般放的是xml文件以及一些图片素材文件。xml文件一般来说有以下几种:&/p&&p&√ 布局文件,被放在res中以layout开头的文件夹中,文件里描述的一般都是原生界面的布局信息。由于Unity游戏的显示是直接通过GL指令来完成的,所以我们一般不会涉及到这些文件。&/p&&p&√ 字符串定义文件,一般被放到values文件夹下,这个里面可以定义一些字符串在里面,方便程序做国际&/p&&p&化还有本地化用。当然有时候被放到里面的还有其他xml会引用到的字符串,一般常见的是app的名称。&/p&&p&√ 动画文件,一般定义的是Android原生界面元素的动画,对于Unity游戏,我们一般也不会涉及他。&/p&&p&√ 图片资源,一般放在以drawable为开头的文件夹内。这些文件夹的后缀一般会根据手机的像素密度来来进行区分,这样我们可以往这些文件夹内放入对应像素密度的图片资源。&/p&&p&例如后缀为ldpi的drawable文件夹里面的图片的尺寸一般来说会是整个系列里面最小的,因为这个文件夹的内容会被放到像素密度最低的那些手机上运行。而一般1080p或者2k甚至4k的手机在读取图片的时候会从后缀为xxxxhdpi的文件夹里面去读,这样才可以保证应用内的图像清晰。图片资源在打包过程中会被放到APK的res文件夹内的对应目录。&/p&&p&√ Android还有其他一些常见的xml文件,这里就不一一列举了。&/p&&p&&br&&/p&&p&res文件夹下的xml文件在被打包的时候会被转换成一种读取效率更高的一种特殊格式(也是二进制的格式),命名的时候还是以xml为结尾被放到APK包里面的res文件夹下,其目录结构会跟打包之前的目录结构相对应。&/p&&p&&br&&/p&&p&除了转换xml之外,Android的打包工具还会把res文件夹下的资源文件跟代码静态引用到的资源文件的映射给建立起来,放到APK根目录的resources.arsc文件。这一步可以确保安卓应用启动的时候可以加载出正确的界面,是打包Android应用不可或缺的一步。&/p&&p&&br&&/p&&p&● AndroidManifest.xml,这份文件太重要了,这是一份给Android系统读取的指引,在Android系统安装、启动应用的时候,他会首先来读取这个文件的内容,分析出这个应用分别使用了那些基本的元素,以及应该从classes.dex文件内读取哪一段代码来使用又或者是应该往桌面上放哪个图标,这个应用能不能被拿来debug等等。在后面的部分会有详细解释。打包工具在处理Unity项目里面的AndroidManifest文件时会将所有AndroidManifest文件的内容合并到一起,也就是说主项目引用到的库项目里面如果也有AndroidManifest文&/p&&p&件,都会被合并到一起。这样就不需要手动复制粘贴。需要说明的是,这份文件在打包Android程序的时候是必不可少的,但是在Unity打包的时候,他会先检查Plugins目录下有没有这份文件,如果没有就会用一个自带的AndroidManifest来代替。此外,Unity还会自动检查项目中AndroidManifest里面的某些信息是不是默认值,如果是的话,会拿Unity项目中的值来进行替换。例如,游戏的App名称以及图标等。&/p&&p&&br&&/p&&p&● project.properties,这份文件一般只有在库项目里面能看得到,里面的内容极少,就只有一句话android.library=true。但是少了这份文件Android的打包工具就不会认为这个文件夹里面是个Android的库项目,从而在打包的时候整个文件夹会被忽略。这有时候不会影响到打包的流程,打包过程中也不会报错,但是打出的APK包缺少资源或者代码,一跑就崩溃。关于这份文件,其实在Unity的官方文档上并没有详细的描述(因为他实际上是Android项目的基础知识),导致很多刚刚接触Unity-Android开发的开发者在这里栽坑。曾&/p&&p&经有个很早就开始用Unity做Android游戏的老前辈告诉我要搞定Unity中的Android库依赖的做法是用Eclipse打开Plugins/Android文件夹,把里面的所有的项目依赖处理好就行了。殊不知这样将Unity项目跟Eclipse项目耦合在一起的做法是不太合理的,会造成Unity项目开启的时候缓慢。&/p&&p&&br&&/p&&p&● 其他文件夹例如aidl以及jni在Unity生成APK这一步一般不会涉及到,这里不展开。&/p&&p&&br&&/p&&p&看到了上述介绍的Unity打包APK的基础知识我们知道了往Plugins/Android目录下放什么样的文件会对APK包产生什么样的影响。但是实际上上述的内容只是着重的讲了Unity是怎么打包APK,所以接下来会简述一下打包这个步骤到底是怎么完成的。&/p&&p&&br&&/p&&p&Android提供了一个叫做aapt的工具,这个工具的全称是Android Asset Packaging Tool,这个工具完成了上述大部分的对资源文件处理的工作,而Unity则是通过对Android提供的工具链(Android Build Tools)的一系列调用从而完成打包APK的操作。这里感觉有点像我们写了个bat/bash脚本,这个脚本按照顺序调用Android提供的工具一样。在一些常见的Android IDE里面,这样的“bat/bash脚本”往往是一个完整的构建系统。最早的Android IDE是Eclipse,他的构建系统是Ant,是基于XML配置的构建系统。后来Android团队推出了Android专用的IDE——Android Studio(这个在文章后面会有详述),他的构建系统则是换成了gradle,从基于xml的配置一下子升级到了语言(DSL, Domain Specific Language)的层级,给使用Android Studio的人带来更多的弹性。&/p&&p&&br&&/p&&p&写到这里我想很多人都清楚了要怎么把Android的SDK/插件放到Unity里面并且打包到Unity里面。这时候应该有人会说,光会放这些文件不够啊,我还需要知道自己怎么写Android的代码并且输出相应的SDK/插件给Unity使用啊。&/p&&p&&br&&/p&&p&本文接下来的内容将会一步一步描述怎么写Android代码并且输出库文件给Unity。&/p&&p&&br&&/p&&p&&b&二 Android开发基础以及导入到Unity&/b&&/p&&p&&b&1. 开始你的第一个Android程序&/b&&/p&&p&安装完Android Studio并且配置好代理以后我们就可以打开它,在弹出的框中选择“Start a new Android Studioproject”。&/p&&p&&br&&/p&&img src=&/v2-4d3f34f36bc2bd0952f45bddc4a0429b_b.png& data-rawwidth=&1133& data-rawheight=&675& class=&origin_image zh-lightbox-thumb& width=&1133& data-original=&/v2-4d3f34f36bc2bd0952f45bddc4a0429b_r.png&&&p&&br&&/p&&p&在接下来弹出的界面里面输入应用名称,公司域名(这个其实不怎么重要)以包名(Package Name),其中我认为最重要的是包名,毕竟看一个应用的包名可以看得出一个开发者的逼格如何。。。&/p&&p&&br&&/p&&img src=&/v2-1ebfed4bdb181a128d0f333d1a7e0203_b.png& data-rawwidth=&674& data-rawheight=&814& class=&origin_image zh-lightbox-thumb& width=&674& data-original=&/v2-1ebfed4bdb181a128d0f333d1a7e0203_r.png&&&p&&br&&/p&&p&接下来选择要开发什么类型的App,这里勾上Phone and Tablet就可以了。SDK的选择一般来说根据项目的需要,最低一般不低于API 9: Android 2.3(Gingerbread),这也是Unity能接受的最低SDK。如果有些插件不能运行在这么低的Android SDK环境下的话可以酌情考虑提升到API 15: Android 4.3(IceCreamSandwich),这个等级的API一般也是可以兼容绝大多数近3-4年的机器。&/p&&p&&br&&/p&&img src=&/v2-ab435f500_b.png& data-rawwidth=&676& data-rawheight=&782& class=&origin_image zh-lightbox-thumb& width=&676& data-original=&/v2-ab435f500_r.png&&&p&&br&&/p&&p&因为我们要输出的内容是给Unity用的,这里可以先选择不带有Activity(就是承载游戏画面的基础部件),后续用到再说。&/p&&p&&br&&/p&&img src=&/v2-ea0a5a8d0f_b.png& data-rawwidth=&675& data-rawheight=&782& class=&origin_image zh-lightbox-thumb& width=&675& data-original=&/v2-ea0a5a8d0f_r.png&&&p&&br&&/p&&p&点击OK以后Android Studio就会开始初始化当前的这个Android项目。初始化会需要一段时间,因为AndroidStudio有可能会去下载一些必要的框架或者更新Android工具的版本。初始化完成以后到左边按照图里面的步骤点开就可以看到整个项目目录树的情况。&/p&&p&&br&&/p&&img src=&/v2-62dfdf36d6_b.png& data-rawwidth=&570& data-rawheight=&827& class=&origin_image zh-lightbox-thumb& width=&570& data-original=&/v2-62dfdf36d6_r.png&&&p&&br&&/p&&p&通过上图我们可以知道,一个Android Studio的项目(Project)可以由许多小的模块(Module)组成,这些模块可以是带有Activity的应用类模块,也可以是不带有Activity的库模块等等。这些小的模块之间可以有引用关系。我们可以把一些完成基础功能或者容易被复用的模块单独拆出来。&/p&&p&&br&&/p&&p&如果要新建一个模块我们可以在上图的列表中点右键选择New Module,在弹出的界面中我们可以选择要新建什么样的模块,或者从Eclipse导入旧的项目也可以。一般来说给Unity游戏开发插件最常用的就是库模块(AndroidLibrary)。同样的,在接下来弹出的窗口中填写好模块名称、包名以及最低运行的SDK。&/p&&p&&br&&/p&&p&简单的看一下Android项目的目录结构。如下图所示:&/p&&p&&br&&/p&&img src=&/v2-fb1efd851f3a_b.png& data-rawwidth=&355& data-rawheight=&273& class=&content_image& width=&355&&&p&&br&&/p&&p&● libs目录跟本文第一部分介绍的libs目录的功用是一样的,把依赖到的库放在这里面就可以了。&/p&&p&● src/main/res目录也是跟本文第一部分介绍的res目录的功能和结构是一样的,把对应资源放进去就可以了。&/p&&p&● 接下来是java代码所在的目录src/main/java,这个目录有点特殊,他的子路径跟java文件里面定义的包名(package name)要对应的上。&/p&&p&● AndroidManifest.xml也是跟第一部分介绍的AndroidManifest的功能是一样的。&/p&&p&● build文件夹是Android Studio动态生成的,打出的APK包(应用模块)或者AAR包(库模块)会被放到这里面的output文件夹。需要注意的是这个文件夹不应该被放提交到svn里面,要不然会造成项目成员之间的冲突,切记。&/p&&p&● src/test以及src/androidTest是做单元测试用的,本文不涉及。&/p&&p&&br&&/p&&p&至此,我们就可以开始动手写代码了,这里我们写一个可以弹出Android的Toast提示的Activity来替换掉Unity默认的Activity。&/p&&blockquote&简述一下Unity跟Activity的关系:在Android系统中,打开一个应用,就是开启该应用指定的启动Activity。&br&Unity里面有个默认的Activity,他的作用就是在系统启动应用的时候加载Unity的Player,这个Player就是就相当于是Unity应用的“播放器”,他会执行我们在Unity项目中创作的内容,并且通过GL指令渲染到指定的SurfaceView中,而SurfaceView则是被置于Activity里面的一个特殊的View。&/blockquote&&p&首先,我们在Android Studio中找到src/main/java(如上图所示),然后点击右键,选择新建Empty Activity。&/p&&p&&br&&/p&&img src=&/v2-ea09bdf42f8ed7b93adddbf_b.png& data-rawwidth=&1134& data-rawheight=&543& class=&origin_image zh-lightbox-thumb& width=&1134& data-original=&/v2-ea09bdf42f8ed7b93adddbf_r.png&&&p&&br&&/p&&p&在弹出的窗口中给你的Activity取个符合Java代码规范的名字,然后再想个合理的包名(当然,也可以直接用默认项目的包名也可以)。可以参考下图的配置:&/p&&p&&br&&/p&&img src=&/v2-2d22fb0a8c8_b.png& data-rawwidth=&938& data-rawheight=&795& class=&origin_image zh-lightbox-thumb& width=&938& data-original=&/v2-2d22fb0a8c8_r.png&&&p&&br&&/p&&p&其中的Generate Layout File,我们在制作给Unity游戏用的Activity是不需要勾上的。Launcher Activity勾上以后Android Studio会帮你在当前模块的AndroidManifest.xml中声明本Activity是应用的入口之一。作为一个库项目我们这边其实也不需要这个选项。点击Finish之后Android Studio就会帮我们在指定目录下创建一个很简单的Activity。里面的内容如下:&/p&&p&&br&&/p&&img src=&/v2-af0b8d5c43e7a148ef6239_b.png& data-rawwidth=&944& data-rawheight=&333& class=&origin_image zh-lightbox-thumb& width=&944& data-original=&/v2-af0b8d5c43e7a148ef6239_r.png&&&p&&br&&/p&&p&需要注意的是这只是一个最基础的Android Activity,他还不会去加载我们的Unity出来,所以我们要让他继承自Unity的Activity而不是默认的。为此,我们要先将Unity相应的jar包引入到我们的模块当中。首先找到Unity的安装目录,然后找到以下子目录Editor\Data\PlaybackEngines\AndroidPlayer\Variations\il2cpp\Release\Classes\里&/p&&p&面的classes.jar,这个就是被打包成jar包的Unity默认的Activity。我们把这个jar包复制到当前模块的libs目录下(可以把这个jar包改成你想要的名字,便于管理)。(这个jar包的源码在Editor\Data\PlaybackEngines\AndroidPlayer\Source\com\unity3d\player这个目录下。感兴趣的同学可以翻阅一下源码,就可以理解Unity播放器的加载机制。)&/p&&p&&br&&/p&&p&接下来,我们可以在Android Studio左边的Project View中找到当前的模块以后点击右键,选择“Open ModuleSetting”或者直接按F4。在弹出的窗口中我们选到最右边的页签“Dependencies”,然后选择右边绿色的加号-JarDependency。&/p&&p&&br&&/p&&img src=&/v2-99ac7f6a54ee8edb5ea874_b.png& data-rawwidth=&948& data-rawheight=&663& class=&origin_image zh-lightbox-thumb& width=&948& data-original=&/v2-99ac7f6a54ee8edb5ea874_r.png&&&p&&br&&/p&&p&从项目的libs文件夹中找到刚刚导入的jar包,点击OK即可。接下来有一个比较关键的步骤就是,我们改变这个jar包的scope属性,因为默认的scope属性(Compile)是会将该jar包里面的内容跟本模块里面Java代码合并到一起。这在之后Unity打包这个模块的jar包的时候会报错,因为Unity里面内置了刚刚这个jar包。所以我们可以参考下图把这个jar包的scope设置成provided。&/p&&p&&br&&/p&&img src=&/v2-d031d7c83fdb5a776a7751_b.png& data-rawwidth=&943& data-rawheight=&798& class=&origin_image zh-lightbox-thumb& width=&943& data-original=&/v2-d031d7c83fdb5a776a7751_r.png&&&p&&br&&/p&&p&然后删除上述列表的第一行,因为他会把所有libs文件夹下的jar包都打包到一起。跟我们刚刚做完的provided设置会有冲突。&/p&&p&&br&&/p&&p&搞定了这步骤以后我们就可以回到刚刚新创建出来的Activity把他的父类改成UnityPlayerActivity,同时别忘记引用一下相应的package,改完之后的代码是这样的:&/p&&p&&br&&/p&&img src=&/v2-aa7bc8f8b5ea1f2eaff8f4_b.png& data-rawwidth=&945& data-rawheight=&383& class=&origin_image zh-lightbox-thumb& width=&945& data-original=&/v2-aa7bc8f8b5ea1f2eaff8f4_r.png&&&p&&br&&/p&&p&到这一步,如果我们的Activity如果能被运行的话,他应该能够借助他的父类UnityPlayerActivity里面的代码来运行Unity。接下来,我们来给这个Activity添加一方法,当这个方法被调用的时候会展示一个系统默认的Toast提示。&/p&&p&&br&&/p&&img src=&/v2-0b8fb17de8f2d_b.png& data-rawwidth=&943& data-rawheight=&227& class=&origin_image zh-lightbox-thumb& width=&943& data-original=&/v2-0b8fb17de8f2d_r.png&&&p&&br&&/p&&p&看得出来,里面最核心的一个方法其实就只是调用Android里面的Toast组件而已,没啥好解释的。相反,是外面的runOnUiThread是值得大家注意的,在Android编程中,所有涉及到对UI的操作必须要放在UI线程里面来做,否则会造成其他线程修改UI线程里面的数据然后崩溃。由于我们写的这个ShowMessage方法最后会被Unity那边调用,而来自Unity的调用可能不是UI线程,所以我们要给他做适当的保护。&/p&&p&&br&&/p&&p&在Android中有很多种调度方法可以把某段代码放到UI线程里面来跑。上面这段代码的runOnUiThread的写法是最简便的一种写法。如果遇到比较复杂的逻辑可以考虑使用Messenger或者Handle来调度线程,感兴趣的同学可以上网查一下。&/p&&p&&br&&/p&&p&&b&2. 导入到Unity并且编译&/b&&/p&&p&完成Activity的代码编写之后就可以输出这个模块到Unity项目中去。在Android Studio中选择Build - Make Project或者是在左边的项目视图中选中要导出的模块然后选择Build - Make Module。选择完了之后就可以看到下面有个Gradle的进度条,待进度条完成了以后我们就可以到该模块的build/outputs/aar目录下去找输出的文件。打开这个文件夹,可以看到有个*.aar的文件。这个就是该模块所编译出来的结果,如果你用解压缩软件去解压缩它,你会发现他几乎就是一个完整的Android工程。根据本文第一部分所说的内容,我们只要在Unity工程中的Plugins/Android目录下新建一个文件夹,然后把这个文件解压缩以后整个丢进去,再手写一个名字叫project.properties,内容是android.library=true的文件放到新建的文件夹里面就可以了。&/p&&p&&br&&/p&&p&胜利在望,我们接下来只要把Unity工程里面的AndroidManifest.xml文件的入口Activity从Unity默认的的改成我们刚刚写的这个就可以了。需要注意的是,如果是旧的Unity工程,可能已经有人写过相关的AndroidManifest文件放在了Plugins/Android目录下,但是如果是全新的Unity项目的话,就没有这份文件了。在打包的时候,如果Unity发现Plugins/Android目录下没有这份文件,他会复制一份默认的文件并且修改其中跟项目有关的内容。这里我们可以从Unity的安装目录的Editor\Data\PlaybackEngines\AndroidPlayer\Apk文件夹内找到AndroidManifest.xml这份文件,把它复制一份到Unity工程的Plugins/Android目录下。接下来就是修改里面的内容。&/p&&p&&br&&/p&&img src=&/v2-f1a5dfcf28d16bd5b179eedb_b.png& data-rawwidth=&942& data-rawheight=&768& class=&origin_image zh-lightbox-thumb& width=&942& data-original=&/v2-f1a5dfcf28d16bd5b179eedb_r.png&&&p&&br&&/p&&p&&b&这里解释一下这份文件里面的一些关键内容。&/b&&/p&&p&&br&&/p&&p&● package=&com.unity3d.player&这里的内容如果放着不动,打包的时候Unity会将其修改为Player Setting的Bundle Identifier。&/p&&p&● android:versionCode以及android:versionName这两部分的内容则在打包时会根据Player Setting里面的Version以及Bundle Version Code的内容来进行修改。&/p&&p&● android:icon以及android:label这两个对应的是应用的图标以及应用名称。如果不改的话,Unity也会自动根据Player Setting里面的内容来进行修改。&/p&&p&● android:debuggable=&true&这个在打包的时候Unity也会自动根据Build Setting里面的Development Build选项自动进行修改。&/p&&p&● activity里面的android:name,这个name只的是该activity需要运行的哪个Java的Activity的类。如果不修改,加载的就是Unity默认Activity的类。这篇文章需要把默认的Activity改成刚刚我们的实现,所以,我们把刚刚写好的那个Activity的完整名称写上去(包括包名还有类名)。&/p&&p&● activity里面的android:label,这个是在桌面上图标下面写的那一行文字,也是应用的名称。不修改的话Unity会帮你维护。&/p&&p&● meta-data的这一行的name值是key,value值就是这个key对应的内容。meta-data可以根据需要自定义多个,但是key值不能重复,上面代码里面的unityplayer.UnityActivity应该是写给Unity看的,让Unity知道他自己是运行在这个Activity上。&/p&&p&&br&&/p&&p&这里我们基本上只要修改activity里面的android:name这一项。修改完成后,我们就可以通过Unity自带Build功能来出Android包了。出包之前请检查一下Player Setting里面的Bundle Identifier,不能留默认的包名在这里,会造成编译失败。编译过程中,可能会出现一些错误,&b&下面罗列几个常见的错误,可以尝试解决:&/b&&/p&&p&1. 合并Manifest文件出错,一般来说是在合并所有的AndroidManifest文件的时候出的错,常见的有重复定义了activity、里面的最低sdk写错了。模块的最低sdk不可低于项目的最低sdk。&/p&&p&2. jar文件dex错误,当你的项目中不小心存在了一个以上的相同的jar文件,就会出这个错误,把重复的删掉,只留一个就好了。&/p&&p&3. 找不到Android SDK里面的工具,这个一般来讲是Unity自己的bug,Unity一般不能兼容最新的Android SDK的工具,所以要手动降级才行。&/p&&p&&br&&/p&&p&除了上述这些之外,在打包Android项目的过程中还会出现这些那些的错误,大家看到以后不要慌张,会报错总是好的,而且一般的错误你把错误信息贴在万能的Google上,都能找到解决方案。&/p&&p&&br&&/p&&p&&b&3. Unity对Android代码的调用&/b&&/p&&p&文章到这里为止,说清楚了怎么把Android这边写成的插件打包到Unity的项目中去。但其实并没有涉及到Unity中怎么调用刚刚写好在Android的Activity中的代码。这一部对于一个Unity开发来说其实非常简单,只要以Unity提供的AndroidJavaClass还有AndroidJavaObject来做为中介就可以在Unity和Java中互传数据。这两个类的调用给人一种通过反射来调用Java代码的感觉。只要你能通过包名和类名拿到某个Java对象,就可以直接通过成员变量名称或者方法名称直接调用到Java那边的代码。举个例子,假如要在Unity中调用刚刚我们写的那个类的ShowMessage类的话我们需要在Unity中准备以下代码。&/p&&p&&br&&/p&&img src=&/v2-fbed5f97734eecc7ae9c8_b.png& data-rawwidth=&943& data-rawheight=&565& class=&origin_image zh-lightbox-thumb& width=&943& data-original=&/v2-fbed5f97734eecc7ae9c8_r.png&&&p&&br&&/p&&p&&b&简单介绍一下这段代码的几个关键点:&/b&&/p&&p&1. 通过UnityPlayer可以很方便的拿到当前Activity的Java对象实例。&/p&&p&2. 对Java对象实例的方法的调用实际上很简单,只要调用Call就可以了。&/p&&p&3. 注意用宏来区隔Native代码。UNITY_ANDROID && !UNITY_EDITOR这个推荐的写法,如果不过滤掉UNITY_EDITOR会在运行的时候报错。&/p&&p&4. 推荐在new出AndroidJavaClass还有AndroidJavaObject的地方用using来进行保护,确保执行结束后Unity会自动回收相应的代码。&/p&&p&&br&&/p&&p&其他的部分在这篇文章里面我们不展开。&/p&&p&本文到这里差不多把Unity Android的开发过程描述了一遍,如果有不清楚,欢迎留言。&/p&&p&&br&&/p&&p&&b&针对手游的性能优化,腾讯WeTest平台的Cube工具提供了基本所有相关指标的检测,为手游进行最高效和准确的测试服务,不断改善玩家的体验。&/b&&/p&&p&&b&目前功能免费开放中。欢迎点击链接:&a href=&/?target=http%3A///product/cube%3Ffrom%3Dcontent_zhihu& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&/product/cube&i class=&icon-external&&&/i&&/a&&/b& &b&使用。&/b&&/p&&p&如果对使用当中有任何疑问,欢迎联系腾讯WeTest企业qq:&/p&
商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处。原文地址: WeTest 导读随着Unity、cocos2dx等优秀跨平台游戏引擎的出现,开发者可以把自己从繁重的Android、iOS原生台开发中解放出来,把精力放在游戏的…
&img src=&/v2-7670ccd92f4d56e34a9a6383cffb705b_b.png& data-rawwidth=&1920& data-rawheight=&1080& class=&origin_image zh-lightbox-thumb& width=&1920& data-original=&/v2-7670ccd92f4d56e34a9a6383cffb705b_r.png&&&p&Unity《亚当》这部实时渲染影片引起了国内外的一致好评,大家或许不知道,场景与角色的模型制作全部由blender建模加blender雕刻完成,unity支持blender源文件热导,这意味着blender只需要保存即可同步到unity中,无需再借助于其他三维格式的支持。&/p&&a class=&video-box& href=&/?target=https%3A///video/290880& target=&_blank& data-video-id=&& data-video-playable=&true& data-name=&& data-poster=&/v2-950debd0f331f19479d15c.jpg& data-lens-id=&290880&&
&img class=&thumbnail& src=&/v2-950debd0f331f19479d15c.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&/video/290880&/span&
&/a&&p&&/p&
Unity《亚当》这部实时渲染影片引起了国内外的一致好评,大家或许不知道,场景与角色的模型制作全部由blender建模加blender雕刻完成,unity支持blender源文件热导,这意味着blender只需要保存即可同步到unity中,无需再借助于其他三维格式的支持。
&p&老里巴早,听说前苏联的地下摇滚的时候,在虾米上发现了几首,存过。&br&不懂俄语,但是歌词的意象还真好。大概是这样,有一点点意译。很久以前就翻了,现在拿出来分享一下。&/p&&p&&br&&/p&&p&第一首是Чайф(Chaif)乐队的Не спеши(Ne Spashi / Don’t Hurry)请别急&/p&&p&请别急着盖上埋葬的尘土&br&我们还有来不及做的事&br&家里是等着要照顾的孩子&br&我们还想再多活一点时间&br&家里是等着要照顾的孩子&br&我们还想再多活一点时间&/p&&p&请别急着从背后把我们枪毙&br&你们手里有的是时间行刑&br&就请让我们跳完这支舞?&br&如果可以,再唱完这首歌?&br&就请让我们跳完这支舞?&br&如果可以,再唱完这首歌?&/p&&p&请别急着让我们闭上眼睛,&br&黑暗本就是我们的归宿&br&柳条鞭打着我们的脸颊&br&被我们赤裸的身体勾引&br&柳条鞭打着我们的脸颊&br&被我们赤裸的身体勾引&/p&&p&不要急着把我们唾弃&br&不要只争朝夕的胜利&br&倘若今天我们悄然离去&br&明天剩下谁来爱你?&br&倘若今天我们悄然离去&br&明天剩下谁来爱你?&/p&&p&&br&&/p&&p&第二首是Аква?риум(Akvarium)乐队的Поезд в огне(Poezd v Ogne/ The Train’s on Fire)这趟火车着火了&/p&&p&这趟火车着火了&br&瓦辛上校来到前线&br&偕同他年轻的妻&br&瓦辛上校召集了弟兄将士们&br&宣布:我们回家吧&br&这场仗我们已经打了七十年&br&从小我们就被教育人生就是打仗&br&可是就在刚才情报说&br&这么多年来,我们都在同自己作战&/p&&p&我见过那些上将们&br&吃着我们的命,喝着我们的死&br&他们的孩子已经疯了&br&世上已经不剩他们没有的东西&br&然后我们的土地苍夷&br&我们的庙宇烧成灰烬&br&如果我们有一个家可以回&br&现在就是回家的时候&/p&&p&我们的火车着火了,没有停止的按钮&br&我们的火车着火了,没有逃亡的方向&br&很久以前,这片土地属于我们,&br&早在我们卷入这场战争之前&br&要是她不属于任何人,&br&这片土地就要死去&br&是时候,把她还给我们了&/p&&p&火炬在我们周围燃烧&br&是所有死去将士的集结&br&那些枪杀我们父亲的人&br&正在规划着我们孩子的未来&br&我们生在行军的号角下&br&我们面临着牢狱之灾&br&我说,别再地上爬了&br&回到我们的土地吧&/p&
老里巴早,听说前苏联的地下摇滚的时候,在虾米上发现了几首,存过。 不懂俄语,但是歌词的意象还真好。大概是这样,有一点点意译。很久以前就翻了,现在拿出来分享一下。 第一首是Чайф(Chaif)乐队的Не спеши(Ne Spashi / Don’t Hurry)请别…
&p&问题可以简化, 变成一个数学问题. (UE4用着熟, 就拿这个当例子, 参考资料是Unity的)&/p&&p&对于鱼竿来说, 其实我们只需要保证杆尾这个点是弹性运动即可, 那么问题就是变成了直杆与弯杆的端点位置的弹性运动, 这个只用一个PhysicsConstraint就可以搞定了:&/p&&img src=&/v2-e029d62b7c4853c7fcea6_b.png& data-rawwidth=&1143& data-rawheight=&1055& class=&origin_image zh-lightbox-thumb& width=&1143& data-original=&/v2-e029d62b7c4853c7fcea6_r.png&&&p&在这里我只用一个角度约束&/p&&img src=&/v2-f420aeecddea8d_b.png& data-rawwidth=&722& data-rawheight=&617& class=&origin_image zh-lightbox-thumb& width=&722& data-original=&/v2-f420aeecddea8d_r.png&&&p&那剩下的问题就简单了, 由三点确定一条曲线. 根据&a href=&///?target=https%3A//en.wikipedia.org/wiki/Euler%25E2%Bernoulli_beam_theory& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Euler-Bernoulli beam theory&i class=&icon-external&&&/i&&/a&, 这个在工程力学中常用的理论, 参考其中的Cantilever beams(悬臂梁)弯曲算法, 很容易就能得出我们想要的曲线:&/p&&img src=&/v2-2ae4a515adcc22dd609d_b.png& data-rawwidth=&1007& data-rawheight=&1100& class=&origin_image zh-lightbox-thumb& width=&1007& data-original=&/v2-2ae4a515adcc22dd609d_r.png&&&p&因为我们只是想求弯杆在白杆与黄杆之间插值的比率w, 那么把公式进一步简化为:&/p&&p&w = x^2 * (3 * L
- x) / (2 * L^3).
其中x是离起点的距离, L是杆长度. &/p&&img src=&/v2-f3c40e8df3af_b.png& data-rawwidth=&422& data-rawheight=&341& class=&origin_image zh-lightbox-thumb& width=&422& data-original=&/v2-f3c40e8df3af_r.png&&&p&用BP实现一下就是:&/p&&img src=&/v2-cb77ba10a1fb6bbaab3c3_b.png& data-rawwidth=&1434& data-rawheight=&493& class=&origin_image zh-lightbox-thumb& width=&1434& data-original=&/v2-cb77ba10a1fb6bbaab3c3_r.png&&&p&这样我们就把曲线上的细分点位置求解出来了:&/p&&img src=&/v2-4da9d5af701dcd7b4fc2d_b.png& data-rawwidth=&818& data-rawheight=&455& class=&origin_image zh-lightbox-thumb& width=&818& data-original=&/v2-4da9d5af701dcd7b4fc2d_r.png&&&p&至此已经解答完毕题主关于&弹性&的问题了. 至于&鱼竿&的表现部分, 我也想到两种实现方法, 一种是SplineMesh, 一种是SkeletalMesh. 下面使用比较通用的蒙皮骨骼模型实现一下看看效果. &/p&&p&Maya里做根简单的鱼杆, 绑定上一串骨骼:&/p&&img src=&/v2-bcfba1fe4d0db34973ca2_b.png& data-rawwidth=&679& data-rawheight=&613& class=&origin_image zh-lightbox-thumb& width=&679& data-original=&/v2-bcfba1fe4d0db34973ca2_r.png&&&p&那导入引擎之后, 就是需要把之前计算的曲线上的点, 设置到骨骼上就可以了:&/p&&img src=&/v2-39d9ca1cb3cb1ded67e48c800d693edf_b.png& data-rawwidth=&924& data-rawheight=&451& class=&origin_image zh-lightbox-thumb& width=&924& data-original=&/v2-39d9ca1cb3cb1ded67e48c800d693edf_r.png&&&p&&br&&/p&&img src=&/v2-c537c6bdfa84_b.png& data-rawwidth=&903& data-rawheight=&461& class=&origin_image zh-lightbox-thumb& width=&903& data-original=&/v2-c537c6bdfa84_r.png&&&p&&br&&/p&&img src=&/v2-bd410b6beaf9_b.png& data-rawwidth=&803& data-rawheight=&460& class=&origin_image zh-lightbox-thumb& width=&803& data-original=&/v2-bd410b6beaf9_r.png&&&p&原作者为了保持杆的长度不变多加了一步, 把直线插值变成了弧形插值, 这个实现起来也很容易, 就不再做试验了:&/p&&img src=&/v2-1cf829e9e6fa5cf16bfa3_b.png& data-rawwidth=&951& data-rawheight=&598& class=&origin_image zh-lightbox-thumb& width=&951& data-original=&/v2-1cf829e9e6fa5cf16bfa3_r.png&&&p&&br&&/p&&p&&br&&/p&&p&参考资料:&/p&&p&&a href=&///?target=https%3A///watch%3Fv%3DSYSeoTwG_qk& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&/watch?&/span&&span class=&invisible&&v=SYSeoTwG_qk&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/p&
问题可以简化, 变成一个数学问题. (UE4用着熟, 就拿这个当例子, 参考资料是Unity的)对于鱼竿来说, 其实我们只需要保证杆尾这个点是弹性运动即可, 那么问题就是变成了直杆与弯杆的端点位置的弹性运动, 这个只用一个PhysicsConstraint就可以搞定了:在这里我只…
&p&我考上大学那一年,我老爹非要送我去大学。&/p&&p&我执意不从,还吵了起来。&/p&&p&后来我妈偷偷跟我说,让他去吧,他一辈子都想进大学。&/p&&p&我老爹因为成分不好,没能上大学,这是他一辈子的痛。&/p&&p&送我入学,应该是他这辈子唯一的机会进大学看看。&/p&&br&&p&大学很大,他默默地在校园里走了一遍,没有说一句话。&/p&&p&我一直跟在他的后面,似乎是我在送他进大学。&/p&
我考上大学那一年,我老爹非要送我去大学。我执意不从,还吵了起来。后来我妈偷偷跟我说,让他去吧,他一辈子都想进大学。我老爹因为成分不好,没能上大学,这是他一辈子的痛。送我入学,应该是他这辈子唯一的机会进大学看看。 大学很大,他默默地在校园里…
&img src=&/v2-878c9b64d0d5ffa3b49914_b.png& data-rawwidth=&934& data-rawheight=&525& class=&origin_image zh-lightbox-thumb& width=&934& data-original=&/v2-878c9b64d0d5ffa3b49914_r.png&&&u&这些黄油,让夏天的我们如沐春风。&/u&&br&&p&&b&文 / DLS_MWZZ&/b&&/p&&p&高考还有半天就要结束,之后大家不仅要决定后4年该去哪座城市LoL,还将迎来一个躁动的假期,于是久违的第三发良心小黄油精品推荐来了。和前两期一样,这回我们的标准依旧围绕着三观内涵、制作、完成度、情怀以及其他意外之喜为核心来评价。什么你说没看过前两期?&b&关注“游戏研究社”微信公众号,&/b&&strong&后台发送关键词“黄油”就能回顾了。&/strong&&/p&&br&&p&前一期我们推荐的游戏可能会让一些朋友觉得合体内容偏少,这其实是优质小黄油一种难免的共(bei)性(lun),因为优质作品往往是秉持极强创作信仰心的作者所做,而他们在有限的制作资源条件下,面临提高游戏性与合体演出的抉择时,几乎必然会选择前者。&/p&&br&&br&&h2&《CinderellaEscape!》&/h2&&p&&strong&汉化环境:自带繁中&/strong&&/p&&br&&p&这是一款基于Unity引擎的3D动作解谜游戏(以下简称CE),游戏方式类似于推箱子,故事背景脱胎自经典童话《灰姑娘》,只不过,这并非是那个大家熟悉的童话。&/p&&br&&img src=&/v2-140db8b3fad12e962e04_b.jpg& data-rawwidth=&934& data-rawheight=&525& class=&origin_image zh-lightbox-thumb& width=&934& data-original=&/v2-140db8b3fad12e962e04_r.jpg&&&p&&i&(是个学习外语的好机会)&/i&&/p&&br&&p&游戏的主要内容,是玩家操纵被囚禁的灰姑娘通过重重难关逃出升天,共计40关。由于使用了3D引擎及物理运算,相较于传统平面推箱子,CE解谜的空间和可能性都变得非常大,一些谜题的破解方法也不唯一,让玩家可以充分享受在智慧海洋沉浮的快感。&/p&&br&&p&&i&&img src=&/v2-31efcbd2651ce_b.jpg& data-rawwidth=&953& data-rawheight=&535& class=&origin_image zh-lightbox-thumb& width=&953& data-original=&/v2-31efcbd2651ce_r.jpg&&(从简到繁,每关的设计都很丰富,任君发挥)&/i&&/p&&br&&p&也许是因为CE的游戏内容太体现智慧的光辉,虽然这款被作者定为小黄油,但实际上没什么合体演出,如果不是游戏道路中个别陷阱带有些许色彩,简直会让人几乎忘记这是一款小黄油。&/p&&br&&p&&i&&img src=&/v2-b030a7a089b17e4e40b92f_b.jpg& data-rawwidth=&845& data-rawheight=&475& class=&origin_image zh-lightbox-thumb& width=&845& data-original=&/v2-b030a7a089b17e4e40b92f_r.jpg&&(呃,我,我才不知道左边这个椅子是怎么回事呢)&/i&&/p&&br&&p&CE的系统十分有想法,兼顾了挑战性和娱乐性。游戏中灰姑娘具备“跳”的能力,可以跳上1个单位高度的平台,来躲避或跨越各种地形与陷阱,但跳跃次数是有限制的,每次跳跃会消费一个蓝色水晶鞋——这里也算是紧扣了游戏“灰姑娘”的主题 。游戏中的另一个能力是“踢”,每次消费一个红色水晶鞋,功能是将可推动的白色箱子击毁&/p&&br&&p&此外,灰姑娘还有HP,被陷阱伤害时会掉血,有些是瞬伤,有些是延时伤,需要晃动鼠标摆脱,HP扣光自然是Game over重新来过。基于种种限制,使破关的难度进一步提升,但作者显然也考虑了玩家们的接受能力,因此提供了级别系统。级别越高,水晶鞋的数量和HP都会增长,这样就增强了游戏的容错性,一两次失足并不至于千古恨。&/p&&br&&p&&i&&img src=&/v2-ecde1fcac5f13_b.jpg& data-rawwidth=&808& data-rawheight=&454& class=&origin_image zh-lightbox-thumb& width=&808& data-original=&/v2-ecde1fcac5f13_r.jpg&&(成长元素的设计令游戏更加丰富)&/i&&/p&&br&&p&游戏还有多结局的设计,在每个大关最后一小关,会分别遇到姐妹娘,将其全部救下可以进入真结局,无视之直接过关则进入普通结局,而这也正是尤其体现作者细致考虑之处。这三关如果不救人,会非常简单,几乎是直接通过,如果救人则要费一番周折,很有经典道德难题“铁道选择”的感觉。&/p&&br&&p&&i&&img src=&/v2-3f79a766f299dcc68f5674d5affba965_b.jpg& data-rawwidth=&943& data-rawheight=&530& class=&origin_image zh-lightbox-thumb& width=&943& data-original=&/v2-3f79a766f299dcc68f5674d5affba965_r.jpg&&(到底,得救的是会是谁呢?)&/i&&/p&&br&&p&反正,如果不想做一个只用下体思考的人,本游戏似乎是个很好的选择。&/p&&br&&br&&h2&《処女を守る魔法》&/h2&&p&&strong&汉化环境:有汉化补丁&/strong&&/p&&br&&p&游戏的名字大约已经引起了很多遐想和瞎想,但请不要想多,这真的是款一本正经讲故事、风格气质清新的RPG小黄油。&/p&&br&&p&&i&&img src=&/v2-33aff323c9dd547a9a0dfc55c56a65a6_b.jpg& data-rawwidth=&640& data-rawheight=&480& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&/v2-33aff323c9dd547a9a0dfc55c56a65a6_r.jpg&&(游戏开头一进入就有强烈的清新感)&/i&&/p&&br&&p&正面、细致、认真的情节是本作最明显的良心之处,感觉游戏所有的制作精力都投入到对情节内容的刻画,其他大部分素材都直接用了“RPG制作大师”自带的基本内容。玩家扮演一位初出师门的新人魔女,为了完成“魔女修行”成为独当一面的毕业魔女而踏上旅途,却不觉卷入了一场笼罩全国针对女性犯罪的阴谋。&/p&&br&&p&与其他过于天马行空、情节敷衍或内容干瘪的小黄油不同,《処女を守る魔法》d 故事设定与剧情演绎非常认真,全流程十余个小时,跨越六个章节四座风格各异的城镇,通过女主角的成长经历,来详细描绘在游戏中的这个奇幻世界里,魔女这一象征着享有自由之身的女性形象。为人自由最直观的体现,当然是对自己身体的支配权利,这也正是游戏标题的含义。&/p&&br&&p&&i&&img src=&/v2-c43d77ca127ec15bcfa22b_b.jpg& data-rawwidth=&640& data-rawheight=&480& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&/v2-c43d77ca127ec15bcfa22b_r.jpg&&(女主的老师(右)就是个自由自在的蕾丝,万事都为自己做主)&/i&&/p&&br&&p&为了营造合适的游戏体验,表达故事中心,制作组非常用心的设计了许多细节让玩家感受“女性应该主宰自己的命(shen)运(ti)并为其负责”,在此列举一二。&/p&&br&&p&游戏中查看主角状态时,不仅显示游戏参数,还会显示女主是否失身,失身于谁,无论被哪个野怪或哪个角色推了,这条记录会一直跟着你到游戏结束,每次打开都会看到,想不看都不行,让玩家极大的感同身受一种女性生存氛围。&/p&&br&&p&&i&&img src=&/v2-209d6e985fabe534f3576_b.jpg& data-rawwidth=&640& data-rawheight=&480& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&/v2-209d6e985fabe534f3576_r.jpg&&(笔者承认这个档玩的太“正直”了)&/i&&/p&&br&&p&游戏居然有QTE系统,当玩家扮演的女主遭到侵犯时,可以通过QTE操作挣扎摆脱控制,也可以放弃抵抗,如果嫌麻烦,系统还支持将QTE关掉,可以默认抵抗成功或抵抗失败,给予玩家充分的决定自由,无论清纯还是放荡,那都是自己选择的人生。也因此,如果从不战斗失败,就当全年龄RPG玩,几乎不会触发合体演出。&/p&&br&&p&&i&&img src=&/v2-effd6da65b16f_b.jpg& data-rawwidth=&185& data-rawheight=&345& class=&content_image& width=&185&&(合体时的QTE,为了保护青少年的健康成长,这里只截取了QTE的部分)&/i&&/p&&br&&p&游戏情节发展到最后一章,需要购买开价十万元的关键情报。“还债系”剧情是小黄油常用的俗套桥段,大多以巨大金额来逼迫玩家从事非常规行业,比如要你还百万巨款但打怪就掉十块钱。《処女を守る魔法》这段剧情相对于最强装备也不过万元的市场行情,十万元虽然超出玩家当时的支付能力,但面临如何赚钱的问题时,游戏中仍旧设置了多个可行方式:1、找高利贷借钱,利率10%,不还会进入BE被轮;2、去风俗场打工;3、去三俗酒店打工;4、拍卖自己的**;5、像正常RPG一样杀怪攒钱等等……这些设计不仅依托游戏世界观,又颇有现实意味。&/p&&br&&p&&i&&img src=&/v2-fcb1a7b30d138bd0836a_b.jpg& data-rawwidth=&631& data-rawheight=&473& class=&origin_image zh-lightbox-thumb& width=&631& data-original=&/v2-fcb1a7b30d138bd0836a_r.jpg&&(获得钱的方式有很多,如何选择在玩家)&/i&&/p&&br&&p&比如其中涉及身体关系的打工,都可以出卖“**”(考虑到游戏的标题看到这里你应该知道这个是什么)一次换取十倍的收益,但讽刺的是,因为一次打工最多是2000收益,所以就算是十倍,也只有可怜的两万元,距离十万目标仍差的很远,而“**”却只能卖一次。&/p&&br&&p&&strong&由于是否保有“**”会影响结局和部分游戏内容,这会让坚持到最后一章的玩家深切的感受到不值&/strong&——那么不如做一个坚强独立的女性,专心打野事业能拿到经验值升级变得更加厉害。&/p&&br&&p&也许,这正是作者希望玩家感受到的,做一个独立强大女性总是很艰难的,但并非不可能,也正因为如此,游戏中所描绘的,强大、独立、追求自由的魔女才值得人们尊重和敬佩。&/p&&br&&br&&h2&Trio of Alfheim Summonettes&/h2&&p&&strong&汉化环境:暂无&/strong&&/p&&br&&p&本作是小黄油中少见的塔防型游戏,画风细腻精致,有着一目了然的经典塔防类游戏系统,但也有与传统全年龄塔防游戏的鲜明区别,比如增加了很多情节描绘,善用了小黄油年龄限制的另类特权。&/p&&br&&p&&i&&img src=&/v2-b5b21c4b88e8ae6a19b678_b.jpg& data-rawwidth=&722& data-rawheight=&539& class=&origin_image zh-lightbox-thumb& width=&722& data-original=&/v2-b5b21c4b88e8ae6a19b678_r.jpg&&(基本上一张图就大概知道怎么玩的简单小游戏)&/i&&/p&&br&&p&玩家扮演一位邪恶魔王,拐走人间三位元素贤者。夺取她们的法力,准备统治世界。因此堕落、邪恶黑化的剧情是游戏的特点。游戏中击毙的敌人,都是前来拯救元素贤者的同僚、勇士、僧侣等等,是好人,而被夺取魔法的贤者只能眼睁睁看着他们惨死在自己失控的法力之下,发出无助的悲鸣……直到她们无法承受,迷失自我,堕落为恶魔的帮凶。&/p&&br&&p&&i&&img src=&/v2-abceeadddef5f6b647a220894adbfe54_b.jpg& data-rawwidth=&516& data-rawheight=&190& class=&origin_image zh-lightbox-thumb& width=&516& data-original=&/v2-abceeadddef5f6b647a220894adbfe54_r.jpg&&风:贤者的魔法本是为了帮助他人才诞生的……&/i&&/p&&p&&i&水:无辜的人们被如此屠杀……太残忍了……&/i&&/p&&p&&i&火:大家不要过来!被我的魔法擦一下就要变成焦炭了!&/i&&/p&&br&&p&堕落邪恶化情节放在塔防游戏,非常引人深思。与其他容易犯困的塔防不同,三位贤者在游戏中会随机出现台词演出,结合敌人被击杀时发出的亡啸声,悲壮的战斗音乐和凄凉阴暗的胜利音乐,使得场面异常惨烈,尤其是游戏后期常常要按下加速功能,大规模绞肉机般收割的时候,再加上堕落之前贤者们的哀叹、悲鸣,与堕落后各种疯狂情绪的发泄形成的对比,更强化了一种道德鞭笞的效果。&/p&&br&&p&大部分塔防类游戏都是对毫无反抗能力的敌人下手,也因此总爱用“正义”系故事背景作为麻醉剂让人减少道德谴责感。而本游戏的情节演出则颇有撕碎虚假的全年龄温柔乡的效果,也是一面镜子——也许,我们之中很多人,在玩塔防游戏时,内心不自觉的冒出了与堕落后的贤者们一样的想法吧。&/p&&br&&p&&i&&img src=&/v2-907f348a3bdc67bea6f8d4_b.jpg& data-rawwidth=&514& data-rawheight=&190& class=&origin_image zh-lightbox-thumb& width=&514& data-original=&/v2-907f348a3bdc67bea6f8d4_r.jpg&&恶风:嗯,又死一个……真爽啊&/i&&/p&&p&&i&黑水:永别了……可爱又可悲的人类……&/i&&/p&&p&&i&邪火:烧吧烧吧都烧成灰!&/i&&/p&&br&&br&&h2&《RIZU》&/h2&&p&&strong&&strong&汉化环境:有汉化补丁&/strong&&/strong&&/p&&br&&p&初玩就有惊艳的感受,很难相信这是基于“RPG制作大师”引擎的游戏,细细品味之后更会发觉,《RIZU》在画面、音乐、系统、剧情上都有非常丰富厚道的内容,简直是难得一见的上佳之作,仿佛令人梦回90年代的2D RPG黄金期——请问,能出SFC版吗?&/p&&br&&p&画面上最直观的体现,就是精致的动态效果。《RIZU》中所有的动画效果,都有良好的节奏感和强烈的打击感,无论敌我的动作举手投足都透着一股帅劲,女主更是无论大小技能,都有几分 “必杀技装酷教科书”《机器人大战》的感觉。这些动画演出一扫劣质小黄油中画面不给力的先天缺陷,说明制作组针对画面演出下了很大功夫。&/p&&br&&p&&i&&img src=&/v2-f3eace70e6_b.jpg& data-rawwidth=&512& data-rawheight=&288& class=&origin_image zh-lightbox-thumb& width=&512& data-original=&/v2-f3eace70e6_r.jpg&&(开篇单挑牛头人的战斗就像制作组在秀本领)&/i&&/p&&br&&p&静态画面也一样上乘,虽然剧情不长,人物不多,但立绘风格统一细腻靓丽,并且表情丰富传神,为生动表现剧情提升了很大效果。&/p&&br&&p&&i&&img src=&/v2-a1cbbdf5627e_b.jpg& data-rawwidth=&640& data-rawheight=&480& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&/v2-a1cbbdf5627e_r.jpg&&(游戏中所有的名称都用了这种动静态结合的帅气风格)&/i&&/p&&br&&p&游戏日常的画面是像素点阵风格,不仅确保了动画效果的细腻,还有深厚的情怀感,差点让人以为恶魔城新作在任天堂主机发售了……看来因KONAMI花式赶走游戏制作人而愤怒的爱好者真不少。&/p&&br&&p&&i&&img src=&/v2-7cbe1d6afd6e6af8a215a3e29ca1b1e9_b.jpg& data-rawwidth=&625& data-rawheight=&475& class=&origin_image zh-lightbox-thumb& width=&625& data-original=&/v2-7cbe1d6afd6e6af8a215a3e29ca1b1e9_r.jpg&&(制作组你直说了吧,到底有多爱恶魔城…总觉得我以前来过这儿…)&/i&&/p&&br&&p&《RIZU》的音乐音效制作非常用心,近年少见。大部分小黄油由于制作资源的限制,会使用一些常见的免费曲库,玩十个可能在九个里听到同一首“过夜休息曲”,而本作不仅根据游戏内容大量原创了BGM,还质量上乘十分动听。城镇中曲风轻松惬意,久放如陈酿般缭绕不绝;迷宫中则风情各异,甚至混入朦胧的轻声低语,仿佛诉说着这里发生的事情,令人不安又好奇;Boss战便要荡气回肠,深入刺激着心神让战栗与振奋并发,让人忍不住想问:制作组你们出OST吗?&/p&&br&&p&&i&&img src=&/v2-1368eaeeeab_b.jpg& data-rawwidth=&546& data-rawheight=&416& class=&origin_image zh-lightbox-thumb& width=&546& data-original=&/v2-1368eaeeeab_r.jpg&&(这种规模的音乐制作名单,小黄油一般不会有)&/i&&/p&&br&&p&游戏系统也很有意思,众多小创新让游戏玩起来非常新颖有趣,仿佛一股清流。&/p&&br&&p&游戏中角色没有级别,打多少敌人都没用,想要变强,只能去炼金工房进行1000货币一次的属性强化,或者去圣殿购买价格不菲的装备,还可以购买克制强敌属性的魔法卷轴,但特别贵。总之,宛如成年人世界一般,只有钱才是真理。&/p&&br&&p&&i&&img src=&/v2-4d276af0a3eb31a02054_b.jpg& data-rawwidth=&683& data-rawheight=&517& class=&origin_image zh-lightbox-thumb& width=&683& data-original=&/v2-4d276af0a3eb31a02054_r.jpg&&(在游戏初期,击败敌人一次只有几十块进账,这宛如打劫一般的昂贵价格……)&/i&&/p&&br&&p&游戏迷宫的样子也与大部分RPG不一样,乍看非常像动作游戏却又有创新。移动只需要十字键,并没有“跳”的功能,而且有“移动力”的设计(下图右上角),玩家在地图中的行动会消耗移动力,比如遭遇敌人、拾取道具、通过陷阱等等,移动力耗光等同于战斗失败,会强行回到迷宫入口并损失一半金钱,虽然可以在城镇酒馆购买回复移动力的道具,但前期很穷并不好买,因此还是探索迷宫的规划性重要。&/p&&br&&p&&i&&img src=&/v2-c4eaedc4c4becb75b8dd_b.jpg& data-rawwidth=&627& data-rawheight=&472& class=&origin_image zh-lightbox-thumb& width=&627& data-original=&/v2-c4eaedc4c4becb75b8dd_r.jpg&&(绿色钱袋是道具,蓝色的是敌人,鞋子状的可能是陷阱,路过都掉移动力)&/i&&/p&&br&&p&游戏的战斗系统融合了多种元素,非常爽快。第一个特点是游戏没有MP概念,魔法的释放代价相当于“信用卡”形式,先花钱后填补,使用一次某类魔法后需要通过若干时间来充能,如果能调整好使用节奏,那么就可以用不同类魔法肆意狂轰滥炸,极大的解决了RPG游戏连续战斗续航的问题。&/p&&br&&p&第二个特点是SP的使用,相当于“储蓄卡”形式先充钱后消费,进入战斗时有个初始值,战斗中普攻或技能需要消费SP,如果SP不足需要通过防御或吃药来恢复。这两个特点,结合上技能树类型的学习形式,以及行动条回合制,使玩家攻关过程中可以形成丰富有趣的作战方式,而非枯燥地刷怪。&/p&&br&&img src=&/v2-0d3002cdd6ca587cbc2f_b.jpg& data-rawwidth=&762& data-rawheight=&574& class=&origin_image zh-lightbox-thumb& width=&762& data-original=&/v2-0d3002cdd6ca587cbc2f_r.jpg&&&p&作为一款RPG,剧情自然也是重点,而上述的各个优点,都是制作组围绕着为游戏剧情表现而做出的努力。玩家扮演一位斩杀主人出逃的奴隶战士RIZU,为了移除自己身上的诅咒、复活被奴隶主杀害的母亲而展开冒险,并在冒险者之街邂逅了三位朋友,只不过随着她探索的脚步,隐藏在黑暗中的惊人秘密也逐渐解开。&/p&&br&&p&和很多设计细致的作品一样,虽然描述的只是一个少女逃亡的小故事,但搭建舞台的背景设定内容足够丰富到宏大,借此制作组使用了拼图式的故事表述。如果玩家按照情节一路通剧情去玩,自然接触的内容有限,甚至除了开篇之外不会遇到任何其他的合体演出,简直让人忘记这是个小黄油,直到最后迎来一个非常绝望的表面结局,并引出剧情表里两部分的差别。&/p&&br&&p&想要触及内情,就要满足主流程之外的附加条件,当然在凑足条件的过程中自然也会解锁其他合体演出,仿佛在吐槽传统少年向RPG——真相并不适合让躲在少年幻梦中的人知晓,只有敢直面丑恶的坚强者才值得承受。&/p&&br&&p&最后,在这款游戏里,你还可以感受到深藏其中对ACG文化的热爱,比如——&/p&&br&&p&&img src=&/v2-39de842f3ffefcd689ca5_b.jpg& data-rawwidth=&527& data-rawheight=&403& class=&origin_image zh-lightbox-thumb& width=&527& data-original=&/v2-39de842f3ffefcd689ca5_r.jpg&&&i&制作组真是毫不掩饰喜好呢。&/i&&/p&
这些黄油,让夏天的我们如沐春风。 文 / DLS_MWZZ高考还有半天就要结束,之后大家不仅要决定后4年该去哪座城市LoL,还将迎来一个躁动的假期,于是久违的第三发良心小黄油精品推荐来了。和前两期一样,这回我们的标准依旧围绕着三观内涵、制作、完成度、情怀…
&img src=&/v2-1cf0aa0c9e981a811140_b.jpg& data-rawwidth=&1920& data-rawheight=&921& class=&origin_image zh-lightbox-thumb& width=&1920& data-original=&/v2-1cf0aa0c9e981a811140_r.jpg&&&p&//--前言&/p&&p&文章是老文章了,技术还在沿用,而且最近对射击游戏突然上瘾,无奈射击能力比较差(看来我还是比较适合rts),所以也把技术文章过一些出来,这个还是有些用的么&/p&&p&//--正文&/p&&a href=&/?target=https%3A///wiki/Source_Multiplayer_Networking& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Source Multiplayer Networking&i class=&icon-external&&&/i&&/a&&br&&p&较早的文章了,介绍了source引擎在多人对战网络同步(尤其是用于fps游戏)中的做法,在行业内影响了很多多人对战游戏的开发。&/p&&p&在了解了其中的技术和概念之后,对于玩家来说,就会知道为什么fps游戏对射的时候不要静止,要来回跑,除了让对方难以瞄准外,物理技术上也是如此哦&/p&&br&&p&&strong&基本概念&/strong&&/p&&br&&p&这个图可以说很好地表达了,客户端和服务器之间的关系。&/p&&ol&&li&服务器一般以一定帧数(比如30帧,也可以更高)的速度tick,然后以一定频率(一般低于tick的频率)来发snapshot给客户端&/li&&ol&&li&服务器常常也buffer一些指令&/li&&/ol&&li&客户端以一定频率发送input的指令(和tick帧数保持一致),然后本地buffer一定时间(比如100ms的服务器传过来的snapshot)&/li&&/ol&这两点放在一起,就可以建立起一个逻辑基本正确的客户端服务器多人对战系统了。&br&&br&&strong&延时和体验&/strong&&br&但是逻辑基本正确的系统是远远不够的,对人对战的体验和单机打怪(我们认为这个是好的标准)之间的差异就来自延时。&br&这里的延时包括:对于移动以及射击会有所不同,按照程序执行的顺序&br&&ol&&li&按下鼠标到网络packet发出--客户端帧数越高越好&/li&&li&网络延时(ping)--延时最大头&/li&&li&服务器上面buffering的时间--可以根据重要性进行取舍&/li&&li&服务器上面执行时间(帧数越高越低)&/li&&li&服务器执行结果下行,又是一个网络延时(ping)--延时最大头&/li&&li&客户端buffering时间&/li&&li&客户端显示时间(敌人倒地飙血等等)&/li&&/ol&&strong&input prediction(预演)&/strong&&br&所以,按照初始的客户端服务器逻辑,一枪开出去或者一个移动操作做出来,要经过这么久才能有所反应,70ms延时,要150ms左右才能走完循环,这个体验延迟感很强,就是有问题。&br&所以引入一个input prediction的概念:就是不等服务器返回确认,就立刻做出表现,移动,开枪射击的弹道火花等等,然后在服务器回包的时候做一个正确性验证,不对的话就纠正。&br&&br&&strong&entity interpolation(平滑插值)&/strong&&br&然后平滑可以作为一个原则,加入到整个同步过程的方方面:&br&&ol&&li&entity移动,服务器发过来的是一个新的位置,那么就通过一些插值(可以是线性,可以是曲线(走一个寻路))&/li&&li&本地纠正,如果服务器验证和本地预演不匹配,那么一个瞬移就太糙了,可以走一个平滑的插值过去&/li&&/ol&&br&&strong&延时和逻辑正确&/strong&&br&延时带来的更严重的一个问题是逻辑正确性,由于时差的问题,我们本地客户端看到的东西,和服务器上面的不完全一致,然后客户端的命令走到服务器上进一步有一个延时。&br&如图中,我们在客户端上看到的是蓝色线条的敌人,但是一枪开出去的逻辑到了服务器上,敌人已经向左走了一段距离,这就会造成该打到的没打到。&br&&strong&lag compensation(延迟补偿)&/strong&&br&处理这个方法就是,开枪这种指令到服务器上都是有时间戳的,然后服务器会把敌人会退到开枪的这个瞬间,然后做计算命中,这样逻辑就正确了。&br&但是这个也不是绝对准确的,只能说是一个相对准确,因为这个回退位置不可能和你本地的时间完全一致,只能说是一个近似一致的。&br&但是如果敌人是静止的,那就完全一致了,所以一个静止的敌人总是更容易被打中,即便技术上也是如此。&br&&br&&strong&优化&/strong&&br&这里谈的是fps游戏,实际上这个系统可以用于大量的游戏系统,比如mmo,然后体验的优化就可以包括:&br&&ol&&li&预演做的更好:比如加上搓招,前摇等过程,尽可能把能预演的都做好,把“拙”藏好&/li&&li&降低延时:&/li&&ol&&li&网络路线选择的更好&/li&&li&让服务器和客户端tick的速度更高&/li&&li&可以的话减少buffering&/li&&li&可以的话减少移动插值的delay&/li&&/ol&&/ol&&strong&死穴与逻辑冲突&/strong&&br&在理解了工作原理之后,我们就知道有一些事情是不可避免的,比如:&br&&ol&&li&你看见敌人的瞬间就躲到掩体里,但是敌人还是爆了你的头--这是有可能的,你的即时反应还没有同步到服务器上,而服务器上计算命中是一个延迟补偿的,所以本地虽然没看到,但是还是被击中了&/li&&li&移动的shooter比静止的shooter有优势,这里是两个原因&/li&&ol&&li&上面延迟补偿部分提到了,移动的人对于另外一台的机器上的人来说,和服务器上不会在像素级完全一致&/li&&li&另外就是有移动插值的存在,我们看动的物体总是有一定的延时,&/li&&/ol&&/ol&所以fps游戏的时候,两边对射,千万别静止站着,要左右跑,物理技术上就会比站着有优势哦
//--前言文章是老文章了,技术还在沿用,而且最近对射击游戏突然上瘾,无奈射击能力比较差(看来我还是比较适合rts),所以也把技术文章过一些出来,这个还是有些用的么//--正文 较早的文章了,介绍了source引擎在多人对战网…
&p&相信很多来到这里的人和我第一次到这里一样,都是想找一种比较好的目标跟踪算法,或者想对目标跟踪这个领域有比较深入的了解,虽然这个问题是&b&经典目标跟踪算法&/b&,但事实上,可能我们并不需要那些曾经辉煌但已被拍在沙滩上的tracker(目标跟踪算法),而是那些即将成为经典的,或者就目前来说最好用、速度和性能都看的过去tracker。我比较关注目标跟踪中的相关滤波方向,接下来我帮您介绍下我所认识的目标跟踪,尤其是相关滤波类方法,分享一些我认为比较好的算法,顺便谈谈我的看法。&/p&&p&1.图片来自某些slides和paper,如有侵权请提醒删除。&/p&&p&2.以下内容主要是论文的简单总结,代码分析和个人看法,不涉及任何公司内部资料。&/p&&p&3.转载请注明出处,谢谢。&/p&&p&4.如有错误欢迎指出,非常感谢。有问题可以私信我,也可以在评论区提出,上班族时间有限,有空我尽量都会回复,也感谢各位道友帮忙解答。&/p&&p&/*************************************我是分割线**********************************************/&/p&&p&&b&先来混个脸熟,大概了解一下目标跟踪这个方向都有些什么&/b&。一切要从2013年开始说起,那一年的冬天和往常一样冷。。如果你问别人近几年有什么比较niubility的跟踪算法,大部分人都会扔给你吴毅老师的论文,&b&OTB50&/b&和&b&OTB100&/b&(OTB50这里指OTB-2013,OTB100这里指OTB-2015,感谢指正):&/p&&ul&&li&Wu Y, Lim J, Yang M H. &b&Online object tracking: A benchmark&/b& [C]// CVPR, 2013.&/li&&li&Wu Y, Lim J, Yang M H. &b&Object tracking benchmark &/b&[J]. TPAMI, 2015.&/li&&/ul&&p&顶会转顶刊的顶级待遇,在加上引用量多,影响力不言而喻,已经是做tracking必须跑的数据库了,测试代码和序列都可以下载: &a href=&///?target=http%3A//cvlab.hanyang.ac.kr/tracker_benchmark/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Visual Tracker Benchmark&i class=&icon-external&&&/i&&/a&,OTB50包括50个序列,都经过人工标注:&/p&&img src=&/v2-e544f145ded9d69c98e092adaf2d8bc5_b.png& data-rawwidth=&1730& data-rawheight=&694& class=&origin_image zh-lightbox-thumb& width=&1730& data-original=&/v2-e544f145ded9d69c98e092adaf2d8bc5_r.png&&&p&论文在数据库上对比了&b&包括2012年及之前的29个顶尖的tracker&/b&,有大家比较熟悉的OAB, IVT, MIL, CT, TLD, Struck等,大都是顶会转顶刊的神作,由于之前没有比较公认的数据库,论文都是自卖自夸,大家也不知道到底哪个好用,所以这个database的意义非常重大,直接促进了跟踪算法的发展,后来又扩展为&b&OTB100&/b&发到TPAMI,有100个序列,难度更大更加权威,我们这里参考OTB100的结果,首先是29个tracker的情况(&i&标出了一些性能速度都比较好的算法&/i&):&/p&&img src=&/v2-63db35d3d2f57965cea3c_b.png& data-rawwidth=&518& data-rawheight=&389& class=&origin_image zh-lightbox-thumb& width=&518& data-original=&/v2-63db35d3d2f57965cea3c_r.png&&&p&接下来再看结果(&i&更加详细的情况建议您去看论文比较清晰&/i&):&/p&&img src=&/v2-92fe48e735d8a4ae1585_b.png& data-rawwidth=&1161& data-rawheight=&730& class=&origin_image zh-lightbox-thumb& width=&1161& data-original=&/v2-92fe48e735d8a4ae1585_r.png&&&p&直接上结论:平均来看&b&Struck, SCM, ASLA&/b&等算法的性能比较高,排在前三,着重强调&b&CSK&/b&,第一次向世人展示了相关滤波的潜力,&b&排第四还362FPS&/b&简直逆天了。速度排第二的是经典算法&b&CT(64fps)&/b&(&i&这段时间是压缩感知大热的时候,这里能看到很多稀疏相关算法~都是历史&/i&)。如果对更早期的算法感兴趣,推荐另一篇经典的survey(&i&反正我是没兴趣也没看过&/i&):&/p&&ul&&li&Yilmaz A, Javed O, Shah M. &b&Object tracking: A survey &/b&[J]. CSUR, 2006. &/li&&/ul&&p&2012年以前的算法基本就是这样,自从2012年AlexNet问世以后,CV各个领域都有了巨大变化,所以我猜你肯定还想知道年发生了什么,抱歉我也不知道(&i&容我卖个关子&/i&),不过我们可以肯定的是,2013年以后的论文确定以及必定都会引用OTB50这篇论文,借助&b&谷歌学术中的被引用次数&/b&功能,得到如下结果:&/p&&img src=&/v2-ccb19ad37fe2a0393afbdf98_b.png& data-rawwidth=&907& data-rawheight=&563& class=&origin_image zh-lightbox-thumb& width=&907& data-original=&/v2-ccb19ad37fe2a0393afbdf98_r.png&&&p&这里仅列举几个排名靠前的,(&i&注意引用量&/i&)依次是&b&Struck&/b&转TPAMI, 三大相关滤波方法&b&KCF, CN, DSST&/b&, 和&b&VOT竞赛&/b&,这里仅作示范,有兴趣可以亲自去试试。&b&(这么做的理论依据是&/b&:一篇论文,在它之前的工作可以看它的引用文献,之后的工作可以看谁引用了它;虽然引用量并不能说明什么,但好的方法大家基本都会引用的(&i&表示认可&/i&);之后还可以通过限定时间来查看某段时间的相关论文,如&a href=&tel:&&&/a&就能找到最新的论文了,至于论文质量需要仔细甄别;其他方向的重要论文也可以这么用,顺藤摸瓜,然后你就知道大牛是哪几位,接着关注跟踪一下他们的工作&b& )&/b&这样我们就大致知道目标跟踪领域的最新进展应该就是相关滤波无疑了,再往后还能看到相关滤波类算法有&b&SAMF, LCT, HCF, SRDCF&/b&等等。当然,引用量也与时间有关,建议分每年来看,这里就不贴图了(&i&相关滤波类新论文也可以通过查引用KCF的论文去找&/i&)。此外,最新版本OPENCV3.2除了&b&TLD&/b&,也包括了几个很新的跟踪算法 &a href=&///?target=http%3A//www.docs.opencv.org/3.2.0/d9/df8/group__tracking.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&OpenCV: Tracking API&i class=&icon-external&&&/i&&/a&:&/p&&img src=&/v2-7f1e3a8d9f_b.png& data-rawwidth=&984& data-rawheight=&342& class=&origin_image zh-lightbox-thumb& width=&984& data-original=&/v2-7f1e3a8d9f_r.png&&&p&TrackerKCF接口实现了&b&KCF&/b&和&b&CN&/b&,影响力可见一斑,这一点就可以说明很多问题了,还有个GOTURN是基于深度学习的方法,速度虽快但精度略差,窃以为太激进了...&/p&&p&/*************************************我是分割线**********************************************/&/p&&p&&b&总体介绍下目标跟踪。&/b&这里说的目标跟踪,是通用单目标跟踪,第一帧给个矩形框,这个框在数据库里面是人工标注的,在实际情况下大多是检测算法的结果,然后需要跟踪算法在后续帧紧跟住这个框,以下是VOT对跟踪算法的要求:&/p&&img src=&/v2-518e71f77d3bf360acdc6f_b.png& data-rawwidth=&480& data-rawheight=&361& class=&origin_image zh-lightbox-thumb& width=&480& data-original=&/v2-518e71f77d3bf360acdc6f_r.png&&&p&通常目标跟踪面临&b&几大难点&/b&(吴毅在&b&VALSE&/b&的slides):外观变形,光照变化,快速运动和运动模糊,背景相似干扰:&/p&&img src=&/v2-b5f8aff728d0de563869_b.png& data-rawwidth=&716& data-rawheight=&416& class=&origin_image zh-lightbox-thumb& width=&716& data-original=&/v2-b5f8aff728d0de563869_r.png&&&p&平面外旋转,平面内旋转,尺度变化,遮挡和出视野等情况:&/p&&img src=&/v2-3dbabf17d52c20bcbdf12_b.png& data-rawwidth=&622& data-rawheight=&460& class=&origin_image zh-lightbox-thumb& width=&622& data-original=&/v2-3dbabf17d52c20bcbdf12_r.png&&&p&正因为这些情况才让tracking变得很难,目前比较常用的数据库除了&b&OTB&/b&,还有谷歌学术找到的&b&VOT&/b&竞赛数据库(类比ImageNet),已经举办了四年,VOT2015和VOT2016都包括60个序列,所有序列也是免费下载 &a href=&///?target=http%3A//votchallenge.net/challenges.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&VOT Challenge | Challenges&i class=&icon-external&&&/i&&/a&:&/p&&ul&&li&Kristan M, Pflugfelder R, Leonardis A, et al. &b&The visual object tracking vot2013 challenge results&/b& [C]// ICCV, 2013.&/li&&li&Kristan M, Pflugfelder R, Leonardis A, et al. &b&The Visual Object Tracking VOT2014 Challenge Results&/b& [C]// ECCV, 2014.&/li&&li&Kristan M, Matas J, Leonardis A, et al. &b&The visual object tracking vot2015 challenge results&/b& [C]// ICCV, 2015.&/li&&li&Kristan M, Ales L, Jiri M, et al. &b&The Visual Object Tracking VOT2016 Challenge Results&/b& [C]// ECCV, 2016.&/li&&/ul&&p&&b&OTB和VOT区别&/b&:OTB包括25%的灰度序列,但VOT都是彩色序列,这也是造成很多颜色特征算法性能差异的原因;两个库的评价指标不一样,具体请参考论文;VOT库的序列分辨率普遍较高,这一点后面分析会提到。对于一个tracker,如果两个库(最好是OTB100和VOT2016)都跑了且结果上佳,那性能肯定是非常优秀的(&i&两个库调参你能调好,我服,认了~~&/i&),如果只跑了一个。。(仅供参考)我比较认可的是VOT2016,因为序列都是精细标注,且评价指标我更加认可(&i&人家毕竟是竞赛,评价指标发过TPAMI的&/i&),&b&差别最大的地方&/b&,OTB是随机帧开始,或矩形框加随机干扰初始化去跑,作者说这样更加符合检测算法给的框框;而VOT是第一帧初始化去跑,每次跟踪失败(预测框和标注框不重叠)时,5帧之后再次初始化,VOT以short-term为主,且认为跟踪检测应该在一起永不分离,detecter会多次初始化tracker。至于哪个更好,看你,和你的需求。&/p&&p&&b&补充&/b&:&b&OTB&/b&在2013年公开了,对于2013以后的算法是透明的,有调参的可能性,尤其是那些只跑OTB,而且论文中有关键参数直接给出还精确到小数点后两位的算法,建议您先实测再评价(&i&人心不古啊~被坑的多了&/i&),但&b&VOT&/b&竞赛的数据库是每年更新,还动不动就重新标注,动不动就改变评价指标,对当年算法是不可见且难度很大的,所以结果更可靠。&b&如果您认可以上看法,后面会推荐很多在我看来顶尖又快速的算法。如果您不认可以上看法,后面也就没必要看下去了,谢谢!&/b&(&i&看每篇论文都会觉得这个工作太好太重要了,如果没有这篇论文,必会地球爆炸,宇宙重启~~所以就像大家都通过历年ILSVRC竞赛结果为主线了解深度学习的发展一样,第三方的结果更具说服力,所以我也以&/i&&b&竞赛排名+是否公开源码+实测性能&/b&&i&为标准分析每个方法&/i&)&/p&&p&&b&目标视觉跟踪(Visual Object Tracking)&/b&,大家比较公认分为两大类:&b&生成(generative)&/b&模型方法和&b&判别(discriminative)&/b&模型方法,目前比较流行的是判别类方法,也叫检测跟踪tracking-by-detection,为保持完整性,以下简单介绍。&/p&&p&&b&生成类方法&/b&,在当前帧对目标区域建模,下一帧寻找与模型最相似的区域就是预测位置,比较著名的有&b&卡尔曼滤波,粒子滤波,mean-shift&/b&等。举个例子,从当前帧知道了目标区域80%是红色,20%是绿色,然后在下一帧,搜索算法就像无头苍蝇,到处去找最符合这个颜色比例的区域,推荐算法&b&ASMS&/b& &a href=&///?target=https%3A///vojirt/asms& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&vojirt/asms&i class=&icon-external&&&/i&&/a&:&/p&&ul&&li&Vojir T, Noskova J, Matas J. &b&Robust scale-adaptive mean-shift for tracking&/b& [J]. Pattern Recognition Letters, 2014.&/li&&/ul&&p&&b&ASMS&/b&是VOT2015的第20名官方推荐的实时算法,VOT2016的32名(&i&中等水平&/i&),平均帧率&b&125FPS&/b&,在经典mean-shift框架下加入了尺度估计,经典颜色直方图特征,加入了两个先验(尺度不剧变+可能偏最大)作为正则项,和反向尺度一致性检查。作者给了C++代码,在相关滤波和深度学习盛行的年代,还能看到mean-shift打榜还有如此高的性价比实在不容易(已泪目~~),实测性能还不错,如果您对生成类方法情有独钟,这个非常推荐您去试试。(&i&某些算法,如果连这个你都比不过。。天台在24楼,不谢&/i&)&/p&&p&&b&判别类方法&/b&,OTB50里面的大部分方法都是这一类,CV中的经典套路&b&图像特征+机器学习&/b&, 当前帧以目标区域为正样本,背景区域为负样本,机器学习方法训练分类器,下一帧用训练好的分类器找最优区域(马超在VALSE的slides):&/p&&img src=&/v2-d2c2473036eda496b79609_b.png& data-rawwidth=&1337& data-rawheight=&651& class=&origin_image zh-lightbox-thumb& width=&1337& data-original=&/v2-d2c2473036eda496b79609_r.png&&&p&与生成类方法最大的区别,是分类器训练过程中用到了&b&背景信息&/b&,这样分类器就能专注区分前景和背景,所以判别类方法普遍都比生成类好。举个例子,在训练时告诉tracker目标80%是红色,20%是绿色,还告诉它背景中有橘红色,要格外注意别搞错了,这样的分类器知道更多信息,效果也肯定更好。&b&tracking-by-detection&/b&和&b&检测算法&/b&非常相似,如经典行人检测用HOG+SVM,&b&Struck&/b&用到了haar+structured output SVM,跟踪中为了尺度自适应也需要多尺度遍历搜索,区别仅在于跟踪算法对特征和在线机器学习的速度要求更高,检测范围和尺度更小而已。这点其实并不意外,大多数情况检测识别算法复杂度比较高不可能每帧都做,这时候用复杂度更低的跟踪算法就很合适了,只需要在跟踪失败(drift)或一定间隔以后再次检测去初始化tracker就可以了。其实我就想说,&b&FPS才TMD是最重要的指标,慢的要死的算法可以去死了&/b&(&i&喂同学,别这么偏激,速度可以慢慢优化嘛&/i&)。经典判别类方法推荐&b&Struck&/b&和&b&TLD&/b&,都能实时性能还行,Struck是2012年之前最好的方法,TLD是经典long-term的代表,即使效果差一点但思想非常值得借鉴:&/p&&ul&&li&Hare S, Golodetz S, Saffari A, et al. &b&Struck: Structured output tracking with kernels &/b&[J]. IEEE TPAMI, 2016. &/li&&li&Kalal Z, Mikolajczyk K, Matas J. &b&Tracking-learning-detection &/b&[J]. IEEE TPAMI, 2012. &/li&&/ul&&p&长江后浪推前浪,前面的已被排在沙滩上,后浪就是&b&相关滤波&/b&类方法(correlation filter简称CF,或discriminative correlation filter简称DCF,注意和后面KCF种的DCF方法区别,包括前面提到的那几个,后面要着重介绍),和&b&深度学习&/b&(Deep ConvNet based)类方法,因为深度学习类并不了解就不瞎推荐了,除了Winsty的几篇 &a href=&///?target=http%3A//www.winsty.net/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Naiyan Wang - Home&i class=&icon-external&&&/i&&/a&,还有VOT2015的冠军&b&MDNet &/b&&a href=&///?target=http%3A//cvlab.postech.ac.kr/research/mdnet/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Learning Multi-Domain Convolutional Neural Networks for Visual Tracking&i class=&icon-external&&&/i&&/a&和VOT2016的冠军&b&TCNN &/b&&a href=&///?target=http%3A//www.votchallenge.net/vot2016/download/44_TCNN.zip& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&votchallenge.net/vot201&/span&&span class=&invisible&&6/download/44_TCNN.zip&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a& ,速度方面比较突出的如80FPS的&b&SiamFC &/b&&a href=&///?target=http%3A//www.robots.ox.ac.uk/%7Eluca/siamese-fc.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&SiameseFC tracker&i class=&icon-external&&&/i&&/a&和100FPS的&b&GOTURN &/b&&a href=&///?target=https%3A///davheld/GOTURN& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&davheld/GOTURN&i class=&icon-external&&&/i&&/a&,注意是在GPU上。基于ResNet的&b&SiamFC-R&/b&在VOT2016表现不错,很看好后续发展,如果有兴趣可以去VALSE听作者自己讲解 &a href=&///?target=http%3A///w_19ruirwrel.html%23vfrm%3D8-8-0-1& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&VALSE--LucaBertinetto-Oxford-JackValmadre-Oxford-pu&i class=&icon-external&&&/i&&/a&,至于GOTURN,效果比较差,跑100FPS又有什么用呢,所以还不推荐,暂时持观望态度。写论文的同学深度学习类是特点也有巨大潜力。&/p&&ul&&li&Nam H, Han B. &b&Learning multi-domain convolutional neural networks for visual tracking&/b& [C]// CVPR, 2016.&/li&&li&Nam H, Baek M, Han B. &b&Modeling and propagating cnns in a tree structure for visual tracking&/b&. arXiv preprint arXiv:, 2016.&/li&&li&Bertinetto L, Valmadre J, Henriques J F, et al. &b&Fully-convolutional siamese networks for object tracking&/b& [C]// ECCV, 2016.&/li&&li&Held D, Thrun S, Savarese S. &b&Learning to track at 100 fps with deep regression networks &/b&[C]// ECCV, 2016.&/li&&/ul&&p&还有几篇国人大作遇到了不要惊讶:MEEM, TGPR, CLRST, MUSTer,在VOT中能看到身影。&b&最后&/b&,深度学习END2END的强大威力在目标跟踪方向还远没有发挥出来,还没有和相关滤波类方法拉开多大差距(&i&速度慢是天生的我不怪你,但效果总该很高吧,不然你存在的意义是什么呢。。革命尚未成功,同志仍须努力&/i&)&/p&&p&最后强力推荐 &a class=&member_mention& href=&///people/2d6e027e5db50df5dea1& data-hash=&2d6e027e5db50df5dea1& data-hovercard=&p$b$2d6e027e5db50df5dea1&&@Qiang Wang&/a& 维护的资源&b&benchmark_results&/b&:大量顶级方法在OTB库上的性能对比,各种论文代码应有尽有,大神自己C++实现并开源的CSK, KCF和DAT,找不着路的同学请跟紧,别迷路 &a href=&///?target=https%3A///foolwood/benchmark_results& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&foolwood/benchmark_results&i class=&icon-external&&&/i&&/a&,还有他自己最新论文DCFNet论文加源码,别错过。&/p&&p&再隆重推荐&a class=&member_mention& href=&///people/24f6a8ba54a520ceb91b& data-hash=&24f6a8ba54a520ceb91b& data-hovercard=&p$b$24f6a8ba54a520ceb91b&&@H Hakase&/a& 维护的&b&相关滤波类资源&/b& &a href=&///?target=https%3A///Ha}

我要回帖

更多关于 最新款封闭三轮摩托车 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信