如何做一个跨平台的游戏App?

iOS和安卓系统上的应用程序,根据提供的内容不同,按照开发方式和用户体验不同,可区分为app和游戏;

首先从开发方式不同来说明,app开发一般是用操作系统官方提供的开发套件来做对应的开发;

这里的开发套件就系统不同可做以下区别:

iOS:  Xcode, Objective-C

android: AndroidStudio, Java/Kotlin

游戏的开发方式就很多了,不过最终一步一般都是生成对应IDE的项目工程,然后在对应的项目工程上进行配置设置,签名配置等步骤,最后完成打包.ipa和.apk的打包; 在最后一步前开发方式就根据项目需求以及其他因素考量,可采取不同的开发方案了; 之前有幸在做iOS的SDK开发,对接了上百款游戏,也算对游戏的开发环境有所了解了。

2D游戏一般用: Cocos2dx, Cordova,Corona,Contruct2等,当然也可以用Unity来开发2D游戏;

3D游戏一般用: Unity为主流;

最后从用户体验不同来说明,

app在前几年时间里,界面一般要根据不同系统来做开发,市面上看到的很多app的iOS版本和安卓版本有一些UI是长的不一样的, 这里就导致用户体验不一致的问题,如果领导需要,可采取混合网页的方式,但是同时会带来体验不流畅的问题,这就要看沟通了,最终采取哪种方式了。

一般情况下,市面上的应用程序要么是app要么是游戏类型,但是碰到一些需求,需要吸取app和游戏的特性,融合在一起,丰富应用程序的功能和体验,这时候我们开发的应用程序,我通常称它为游戏app.

前段时间参与过一个项目,功能和体验就是这样的一个应用程序,我把用到的基本技术抽出来,整理代码出来一个小demo, 其它类似的游戏混合app都可以借鉴此思路进行开发; 这个小demo的效果如下所示:

iOS                  Android

demo说明:

演示场景最后一个画面是Unity的游戏场景,倒数第二个界面是React-Native界面,其它页面是原生界面;

相关开发环境说明:

Unity2018.3.11f1

AndroidStudio3.3.2 (gradle插件版本3.2.0,gradle版本4.10.1,buildToolsVersion 29.0.0-rc1)

ReactNative0.59.5

XCode10.2.1

demo效果参考步骤如下:

一. 创建ReactNative工程

参考文档https://facebook.github.io/react-native/docs/getting-started,逐步实现RN功能,下面截图就是我demo工程里创建的一个测试登录界面:

二.Unity导出原生项目

这步网上有很多教程,参考就可以了,基本没什么特别需要注意的地方,主要是一些打包配置设置问题,在我demo工程里,由于我引入了ReactNative功能,我需要把导出的xcode工程和as工程放到指定的文件夹层次,我把导出的原生项目工程截图所示如下:

使用的Unity版本在iOS和安卓打包的时候,有一些区别;

iOS端:  打包生成Xcode工程,可以选择replace或者append, 建议用append方式,这样每次打包不影响原生工程的东西。

安卓端: 打包生成AS工程,会直接替换老的文件,建议用github Desktop进行代码文件管理,不然原生工程修改的相关配置一不小心就被覆盖了。

下面说一下Unity每次修改打包成Xcode工程和AS工程的时候,会改变哪些代码和哪些文件? 此类混合项目要清楚,不然在功能协作的时候,很容易发生混乱,代码相互覆盖等问题!

开发场景一: 每次修改Unity里的.scene里的场景数据,打包出来Xcode工程,截图所示文件夹内的代码文件会发生大幅度的修改

iOS

android

 

开发场景二: 脚本代码发生修改后,打包出来的文件,截图所示红框部分文件每次新打包都会改变,黄框部分文件是脚本代码发生修改后,打包出来发生修改的文件

 iOS                                 android

测试发现Unity打包出Xcode工程以及Unity里功能变更,打包出来的Xcode工程,涉及到文件和项目配置众多,之前网上看到的很多文章大都是把Unity打包出来的新文件和配置,手动在原生项目里进行修改和文件引用众   多工作,我个人操作很麻烦,也有很多问题,每次Unity端功能发生更新,代码和文件更新到原生项目就有点麻烦了,我这边的操作步骤是在Unity端打包出来的Xcode工程上进行原生模块功能添加,原生模块功能以动态   库.framework形式引入,彼此松耦合!

三.原生项目框架引入

这一步按照ReactNative官方文档https://facebook.github.io/react-native/docs/integration-with-existing-apps来就可以了,这里需要注意;

