swift 4 整合导入Unity3d项目

1、创建配置文件 .xcconfig

487D74AD-5382-46B2-B1DE-40D3D24FF1A5.png

配置文件内容

// 版本号要改成自己项目对应的版本
UNITY_RUNTIME_VERSION = 5.5.2f1
UNITY_SCRIPTING_BACKEND = il2cpp;
GCC_THUMB_SUPPORT = NO;
GCC_USE_INDIRECT_FUNCTION_CALLS = NO

//U3D存放目录
UNITY_IOS_EXPORT_PATH = $(PROJECT_DIR)/Unity;

GCC_PREFIX_HEADER = $(UNITY_IOS_EXPORT_PATH)/Classes/Prefix.pch;

//添加的动态库
OTHER_LDFLAGS = -weak-lSystem -weak_framework CoreMotion -weak_framework GameKit -weak_framework iAd -framework CoreGraphics -framework AVFoundation -framework CoreVideo -framework CoreMedia -framework SystemConfiguration -framework CoreLocation -framework MediaPlayer -framework CFNetwork -framework AudioToolbox -framework OpenAL -framework QuartzCore -framework OpenGLES -framework UIKit -framework Foundation -liconv.2 -liPhone-lib;

HEADER_SEARCH_PATHS = $(inherited) $(UNITY_IOS_EXPORT_PATH) $(UNITY_IOS_EXPORT_PATH)/Unity/Classes $(UNITY_IOS_EXPORT_PATH)/Unity/Classes/Native $(UNITY_IOS_EXPORT_PATH)/Unity/Classes/UI $(UNITY_IOS_EXPORT_PATH)/Unity/Libraries $(UNITY_IOS_EXPORT_PATH)/Unity/Libraries/libil2cpp/include $(UNITY_IOS_EXPORT_PATH)/Unity/Libraries/bdwgc/include;
LIBRARY_SEARCH_PATHS = $(inherited) $(UNITY_IOS_EXPORT_PATH) $(UNITY_IOS_EXPORT_PATH)/Libraries $(UNITY_IOS_EXPORT_PATH)/Libraries/libil2cpp/include;

ENABLE_BITCODE = NO;

//请根据自己的项目修改
SWIFT_OBJC_BRIDGING_HEADER = $(PROJECT_DIR)/$(PRODUCT_NAME)/ConfigFile/UnityBridge.h;

OTHER_CFLAGS = -DINIT_SCRIPTING_BACKEND=1;
CLANG_CXX_LANGUAGE_STANDARD = compiler-default;
CLANG_CXX_LIBRARY = libc++;
CLANG_WARN_BOOL_CONVERSION = NO;
CLANG_WARN_CONSTANT_CONVERSION = NO;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
CLANG_WARN_EMPTY_BODY = NO;
CLANG_WARN_ENUM_CONVERSION = NO;
CLANG_WARN_INT_CONVERSION = NO;
CLANG_WARN_OBJC_ROOT_CLASS = YES;
CLANG_WARN_UNREACHABLE_CODE = NO;
CLANG_WARN__DUPLICATE_METHOD_MATCH = NO;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_ENABLE_OBJC_EXCEPTIONS = NO;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_THUMB_SUPPORT = NO;
GCC_USE_INDIRECT_FUNCTION_CALLS = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION[arch=*64] = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = NO;
GCC_WARN_UNINITIALIZED_AUTOS = NO;
GCC_WARN_UNUSED_FUNCTION = NO;
GCC_NO_COMMON_BLOCKS = NO;
CLANG_ENABLE_MODULES = NO;

CLANG_WARN_DOCUMENTATION_COMMENTS = NO;

CLANG_WARN_EMPTY_BODY = NO;
CLANG_WARN_INFINITE_RECURSION = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = NO;
CLANG_WARN_UNREACHABLE_CODE = NO;

GCC_WARN_UNUSED_FUNCTION = NO;

CLANG_WARN__DUPLICATE_METHOD_MATCH = NO;

注意:某些路径不确定的,可以在Build Settings 中进行拖拽,以得到正确的路径。

配置文件完成后在项目的 PROJECT 中进行操作,如下图:
896FF51D-4B31-45F8-862E-F349FAB908E8.png

2、创建桥接文件 UnityBridge.h

//  Copyright © 2018年 Ping. All rights reserved.
//

#ifndef UnityBridge_h
#define UnityBridge_h

#import "UnityUtils.h"
#import "UnityAppController.h"
#import "UnityInterface.h"

#endif /* UnityBridge_h */

3、添加Unity操作类 UnityUtils

如果iOS需要与Unity进行通信操作,则创建UnityUtils类。

UnityUtils.h

#ifndef UnityUtils_h
#define UnityUtils_h

void unity_init(int argc, char *argv[]);

// 下面是Unity与iOS通信的方法
void unity_finish();

void unity_cachelist();

void unity_set();

void unity_help();

void unity_loading_complete(char * _api);

