入口
创建 GameAppController 类 继承 UnityAppController
并且在类的实现之前 需要 加 IMPL_APP_CONTROLLER_SUBCLASS(GameAppController),表明这个是程序的入口。UnityAppController 实现了 UIApplicationDelegate。 可以简单看下 UIApplicationDelegate 的生命周期。
例:
@interface GameAppController : UnityAppController
+ (instancetype)shareAppController;
- (UIWindow*)appWindow;
@end
实现
IMPL_APP_CONTROLLER_SUBCLASS(GameAppController)
@implementation GameAppController {
@end
Unity 与 Objective-C 交互
Unity 调用 Objective-C
#define UNITY_CS_API extern "C"
/**
微信登陆
*/
UNITY_CS_API void OCWXLogin(){
//objective-c 代码
}
Objective-C 调用 Unity 代码
void UnitySendMessage(const char* obj, const char* method, const char* msg);
obj 参数 表示GameObject Name
method 参数 表示要回调的方法名
msg 参数 表示回调的方法参数
Objective-C 与 Unity 的交互要注意的是
字符串使用的是 const char* 类型,而Objective-C 中使用的是NSString* 所以需要转换
字符串作为返回值返回 需要使用 strup 函数。否则程序将闪退
返回值 不能返回null 和 nil 否则闪退。所以返回值每次增加判断,如果null和nil 就用空字符串替换
例子
// const char* 转 NSString*
static inline NSString * str_c2ns(const char*s){
if (s) {
return [NSString stringWithUTF8String:s];
}else{
return [NSString stringWithUTF8String:""];
}
}
//NSString* 转 const char*
+ (const char *) str_ns2c:(NSString *) content{
return [content UTF8String];
}
//返回值使用 strdup 处理, 并做检查
UNITY_CS_API const char* OCReadClipBoard(){
NSString *contentStr = [CoreManager.sharedInstance readClipBoard];
if (contentStr == NULL || contentStr == nil) {
contentStr = @"";
}
return strdup([UnityUtility str_ns2c:contentStr]);
}
Objective-C 与 Unity 交互 有时会使用到Json 进行数据传输,Unity 中 Null 在 Objectiv-C 中解析将会报错,使用NullSafe 库解决. github地址
接入微信SDK
遇到报错
Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: '+[WXApi genExtraUrlByReq:withAppData:]: unrecognized selector sent to class
微信官方文档的解释是需要在 Other Linker Flags 中添加 -ObjC -all_load 进行处理。我加入-all_load 会导致编译报错,这个方法行不通。
首先sdk 的配置都是添加在 UnityFramework 而不是 Unity-iPhone 上。如果是老的Unity 应该只有 Unity-iPhone,那就是添加到Unity-iPhone上。
然后由于-all_load 行不通,所以用-force_load 代替。-force_load 后面需要加入libWeChatSDK.a 所在到路径作为参数
比如:
关于微信登录,或者分享失效,没有回调的情况,应该是漏写了调用
接入友盟 和 阿里支付
遇到UTDID 库冲突。这里阿里官方有解释,下载去除 UTDID 的库。 下载的地方有说明
阿里的文档让人最舒服,没遇上什么问题。
Universal Links
这个如果没有配置好,微信登录将会照成2次弹窗确认。(那种给别人加企业签的就一定会有二次弹窗,因为没有teamid)
这个比较简单,随便找一个模板,替换teamid后,上传至服务器。然后在xcode中Signing & Capabilities 中的Associated Domains 配置 applinks: 域名
打包
如果使用Unity直接到处会覆盖xcode中我们写好的代码。所以把我们接入sdk的xcode代码放入Unity项目的Plugins 文件夹的iOS文件夹中。项目没有就自己创建。并把所有的第三方库也放入其中。这样打包的时候会自动导出至xCode项目。
此外xcode项目中还有一些自定义的配置。这个需要在打包流程完成后的回调中使用代码修改。
例如
string pbxProjectPath = PBXProject.GetPBXProjectPath(locationPath);
//修改 Associated Domains 设置
ProjectCapabilityManager capabilityManager =
new ProjectCapabilityManager(pbxProjectPath, "Unity-iPhone.entitlements", "Unity-iPhone");
capabilityManager.AddAssociatedDomains(new string[]{"applinks:cs1.jxhappy.top"});
//wifi 信息
capabilityManager.AddAccessWiFiInformation();
// 百度持续定位
capabilityManager.AddBackgroundModes(BackgroundModesOptions.LocationUpdates);
capabilityManager.WriteToFile();
PBXProject pbxProject = new PBXProject();
pbxProject.ReadFromFile(pbxProjectPath);
// string xCodeFrameworkPath = "./XCodeFramework";
//
// DirectoryInfo directoryInfo = new DirectoryInfo(xCodeFrameworkPath);
//
// foreach (var directory in directoryInfo.GetDirectories())
// {
// ECKAddResourceGroupToiOSProject(locationPath, pbxProject, pbxProject.GetUnityFrameworkTargetGuid(),
// directory.Name);
// }
// 为类使用 @try @catch NULLSafe 中使用到了;
pbxProject.SetBuildProperty(pbxProject.ProjectGuid(),"GCC_ENABLE_OBJC_EXCEPTIONS","YES");
//Main
string target = pbxProject.GetUnityMainTargetGuid();
pbxProject.SetBuildProperty(target,"ENABLE_BITCODE", "NO");
pbxProject.SetBuildProperty(target,"CONFIGURATION","Release");
pbxProject.SetBuildProperty(target,"CONFIGURATION_BUILD_DIR","$(BUILD_DIR)/$(CONFIGURATION)");
//微信相关的设置 都应该设置在 pbxProject.GetUnityFrameworkTargetGuid;
pbxProject.AddFrameworkToProject(target,"CoreGraphics.framework",false);
pbxProject.AddFrameworkToProject(target,"QuartzCore.framework",false);
pbxProject.AddFrameworkToProject(target,"Foundation.framework",false);
pbxProject.AddFrameworkToProject(target,"UIKit.framework",false);
string targetUnityTarget = pbxProject.GetUnityFrameworkTargetGuid();
//添加framework
//微信sdk
pbxProject.AddFrameworkToProject(targetUnityTarget,"Security.framework",false);
pbxProject.AddFrameworkToProject(targetUnityTarget,"CoreGraphics.framework",false);
pbxProject.AddFrameworkToProject(targetUnityTarget,"WebKit.framework",false);
//支付宝sdk
pbxProject.AddFrameworkToProject(targetUnityTarget,"libc++.tbd",false);
pbxProject.AddFrameworkToProject(targetUnityTarget,"libz.tbd",false);
pbxProject.AddFrameworkToProject(targetUnityTarget,"SystemConfiguration.framework",false);
pbxProject.AddFrameworkToProject(targetUnityTarget,"CoreTelephony.framework",false);
//pbxProject.AddFrameworkToProject(targetUnityTarget,"QuartzCore.framework",false);
//pbxProject.AddFrameworkToProject(targetUnityTarget,"CoreText.framework",false);
//pbxProject.AddFrameworkToProject(targetUnityTarget, "CoreGraphics.framework", false);
//pbxProject.AddFrameworkToProject(targetUnityTarget,"UIKit.framework",false);
//pbxProject.AddFrameworkToProject(targetUnityTarget,"Foundation.framework",false);
//pbxProject.AddFrameworkToProject(targetUnityTarget,"CFNetwork.framework",false);
//pbxProject.AddFrameworkToProject(targetUnityTarget,"CoreMotion.framework",false);
// pbxProject.AddFrameworkToProject(targetUnityTarget,"AlipaySDK.framework",false);
//百度地图sdk
// pbxProject.AddFrameworkToProject(targetUnityTarget,"BMKLocationKit.framework",false);
pbxProject.AddFrameworkToProject(targetUnityTarget,"CoreLocation.framework",false);
//pbxProject.AddFrameworkToProject(targetUnityTarget,"SystemConfiguration.framework",false);
//pbxProject.AddFrameworkToProject(targetUnityTarget,"Security.framework",false);
//pbxProject.AddFrameworkToProject(targetUnityTarget,"libsqlit3.0.tbd",false);
//pbxProject.AddFrameworkToProject(targetUnityTarget, "CoreTelephony.framework", false);
//pbxProject.AddFrameworkToProject(targetUnityTarget,"libz.tbd",false);
pbxProject.AddFrameworkToProject(targetUnityTarget,"AdSupport.framework",false);
//UMengsdk
// pbxProject.AddFrameworkToProject(targetUnityTarget,"UMCommon.xcframework",false);
// pbxProject.AddFrameworkToProject(targetUnityTarget,"UMCommonLog.framework",false);
// pbxProject.AddFrameworkToProject(targetUnityTarget,"UMDevice.xcframework",false);
// pbxProject.AddFrameworkToProject(targetUnityTarget,"UMRemoteConfig.framework",false);
// pbxProject.AddFrameworkToProject(targetUnityTarget,"UTDID.framework",false);
// pbxProject.AddFrameworkToProject(targetUnityTarget,"UYuMao.framework",false);
//
// pbxProject.AddFrameworkToProject(targetUnityTarget,"UMAPM.xcframework",false);
// pbxProject.AddFrameworkToProject(targetUnityTarget,"UMLink.framework",false);
//[WXApi genExtraUrlByReq:withAppData:]
//报错 原因缺少 Wxapi genExtraUrlByReq 函数,
//-all_load 加载 所有的 静态链接库, 但是这个存在动态链接库的函数重复的问题,编译会报错
//-force_load 强制 指定加载 静态链接库。
pbxProject.AddBuildProperty(targetUnityTarget,"OTHER_LDFLAGS","-ObjC -force_load $SRCROOT/Libraries/Plugins/SDK/iOS/WechatSDK/libWeChatSDK.a");
//pbxProject.AddFrameworkToProject(target,"WechatOpenSDK-XCFramework.xcframework",false);
//Unity Tests
string targetGuid = pbxProject.TargetGuidByName(PBXProject.GetUnityTestTargetName());
pbxProject.SetBuildProperty(targetGuid, "ENABLE_BITCODE", "NO");
//Unity Framework
pbxProject.SetBuildProperty(targetUnityTarget, "ENABLE_BITCODE", "NO");
pbxProject.SetBuildProperty(targetUnityTarget, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES");
pbxProject.WriteToFile(pbxProjectPath);
//修改 Info.plist 文件
var plistPath = locationPath + "/Info.plist";
var plist = new PlistDocument();
plist.ReadFromFile(plistPath);
PlistElementDict rootDict = plist.root;
//设置LSApplicationQueriesSchemes(数组)
PlistElementArray loginChannelsArr;
loginChannelsArr = rootDict.CreateArray("LSApplicationQueriesSchemes");
loginChannelsArr.AddString("weixin");
loginChannelsArr.AddString("weixinULAPI");
loginChannelsArr.AddString("weixinURLParamsAPI");
//百度地图权限
rootDict.SetString("NSLocationWhenInUseUsageDescription","前台定位");
rootDict.SetString("NSLocationAlwaysUsageDescription", "永久定位");
rootDict.SetString("NSLocationAlwaysAndWhenInUseUsageDescription","永久定位");
//添加 url scheme
PlistElementArray urlTypes = rootDict.CreateArray("CFBundleURLTypes");
PlistElementDict wxUrl = urlTypes.AddDict();
wxUrl.SetString("CFBundleTypeRole","Editor");
wxUrl.SetString("CFBundleURLName","weixin");
PlistElementArray wxUrlScheme = wxUrl.CreateArray("CFBundleURLSchemes");
wxUrlScheme.AddString("wx528f8481cec8a716");
PlistElementDict aliPay = urlTypes.AddDict();
aliPay.SetString("CFBundleTypeRole","Editor");
aliPay.SetString("CFBundleURLName","alipay");
PlistElementArray aliUrlScheme = aliPay.CreateArray("CFBundleURLSchemes");
aliUrlScheme.AddString("hjhaGameAliPay");
plist.WriteToFile(plistPath);
接 苹果SDK 做上架准备
不得不吐槽一下,苹果文档真垃圾,真垃圾,真垃圾
- 沙盒模式的测试账号创建,提示This email address is not available for use as an Apple ID. You may already have an Apple ID associated with this address. Please try again or sign in using your existing Apple ID.
这个账号不是指你当前有的账号,也就是不能输入当前存在的账号,可以随便输入,但不能跟现有的账号重复。它只是测试的