如何做一個跨平臺的游戲App? iOS和安卓系統上的應用程式,根據提供的內容不同,按照開發方式和用戶體驗不同,可區分為app和游戲; 首先從開發方式不同來說明,app開發一般是用操作系統官方提供的開發套件來做對應的開發; 這裡的開發套件就系統不同可做以下區別: iOS: Xcode, Objecti ...
如何做一個跨平臺的游戲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版本 >= 0.47則加入此行 'DevSupport', # 如果RN版本 >= 0.43,則需要加入此行才能開啟開發者菜單 'RCTText', 'RCTNetwork', 'RCTWebSocket', # 調試功能需要此模塊 'RCTAnimation', # FlatList和原生動畫功能需要此模塊 # 在這裡繼續添加你所需要的其他RN模塊 'RCTImage', ] # 如果你的RN版本 >= 0.42.0,則加入下麵這行 pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga' # 如果RN版本 >= 0.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:1]; 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的開發思路初步是這樣,其中有一些步驟還不算完美,有做類似此類項目的同學,可以一起討論!