前言
最近有个Unity游戏的项目,并且需要整合到现有iOS项目(swift)中,参考了很多大哥的分享,自己也遇到了不少很多坑,特来记录一下,希望能帮大家少走一些弯路。
涉及到的版本
- Unity2019.2.6f1
- Xcode 10.2.1
- swift 4.2
Ready? Let's go~~
1、先确保Unity导出的Xcode项目能运行成功
我在拿到Unity导出的Xcode项目时,还是有几处报错的地方,待会下面会提到,我们还是先开始集成吧!
2.将Unity项目导入到自己的项目中
tip:(Unity导出的Xcode项目,后面都称Unity项目)
2.1 将Unity项目中的Classes、Library和data三个文件直接拖入到项目中。我这里自己创建了一个UnityGame的文件夹,关于Unity项目的东西,全都放在这个文件夹下面
2.1.1 Classes和Library拖入项目中的勾选
2.1.2 Data拖入项目中的勾选
2.1.3 拖入项目后,大概长这样,颜色对了就行啦!
2.2 添加UnityUtils.h UnityUtils.mm (UnityBridge.h)到项目
下载地址在这里
因为我自己的项目中又Bridge桥接文件了,所以我这里不需要再导入了;
2.2.1 如果原来没有桥接文件的话,就把UnityBridge.h文件拖进去好了,然后在Bulid Settings配置一下
2.2.2 拖入后,需要修改一些地方
UnityUtils.h
//
// UnityUtils.h
//
// Created by Adam Venturella on 10/28/15.
//
#ifndef UnityUtils_h
#define UnityUtils_h
void custom_unity_init(int argc, char* argv[]);
#endif /* UnityUtils_h */
UnityUtils.mm
//
// UnityUtils.m
//
// Created by Adam Venturella on 10/28/15.
//
// this is taken directly from the unity generated main.mm file.
// if they change that initialization, this will need to be updated
// as well.
#include "RegisterMonoModules.h"
#include "RegisterFeatures.h"
#include
// Hack to work around iOS SDK 4.3 linker problem
// we need at least one __TEXT, __const section entry in main application .o files
// to get this section emitted at right time and so avoid LC_ENCRYPTION_INFO size miscalculation
static const int constsection = 0;
void UnityInitTrampoline();
// 原来的
//extern "C" void custom_unity_init(int argc, char* argv[])
//{
// @autoreleasepool
// {
// UnityInitTrampoline();
//// UnityParseCommandLine(argc, argv); //Unity 5.3+
// UnityInitRuntime(argc, argv); //Unity 5.6+
//
// RegisterMonoModules();
// NSLog(@"-> registered mono modules %p\n", &constsection);
// RegisterFeatures();
//
// // iOS terminates open sockets when an application enters background mode.
// // The next write to any of such socket causes SIGPIPE signal being raised,
// // even if the request has been done from scripting side. This disables the
// // signal and allows Mono to throw a proper C# exception.
// std::signal(SIGPIPE, SIG_IGN);
// }
//}
/// 修改后
extern "C" int custom_unity_init(int argc, char* argv[])
{
@autoreleasepool
{
UnityInitTrampoline();
// UnityParseCommandLine(argc, argv);
UnityInitRuntime(argc, argv);
RegisterMonoModules();
NSLog(@"-> registered mono modules %p\n", &constsection);
RegisterFeatures();
// iOS terminates open sockets when an application enters background mode.
// The next write to any of such socket causes SIGPIPE signal being raised,
// even if the request has been done from scripting side. This disables the
// signal and allows Mono to throw a proper C# exception.
std::signal(SIGPIPE, SIG_IGN);
// UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String:"AppControllerClassName"]);
}
return 0;
}
自己的Bridge桥接文件需要添加的内容(将UnityBridge.h拖进去的,已经写好了)
#import "UnityUtils.h"
#import "UnityAppController.h"
#import "UnityInterface.h"
2.3 添加工程配置
tip: 配置信息可以参考从Unity导出来的Xcode项目的配置,我在这里只是指点出来哪些地方
2.3.1 添加以下配置信息
UNITY_RUNTIME_VERSION = 2019.2.6f1;
UNITY_SCRIPTING_BACKEND = il2cpp;
GCC_THUMB_SUPPORT = NO;
GCC_USE_INDIRECT_FUNCTION_CALLS = NO
2.3.2 配置Language C++
2.3.3 配置Prefix Header,文件所在地址根据自己项目来发
2.3.4 配置Other C Flag
$(inherited)
-DINIT_SCRIPTING_BACKEND=1
-fno-strict-overflow
-DNET_4_0
-DRUNTIME_IL2CPP=1
2.3.5 配置Other C++ Flag
$(inherited)
$(OTHER_CFLAGS)
-DINIT_SCRIPTING_BACKEND=1
2.3.6 配置Header Search Paths
$(inherited)
"$(SRCROOT)/UnityGame/Classes"
"$(SRCROOT)"
$(SRCROOT)/UnityGame/Classes/Native
$(SRCROOT)/UnityGame/Libraries/bdwgc/include
$(SRCROOT)/UnityGame/Libraries/libil2cpp/include
2.3.7 配置Library Search Paths
$(inherited)
"$(SRCROOT)"
"$(SRCROOT)/UnityGame/Libraries"
2.3.8 配置Other Linker Flags
-weak_framework
CoreMotion
-weak-lSystem
2.3.9 EnableBitCode 设置为No
2.4 修改文件代码
2.4.1 UnityAppController.h文件
修改代码如下
// 修改前
//inline UnityAppController* GetAppController()
//{
// return _UnityAppController;
//}
// 修改后
NS_INLINE UnityAppController* GetAppController()
{
NSObject* delegate = [UIApplication sharedApplication].delegate;
UnityAppController* currentUnityController = (UnityAppController *)[delegate valueForKey:@"currentUnityController"];
return currentUnityController;
}
2.4.2 main.mm
// 修改前
//int main(int argc, char* argv[])
//{
//#if UNITY_USES_DYNAMIC_PLAYER_LIB
// SetAllUnityFunctionsForDynamicPlayerLib();
//#endif
//
// @autoreleasepool
// {
// UnityInitTrampoline();
// UnityInitRuntime(argc, argv);
//
// RegisterMonoModules();
// NSLog(@"-> registered mono modules %p\n", &constsection);
// RegisterFeatures();
//
// // iOS terminates open sockets when an application enters background mode.
// // The next write to any of such socket causes SIGPIPE signal being raised,
// // even if the request has been done from scripting side. This disables the
// // signal and allows Mono to throw a proper C# exception.
// std::signal(SIGPIPE, SIG_IGN);
//
// UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String: AppControllerClassName]);
// }
//
// return 0;
//}
// 修改后
int main_unity_default(int argc, char* argv[])
{
@autoreleasepool
{
UnityInitTrampoline();
// UnityParseCommandLine(argc, argv);
UnityInitRuntime(argc, argv);
RegisterMonoModules();
NSLog(@"-> registered mono modules %p\n", &constsection);
RegisterFeatures();
// iOS terminates open sockets when an application enters background mode.
// The next write to any of such socket causes SIGPIPE signal being raised,
// even if the request has been done from scripting side. This disables the
// signal and allows Mono to throw a proper C# exception.
std::signal(SIGPIPE, SIG_IGN);
//UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String:AppControllerClassName]);
// UIApplicationMain(argc, argv, nil, NSStringFromClass([UnitySubAppDelegate class]));
UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String:AppControllerClassName]);
}
return 0;
}
2.4.3 添加一个新的main.swift文件到项目
//
// main.swift
// DDog
//
// Created by leesum on 2019/11/10.
// Copyright © 2019 Lgsc. All rights reserved.
//
import Foundation
import UIKit
custom_unity_init(CommandLine.argc, CommandLine.unsafeArgv)
UIApplicationMain(
CommandLine.argc,
UnsafeMutableRawPointer(CommandLine.unsafeArgv)
.bindMemory(
to: UnsafeMutablePointer.self,
capacity: Int(CommandLine.argc)),
nil,
NSStringFromClass(AppDelegate.self)
)
2.4.4 添加依赖库,我懒,是直接从Unity项目中拖进来的
差不多了 运行一下看吧;
3.下面来解决问题
-
问题1
解决:直接把@UIApplicationMain注销掉
//@UIApplicationMain
-
问题2
解决:在开始我都说了,我的文件在UnityGame下存放,所以从Unity项目中拖过来的时候,路径已经变了;
方法一:路径写完整
#include "UnityGame/Classes/iPhone_Sensors.h"
方法二:不要路径
#include "iPhone_Sensors.h"
其实这个文件在下一个问题中,我们是需要把他删掉的,但是不解决问题就暴露不出来,尴尬。。
-
问题3
看到这么多错,不要慌
解决:可以看到都是这个DynamicLibEngineAPI.o搞的鬼
去 Build Phases 搜索 DynamicLibEngineAPI ,搜索到一个DynamicLibEngineAPI.mm文件,删掉! 搞定! -
问题4
刚拿到Unity导出的Xcode项目时,运行报错,如下
解决:打开终端,在终端中输入
chmod +x 文件目录/MapFileParser.sh
MapFileParser.sh文件就在你的项目里,自己配置路径
-
问题5
刚拿到Unity导出的Xcode项目,运行报错
分析:报错的原因是因为Unity游戏在加载的时候需要我这边把游戏ID等参数传过去,Unity已经发起了调用我这边传值的方法,但是我这边没有写,故报错;
解决:创建一个.h和.m文件,名称随便,在.m文件中加上相应的方法;方法名和返回参数需和Unity游戏的代码一致,这里也有提示,缺的几个方法,但是参数的类型需要和游戏开发去核对;
我的解决如下:
//
// MyGamePlayer.m
// Unity-iPhone
//
// Created by leesum on 2019/11/13.
//
#import "MyGamePlayer.h"
@implementation MyGamePlayer
int GetRoomID() {
return 1;
}
void hideSplash() {
NSLog(@"退出");
}
int GetGameType() {
return 1;
}
int GetJoinCM() {
return 100;
}
int GameReturn() {
return 1;
}
int GetUnitId() {
return 9;
}
int GetJoinMinUser() {
return 1;
}
int GetJoinMaxTime() {
return 1;
}
int GetUserID() {
return 1;
}
int GetGameID() {
return 1;
}
int GetLevel() {
return 1;
}
@end
我暂时只有这么多问题,后续有问题会及时更新
4.用起来
4.1 在AppDelegate中初始化代码
注意:这里定义的currentUnityController要和UnityAppController中替换的方法中的Key对应
这个时候运行一下,运行成功后,发现已经有游戏的声音了!
这就说明,肯定是已经启动了游戏;游戏启动暂停,开始这些方法,基本上都封装在UnityAppController类中,那么我们就去UnityAppController.mm的实现文件中去找;既然是启动后就有声音,那么先重点找application开头的方法,你会发现确实有启动的方法,把方法注销掉,问题就解决了
4.2 添加游戏开始方法
添加之后,运行成功->点击开始游戏
当点击开始后,并没有来到游戏界面,而是直接崩掉来到了main.swift文件中
打开打印台分析一下报错原因
这里显示是currentUnityController的问题;
解决:因为Unity的代码是OC,故找到AppDelegate,加上@objc,问题就解决了
我差不多就好了,有啥问题,可以留言哦!
参考
https://www.jianshu.com/p/ca693626d00a?open_source=weibo_search
https://www.jianshu.com/p/184f3d1e01f6
https://www.jianshu.com/p/3bf2902bf2f0
https://www.jianshu.com/p/a3df2922d98d
https://www.cnblogs.com/willbin/p/3370412.html
https://www.jianshu.com/p/ec514261e569
https://www.jianshu.com/p/51b7b4bb6748