我在iOS端使用CocoaPods (建议最好用CocoaPods集成方式,跟之前的项目工程形成松耦合)方式的时候,有一些第三方React-Native库没有CocoaPods集成方式,这时候就需要查看源码来手动link和项目配置了,或者换第三方库,再或者自己写,自己写的话,可按照官方指引https://facebook.github.io/react-native/docs/native-modules-setup来;

下面分享一段我项目中使用的Podfile文件

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0' target 'Unity-iPhone' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks! # Pods for Unity-iPhone # 'node_modules'目录一般位于根目录中
# 但是如果你的结构不同,那你就要根据实际路径修改下面的`:path` pod 'React', :path => '../node_modules/react-native', :subspecs => [
'Core',
'CxxBridge', # 如果RN版本 >= .47则加入此行
'DevSupport', # 如果RN版本 >= 0.43,则需要加入此行才能开启开发者菜单
'RCTText',
'RCTNetwork',
'RCTWebSocket', # 调试功能需要此模块
'RCTAnimation', # FlatList和原生动画功能需要此模块
# 在这里继续添加你所需要的其他RN模块
'RCTImage',
]
# 如果你的RN版本 >= 0.42.,则加入下面这行
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga' # 如果RN版本 >= .45则加入下面三个第三方编译依赖
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' # # CodePush plugin dependency
# pod 'CodePush', :path => '../node_modules/react-native-code-push'
# pod 'react-native-blur', :path => '../node_modules/react-native-blur'
# pod 'react-native-fetch-blob',:path => '../node_modules/react-native-fetch-blob'
# pod 'react-native-fast-image',:path => '../node_modules/react-native-fast-image'
# pod 'react-native-orientation',:path => '../node_modules/react-native-orientation'
# pod 'RNFS', :path => '../node_modules/react-native-fs'
# pod 'RNSVG',:path => '../node_modules/react-native-svg' target 'Unity-iPhone Tests' do
inherit! :search_paths
# Pods for testing
# pod 'react-native-blur', :path => '../node_modules/react-native-blur' end end

四. 功能整合

这里要以iOS和android两端做对应处理,区别有点大,由于iOS和安卓端都是我一个人弄,而我本身是iOS出身,对iOS端会更熟悉些,安卓端处理可能会不太专业,但也算初步实现了。

以iOS端为例:

前面的步骤可以算ReactNative功能跟Unity功能初步集成到一起了,接下来就要再加入iOS原生功能,最后再把ReactNative功能,Unity功能串接到一起了!

1. 加入iOS原生功能

demo里我是加入了两个导航页面,我是直接在Unity导出的Xcode工程上加入的,因为Unity导出Xcode工程是可以增量更新的,后续Unity测功能更新,重新打包也不会影响我旧有Xcode工程的代码。

2.引入ReactNative功能

在第一步里,我们已经创建好ReactNative项目,也创建了一个登录测试页面,在这一步里我们需要导航到这个页面,这个页面我们需要用一个原生视图控制器来承载,然后就是原生功能的简单导航了

-(UIViewController*) getRNDisplayVC
{
if(!self.rnVC)
{
NSURL* jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
jsCodeLocation=[[NSBundle mainBundle] URLForResource:@"/bundle/index" withExtension:@"jsbundle"];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"myApp"
initialProperties:nil
launchOptions:self.launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.rnVC=rootViewController;
}
return self.rnVC; }

代码里我使用的是已经打包好的.jsbundle文件,下面给出打包命令,在ReactNative文件夹下创建bundle文件夹,然后在ReactNative项目根文件夹里打开终端命令,输入下面代码

react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ./bundle/index.jsbundle --assets-dest ./bundle

最后把bundle文件夹引入到项目工程里,使用视图控制器的导航相关代码,就已经完成原生页面向ReactNative页面导航了,而ReactNative页面向原生页面导航,实质就是ReactNative访问原生模块的问题了,参考官方指引 https://facebook.github.io/react-native/docs/native-modules-ios#content

3.Unity跟原生互调或者Unity跟ReactNative互调

本质就是Unity跟原生的通信了,网上文章很多,这里就不阐述了。

demo的开发思路初步是这样,其中有一些步骤还不算完美,有做类似此类项目的同学,可以一起讨论! 

 

