Unity3d的ios插件开发

戴维营教育原创文章,转载请注明出处。我们的梦想是做最好的iOS开发培训!

Unity3D是一个非常强大的跨平台游戏引擎,但还是也免不了需要访问平台本身的一些功能。Unity3D并没有将平台方方面面都创建对应的API,尤其是比较新的一些功能。这时需要我们自己编写本地插件来解决,本文主要介绍如何开发Unity3D的iOS本地相册插件GlobalBrowser(能够自动扫描Documents目录,并且使用照片墙展示,其中展示功能使用了一个Objective-C的开源控件MWPhotoBrowser)。

准备工作

本文使用Unity 5和Xcode 6.2进行开发,目前只有Unity 4.6和Unity 5支持arm64,并且只有Unity 5支持在插件中使用子目录。我们有三种使用Objective-C代码的方式:源码、静态库(.a)和框架(iOS 8),这一次我们选择纯源码的方式。

本地代码编写

1、新建iOS的项目PhotoBrowser,在项目目录下创建Library文件夹。

2、将MWPhotoBrowser以及所使用的其它开源代码复制到Library,并添加到Xcode项目中。

3、创建GlobalBrowser目录,然后创建DVIGlobalBrowser类。我们在这个类中实现图片浏览插件的本地代码。为了简单起见,我们只实现了几个类方法,然后使用一个静态变量保存对象。

#import <Foundation/Foundation.h>

@interface DVIGlobalBrowser : NSObject
+ (void)show;
+ (void)dismiss;
@end

/////////////实现代码////////////////////////

#import "DVIGlobalBrowser.h"

#import <UIKit/UIKit.h>

#import "MWPhotoBrowser.h"
#import "MWPhoto.h"

static DVIGlobalBrowser *sharedInstance = nil;

@interface DVIGlobalBrowser () <MWPhotoBrowserDelegate>
{
    NSArray *_photosArray;
    NSString *_photoDir;
}
@property (nonatomic, strong) MWPhotoBrowser *photoBrowser;
@end

@implementation DVIGlobalBrowser

+ (void)initialize {
    sharedInstance = [[DVIGlobalBrowser alloc] init];
    sharedInstance.photoBrowser = [[MWPhotoBrowser alloc] initWithDelegate:sharedInstance];
    sharedInstance.photoBrowser.displayActionButton = YES;
    sharedInstance.photoBrowser.displayNavArrows = YES;
    sharedInstance.photoBrowser.displaySelectionButtons = NO;
    sharedInstance.photoBrowser.alwaysShowControls = NO;
    sharedInstance.photoBrowser.zoomPhotosToFill = YES;
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0
    sharedInstance.photoBrowser.wantsFullScreenLayout = YES;
#endif
    sharedInstance.photoBrowser.enableGrid = YES;
    sharedInstance.photoBrowser.startOnGrid = YES;
    sharedInstance.photoBrowser.enableSwipeToDismiss = YES;
//    [sharedInstance.photoBrowser setCurrentPhotoIndex:0];
}

+ (void)show {
    [sharedInstance loadPhotos];

    UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:sharedInstance.photoBrowser];
    nc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;

    UIWindow *appWin = [UIApplication sharedApplication].keyWindow;
    [appWin.rootViewController presentViewController:nc animated:YES completion:nil];

    [sharedInstance.photoBrowser reloadData];
}

+ (void)dismiss {
    [sharedInstance.photoBrowser dismissViewControllerAnimated:YES completion:nil];
}

- (void)loadPhotos {
    if (_photoDir == nil) {
        _photoDir = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];

    }
    NSArray *array = [[NSFileManager defaultManager] subpathsAtPath:_photoDir];

    _photosArray = array;
}

- (NSUInteger)numberOfPhotosInPhotoBrowser:(MWPhotoBrowser *)photoBrowser {
    return _photosArray.count;
}

- (id <MWPhoto>)photoBrowser:(MWPhotoBrowser *)photoBrowser photoAtIndex:(NSUInteger)index {
    NSString *filename = _photosArray[index];
    NSString *path = [_photoDir stringByAppendingPathComponent:filename];

    MWPhoto *photo = [MWPhoto photoWithURL:[NSURL fileURLWithPath:path]];
    return photo;
}

- (id <MWPhoto>)photoBrowser:(MWPhotoBrowser *)photoBrowser thumbPhotoAtIndex:(NSUInteger)index {
    NSString *filename = _photosArray[index];
    NSString *path = [_photoDir stringByAppendingPathComponent:filename];

    MWPhoto *photo = [MWPhoto photoWithURL:[NSURL fileURLWithPath:path]];
    return photo;}

@end

4、由于Unity3D那边只支持C/C++的函数,我们需要再进一步封装上面的代码,并且用extern "C"导出必要的函数。

//.h文件中
extern "C" void showPhotoBrowser(void);

//.m文件中
void showPhotoBrowser(void) {
    [DVIGlobalBrowser show];
}

void dismissPhotoBrowser(void) {
    [DVIGlobalBrowser dismiss];
}

5、在iOS项目中测试DVIGlobalBrowser

接口代码编写

在Unity3d中调用Objective-C代码,最终要的是编写C#的接口。在GlobalBrowser文件夹中创建C#接口文件PhotoBrowser.cs。

public class PhotoBrowser  {
    //引入C语言中的函数
    [DllImport ("__Internal")]
    private static extern void showPhotoBrowser();

    //暴露给C#的函数
    public static void showPhotoBrowserEx() {
        //平台判断
        if (Application.platform == RuntimePlatform.IPhonePlayer) {
            showPhotoBrowser();     
        }
    }
}

测试项目

在Unity3d的一个场景中加入按钮。没有使用过截屏功能的,需要注意存储路径。

using UnityEngine;
using System.Collections;

public class MyFile : MonoBehaviour {

    // Use this for initialization
    void Start () {
//      print ("Start...");
    }

    // Update is called once per frame
    void Update () {
//      print ("Update...");
    }

    void OnGUI () {
//      print ("onGUI...");

        //创建按钮,用来显示相册
        if (GUI.Button (new Rect (100, 100, 100, 100), "Button")) {
            PhotoBrowser.showPhotoBrowserEx();
        }

        //创建截屏按钮
        if (GUI.Button(new Rect(100, 220, 100, 100), "Save")) {
            var savePath = Application.persistentDataPath + "/" + (Random.value * 100) + "image.png";

            print (savePath + "<--->Capture");

            //截屏并保存图片到Documents目录
            Application.CaptureScreenshot((Random.value * 100) + "image.png");
        }
    }
}

本文档由长沙戴维营教育整理。

戴维营学院(高级开发视频): http://v.diveinedu.com

潜心俱乐部(iOS面试必备): http://divein.club