如何将Unity游戏嵌入iOS原生的Swift应用程序

阅读“关于 11 分钟

Hi! :hand:

文章来源:How to embed a Unity game into an iOS native Swift App

Hi!为了我们未来的B2B协议,我们必须必须把我们的游戏集成到IOS原生的Swift应用环境中去。为了使它高效而且没有错误,我们已经努力了很多天。 我们想通过这篇简单的教程来分享我们的只是和进展。

引用:

本教程的灵感来自于其他人的工作: 将Unity5集成到使用Xcode开发的原生IOS应用中 https://the-nerd.be/2015/11/13/integrate-unity-5-in-a-native-ios-app-with-xcode-7

jiulongw / swift-unity https://github.com/jiulongw/swift-unity

keyv / iOSUnityVuforiaGuide https://github.com/keyv/iOSUnityVuforiaGuide

jack_loverde / Unity 5 Vuforia 6和iOS原生集成 https://bitbucket.org/jack_loverde/unity-5-vuforia-6-and-ios-native-integration/src/master

注意事项:

1、这篇教程深受Jiulong Wang的工作的启发,你可以点击链接查看他的教程和他出色的自动化脚本https://github.com/jiulongw/swift-unity 2、这篇教程使用Unity2017.4.0f1,但是它也适用于2018.2.2f1版本。但是必须把项目中“构建设置”的”不匹配返回类型”设置为”yes”。 3、注意Xcode不喜欢在路径和项目名称中使用空格,所以需要避免它。 4、注意嵌入Unity会在游戏中产生问题,尤其是图形方面的问题 5、当你修改了你的Unity项目并再一次把它导出时,请确定替换”Classes”,“Libraries”和”Data”文件夹,检查项目设置中的”Configurations”是否已被设置为”Untiy”。 6、当你在Xcode中遇到错误时,命令”Clean”(Product/Clean)Command+Shift+K和”Clean Build Folder”Command+Option+Shift+K能帮你在构建之前摆脱它。 7、当你编译时,如果在Xcode中遇到一个”Could not locate device support files” 错误,下载这个https://github.com/iGhibli/iOS-DeviceSupport 并且在”/Applications/Xcode.app/Contents/Developer/Platforns/iPhoneOS.platform/DeviceSupport”

教程:

1、打开Xcode并且创建一个新的Swift工程或者打开一个已经存在的工程。

Unity-Embed-Into-Ios_1.png

2、选择”Single View App”,然后点击”下一步”

Unity-Embed-Into-Ios_2.png

3、命名你的项目并设置语言为Swift

Unity-Embed-Into-Ios_3.png

4、保存你的工程到你想要保存的地方

Unity-Embed-Into-Ios_4.png

5、打开你的Unity工程并切换到iOS平台

Unity-Embed-Into-Ios_5.png

6、如果你还没有”Editor“文件夹,那就创建一个,并拷贝”XcodePostBuild.cs”脚本(在教程开始的地方你可以在”Extra“文件夹里找到)。这个脚本是Jiulong Wang提供的。

Unity-Embed-Into-Ios_6.png

7、打开脚本并且替换”XcodePrijectRoot”为你刚刚创建的的Xcode工程路径。路径必须是到包含”.xcodeproj”文件的那层文件夹。然后显然替换”XcodeProjectName”为你的Xcode项目名称。

Unity-Embed-Into-Ios_7.png

8、编译你的游戏并保存在你所创建的Xcode工程相同的文件件下。

Unity-Embed-Into-Ios_8.png

9、打开你的Xcode工程,查看”General”选项卡是不是选中了有效的”Team”,并且验证你的”Bundle Identifer”是不是OK

Unity-Embed-Into-Ios_9.png

10、下载教程开始时提供的”Extra“文件夹,从它里面拷贝”Unity”文件夹到Xcode工程目录文件夹。

Unity-Embed-Into-Ios_10.png

11、现在拖拽文件夹到Xcode树状结构上,并在弹出的窗口选择”Copy items if needed”和”Create groups”。

Unity-Embed-Into-Ios_11.png
Unity-Embed-Into-Ios_12.png

12、从Unity导出文件夹中拷贝并粘贴”Classes”、”Libraries“和”Data”文件夹到Xcode项目中之前创建的Unity文件夹中

Unity-Embed-Into-Ios_13.png

13、现在拖拽”Classes“和”Libraries“文件夹到Xcode树状结构上,并在弹出的窗口选择”Copy items if needed”和”Create groups”。

Unity-Embed-Into-Ios_14.png
Unity-Embed-Into-Ios_15.png

14、然后,拖拽”Data“文件夹到Xcode树状结构上,但只选择”Create folder references”选项。

Unity-Embed-Into-Ios_16.png
Unity-Embed-Into-Ios_17.png
Unity-Embed-Into-Ios_18.png

15、在项目的”General”(现在在Info)标签页设置”Unity”配置

Unity-Embed-Into-Ios_19.png

16、现在你可以使用”Extra“文件夹提供的文件完全替换”AppDelegate.swift”,”Main.storyboard”和”ViewController.swift”文件或者你可以使用你自己的文件合并到这些文件中。

Unity-Embed-Into-Ios_20.png

17、如果你要替换他们,在Xcode中选中”AppDelegate.swift”,”Main.storyboard”和”ViewController.swift”并把它们移到垃圾回收箱来删除它们。

Unity-Embed-Into-Ios_21.png

18、然后,拖拽extra文件夹提供的三个文件到Xcode工程树上,并选择选项”Copy items if needed”和”Create groups”。

Unity-Embed-Into-Ios_22.png
Unity-Embed-Into-Ios_23.png

19、如果Xcode询问你是否配置一个bridging header,选择”不创建”。