如何做一个跨平台的游戏App?的更多相关文章

  1. 用VUEJS做一个猫眼电影web app

    之前一直在学习原生js,可是发现原生js虽然很好,但是想实现一个稍微复杂一点的项目都很麻烦.直到遇见了vue.js,发现vue是真的很好用,而且很简洁,利用组件化开发能够快速做出项目,所以为了学习vu ...

  2. 用 Vue 做一个简单的购物app

    前言 最近在学习Vue的使用.看了官方文档之后,感觉挺有意思的.于是着手做了一个简单的购物app.h5 与原生 app 交互的原理这是我第一次在这个网站上写分享,如有不当之处,请多多指教. 一整个项目 ...

  3. 请问IOS中做一个手机网站的app壳复杂吗?

    公司开发了一个平台,手机网站已经做出来了,想开发一个苹果应用app,但公司没人会IOS开发,为了减小成本,现在想直接做一个壳来加载手机网站,请问在ios中复杂吗?是否有相应的控件直接加载url就行? ...

  4. 笔记:利用Cocos2dx 3.3 lua 做一个动作类游戏(一)

    在这之前,声明一下: 做不完我是小狗. 没办法,没毅力和恒心,之前的那个Quick Cocos2dx做的横版过关游戏的demo已经转成了3.3的版本了,其实也算是个半成品,战斗,UI啥的都有了,呵呵. ...

  5. 突发奇想想学习做一个HTML5小游戏

    前言: 最近一期文化馆轮到我分享了,分享了两个,一个是关于童年教科书的回忆,一个是关于免费电子书的.最后我觉得应该会不敌web,只能说是自己在这中间回忆了一下那个只是会学习的年代,那个充满梦想的年代. ...

  6. python做一个数独小游戏

    最近看了下python的一些知识,在这里记载一下. 1.首先是安装,在官网下载最新的版本3.6,安装的时候要注意在下面勾选上ADD TO PATH,安装的时候会自动写入到环境变量里面,如果没有勾选,可 ...

  7. 用Python做一个飞机大战游戏

    基于pygame的一款小游戏 这是我上半年做的一款小游戏,但是一直忘记了,现在才上传代码. github项目地址:StarMan 代码基于pygame,Python版本3.5.2运行正常. 游戏很简单 ...

  8. cocos2d-x 3.0来做一个简单的游戏教程 win32平台 vs2012 详解献给刚開始学习的人们!

    原代码来自于网络,因为cocos2d-x 3.0的资料,的确不多,与曾经版本号的接口非常难对上, 所以网上非常多样例都无法调试,对于新学习cocos2d-x 的同学,难度添加了,所以出一个超具体的样例 ...

  9. 【Android UI】如何做一个纯粹的Android app UI 设计

    原文:http://android.eoe.cn/topic/summary 许多开发者会在多个平台上发布应用.如果您打算为 Android 开发应用,请记住在不同的平台需要遵守不同的要求和惯例.在某 ...

随机推荐

  1. httpHandlers path="*.sky"

    <httpHandlers> <add verb="*" path="*.sky" type="WebAppHttpHandlerT ...

  2. 求数组前K个大的数

    我们举例,假若从10000万个数里选出前100个最大的数据. 首先我们先分析:既然要选出前100个最大的数据,我们就建立一个大小为100的堆(建堆时就按找最大堆的规则建立,即每一个根节点都大于它的子女 ...

  3. [LeetCode] 477. Total Hamming Distance 全部汉明距离

    The Hamming distance between two integers is the number of positions at which the corresponding bits ...

  4. 【搜索】L国的战斗之伞兵

    伞兵?SB?嘿嘿嘿 原题传送门 思路 这道题需要采用倒退的思想. 如果a[x][y]无风或可吹至无风区: 那么它南面如果是北风区,则北风区就也是无风或可吹至无风区(实际上就是可吹至无风区). 那么它北 ...

  5. 第09组 Beta冲刺(3/5)

    队名:观光队 链接 组长博客 作业博客 组员实践情况 王耀鑫 过去两天完成了哪些任务 文字/口头描述 学习 展示GitHub当日代码/文档签入记录 接下来的计划 完成短租车,页面美化 还剩下哪些任务 ...

  6. java 声明并初始化整型变量

    public class Sample { public static void main(String[] args) { int num; num = ; System.out.println(& ...

  7. 作业帮:给定一个整数数组,找出其中两个数相加等于目标值(去重set)

    题目描述 给定一个整数数组,找出其中两个数相加等于目标值 输入 [1,3,5,7,9,11] 10 输出 1,9 3,7 代码: import java.util.HashMap; import ja ...

  8. 企业应用向ASP.NET Core迁移

    有人说.NET在国内的氛围越来越不行了,看博客园文章的浏览量也起不来.是不是要转Java呢? 没有必要扯起语言的纷争,Java也好C#都只是语言是工具,各有各的使用场景.以前是C#非开源以及不能在Li ...

  9. innodb部分内部操作

    tab_node_t* tab_create_graph_create( /*====================*/ dict_table_t* table, /*!< in: table ...

  10. Mybatis设置主键自增

    <insert id="insertArea" useGeneratedKeys="true" keyProperty="areaId" ...