void unity_loading_failure(char * _path);

void unity_screenshot(char * _path);

void unity_scaned(char * _path);

#endif

UnityUtils.mm

#include "RegisterMonoModules.h"
#include "RegisterFeatures.h"
#include 

static const int constsection = 0;
void UnityInitTrampoline();

extern "C" void unity_init(int argc, char* argv[])
{
    @autoreleasepool
    {
        UnityInitTrampoline();

        UnityInitRuntime(argc, argv);

        RegisterMonoModules();
        NSLog(@"-> registered mono modules %p\n", &constsection);
        RegisterFeatures();

        std::signal(SIGPIPE, SIG_IGN);
    }
}

// 根据需要实现unity方法
extern "C" {

    void unity_set() {
        
    }

    void unity_help() {
        
    }

    void unity_cachelist() {
        
    }

    void unity_finish() {
        
    }

    void unity_loading_complete(char * api) {
        
    }

    void unity_loading_failure(char * _path) {
        
    }

    void unity_screenshot(char * _path) {
        
    }

    void unity_scaned(char * _path) {
        
    }
    
}

4、修改 main.mm文件

引入 #import

//int main(int argc, char* argv[])
//{
//    @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();
        UnityInitRuntime(argc, argv);

        RegisterMonoModules();
        RegisterFeatures();

        std::signal(SIGPIPE, SIG_IGN);
        UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String:AppControllerClassName]);
    }
    return 0;
}

5、修改 UnityAppController.h 文件

引入 #import

// 注释掉inline
//inline UnityAppController*    GetAppController()
//{
//    return (UnityAppController*)[UIApplication sharedApplication].delegate;
//}
//   添加如下代码
NS_INLINE UnityAppController* GetAppController()
{
    NSObject* delegate = [UIApplication sharedApplication].delegate;
    UnityAppController* currentUnityController = (UnityAppController *)[delegate valueForKey:@"currentUnityController"];
    return currentUnityController;
}

此处获取 currentUnityController 时,运行时会报 valueForUndefinedKey 的错误。
解决方法: 在 AppDelegate 中定义的 var currentUnityController: UnityAppController? 前添加 @objc

6、修改 UnityAppController.mm 文件

将EasyARAppController.mm 中的如下代码复制到 UnityAppController.mm 文件中

extern "C" void ezarUnitySetGraphicsDevice(void* device, int deviceType, int eventType);
extern "C" void ezarUnityRenderEvent(int marker);
B0928B1C-542B-41F3-A1A4-7ABC5A911523.png
A03F0715-73D9-45EC-ACBD-5F07F2C84ED6.png

7、添加 main.swift 文件

//  Copyright © 2018年 Ping. 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))

8、导入所需的Framework

5514914B-E814-4602-A0B8-A4FECD1FE24B.png

8、修改项目中的 AppDelegate.swift

//  Copyright © 2018年 Ping. All rights reserved.
//

import UIKit

// 注释掉此句
//@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    @objc var currentUnityController: UnityAppController?
    var window: UIWindow?

    var isUnityRunning = false
    var application: UIApplication?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        self.application = application
        custom_unity_init(CommandLine.argc, CommandLine.unsafeArgv)
        currentUnityController = UnityAppController()
        currentUnityController?.application(application, didFinishLaunchingWithOptions: launchOptions)
        
        // 第一次调用启动Unity会做一些初始化的东西,所以只需在这里调用它并直接再次停止它
        startUnity()
        stopUnity()

        window = UIWindow(frame: UIScreen.main.bounds)
        window?.backgroundColor = UIColor.white
        window?.rootViewController = ViewController()

        window?.makeKeyAndVisible()
        
        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // 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.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
        if isUnityRunning {
            currentUnityController?.applicationWillResignActive(application)
        }
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // 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.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
        if isUnityRunning {
            currentUnityController?.applicationDidEnterBackground(application)
        }
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // 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.
        if isUnityRunning {
            currentUnityController?.applicationWillEnterForeground(application)
        }
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // 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.
        if isUnityRunning {
            currentUnityController?.applicationDidBecomeActive(application)
        }
    }

    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        if isUnityRunning {
            currentUnityController?.applicationWillTerminate(application)
        }
    }
    
    func startUnity() {
        if !isUnityRunning {
            isUnityRunning = true
            currentUnityController?.applicationDidBecomeActive(application!)
        }
    }
    
    func stopUnity() {
        if isUnityRunning {
            currentUnityController?.applicationWillResignActive(application!)
            isUnityRunning = false
        }
    }

}

遇到的问题

1、接入EasyAR后出现黑屏问题

我遇到的是遇到 Error: Invalid Key or Bundle ID,查看项目的Bundle ID和Unity3d的Bundle ID是否一致,将项目的Bundle ID修改为Unity3D的Bundle ID,就能解决问题

目前就这些,如再遇到问题再补充。

你可能感兴趣的:(swift 4 整合导入Unity3d项目)