Unity-Embed-Into-Ios_24.png

那两个脚本也是Jiulong wang提供的。 AppDelegate.swift

 1 import UIKit
 2 
 3 @UIApplicationMain
 4 class AppDelegate: UIResponder, UIApplicationDelegate {
 5     
 6     var window: UIWindow?
 7     
 8     var application: UIApplication?
 9     
10     @objc var currentUnityController: UnityAppController!
11     
12     var isUnityRunning = false
13     
14     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
15         // Override point for customization after application launch.
16         
17         self.application = application
18         unity_init(CommandLine.argc, CommandLine.unsafeArgv)
19         
20         currentUnityController = UnityAppController()
21         currentUnityController.application(application, didFinishLaunchingWithOptions: launchOptions)
22         
23         // first call to startUnity will do some init stuff, so just call it here and directly stop it again
24         /*startUnity()
25         stopUnity()*/
26         
27         return true
28     }
29     
30     func applicationWillResignActive(_ application: UIApplication) {
31         // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
32         // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
33         
34         if isUnityRunning {
35             currentUnityController.applicationWillResignActive(application)
36         }
37     }
38     
39     func applicationDidEnterBackground(_ application: UIApplication) {
40         // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
41         // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
42         
43         if isUnityRunning {
44             currentUnityController.applicationDidEnterBackground(application)
45         }
46     }
47     
48     func applicationWillEnterForeground(_ application: UIApplication) {
49         // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
50         
51         if isUnityRunning {
52             currentUnityController.applicationWillEnterForeground(application)
53         }
54     }
55     
56     func applicationDidBecomeActive(_ application: UIApplication) {
57         // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
58         
59         if isUnityRunning {
60             currentUnityController.applicationDidBecomeActive(application)
61         }
62     }
63     
64     func applicationWillTerminate(_ application: UIApplication) {
65         // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
66     }
67     
68     func startUnity() {
69         if !isUnityRunning
70         {
71             isUnityRunning = true
72             currentUnityController.applicationDidBecomeActive(application!)
73         }
74     }
75     
76     func stopUnity() {
77         if isUnityRunning {
78             currentUnityController.applicationWillResignActive(application!)
79             isUnityRunning = false
80         }
81     }
82 }

ViewController.swift

 1 import UIKit
 2 
 3 class ViewController: UIViewController
 4 {
 5     @IBOutlet var rotateSwitch: UISwitch!
 6     
 7     override func viewDidLoad()
 8     {
 9         super.viewDidLoad()
10         
11        /* if let appDelegate = UIApplication.shared.delegate as? AppDelegate
12         {
13             appDelegate.startUnity()
14             
15             NotificationCenter.default.addObserver(self, selector: #selector(handleUnityReady), name: NSNotification.Name("UnityReady"), object: nil)
16         }*/
17     }
18     
19     @objc func handleUnityReady() {
20         showUnitySubView()
21     }
22     
23     func showUnitySubView() {
24         if let unityView = UnityGetGLView() {
25             // insert subview at index 0 ensures unity view is behind current UI view
26             view?.insertSubview(unityView, at: 0)
27             
28            /* unityView.translatesAutoresizingMaskIntoConstraints = false
29             let views = ["view": unityView]
30             let w = NSLayoutConstraint.constraints(withVisualFormat: "|-0-[view]-0-|", options: [], metrics: nil, views: views)
31             let h = NSLayoutConstraint.constraints(withVisualFormat: "V:|-75-[view]-0-|", options: [], metrics: nil, views: views)
32             view.addConstraints(w + h)*/
33         }
34     }
35     
36     @IBAction func startUnity(_ sender: UIButton)
37     {
38         if let unityView = UnityGetGLView()
39         {
40             unityView.isHidden = false;
41         }
42         
43         if let appDelegate = UIApplication.shared.delegate as? AppDelegate
44         {
45             appDelegate.startUnity()
46            NotificationCenter.default.addObserver(self, selector: #selector(handleUnityReady), name: NSNotification.Name("UnityReady"), object: nil)
47         }
48     }
49     
50     @IBAction func stopUnity(_ sender: UIButton)
51     {
52         if let appDelegate = UIApplication.shared.delegate as? AppDelegate
53         {
54             appDelegate.stopUnity()
55             
56             if let unityView = UnityGetGLView()
57             {
58                 unityView.isHidden = true;
59             }
60         }
61     }
62 }

20、如果你不导入我们的”Main.storyboard”文件,你可以自己创建并链接按钮到”ViewController.swift“中对应的函数

Unity-Embed-Into-Ios_25.png
Unity-Embed-Into-Ios_26.png

21、一旦你做完了”Main.storyboard”和”ViewController.swift”,稍后检查是否链接到storyboard中的”Class“变量

Unity-Embed-Into-Ios_27.png

22、为了避免”LaunchScreen,storyboard“文件的一些错误,删除他,并在项目的”General”标签页设置”Main.storyboard“为”场景启动文件”

Unity-Embed-Into-Ios_28.png
Unity-Embed-Into-Ios_29.png
Unity-Embed-Into-Ios_30.png

23、现在所有的都要建立起来了,你应该能选择你的IOS设备并且在上面编译你的Xcode工程。

Unity-Embed-Into-Ios_31.png

24、一旦你的应用启动起来,按下”Start Unity”按钮启动你的游戏,按下”Pause Unity”暂停并隐藏它。你可以按下”Start Unity”再一次恢复它。

Unity-Embed-Into-Ios_32.png
Unity-Embed-Into-Ios_33.png

Gist code


To use, see:Jektify - Doc

jektify © 2019  +

Música

Goodbye! :wink:


The word of the day!

Put a very powerful message.