Unity3D项目实战笔记(10):Unity3D编译IPA的PostEvents–节约时间利器

      最近,SDK支付等接入差不多了,就从Unity3D生成IPA (企业版License), 然,需要手动执行的PostEvents竟然多大10项+, 这些我默默的承受了1周时间,每次约浪费20分钟-额外的。

     周末用了2天时间,研究一下官方的例子和雨松的相关博客2篇,总算是搞定了这件事情,开心!

 

痛苦的前传:

Unity3D导出为XCode工程后,有如下任务需要做

Plist 文件中

    <key>CFBundleDevelopmentRegion</key> 中文

    <string>zh_CN</string>

    <key>CFBundleIdentifier</key> AppID

    <string>com.aaa.${PRODUCT_NAME}</string>

    <key>CFBundleShortVersionString</key> 版

    <string>1.0</string>

    <key></key> 白名单

    <array>

    <string>weixin</string>

    </array>

    URL Schema

Build Setting

    证书

    FrameWorks

    Header search

AppDelegate文件:

      #import header.h

      DoFinish

      OpenURL

        开心的实践

               首先在Unity3D官方社区一番搜索、学习,大致明白要搞定这些繁琐的事情,我不是一个人在战斗,有很多国际友人也头疼于此,呵呵。

          有2个解决方案可供选择 :
          方案1: Unity3D官方的 开源的 XcodeAPIimage

        方案2: 社区火热的XUPorter 方案,连雨松都力挺(Unity3D研究院之IOS全自动编辑framework、plist、oc代码(六十七))。

        另外,通过源码分析,Unity Ads  竟然发指的用的是XUPorter方案的变种,而不是其官方力推的开源的XCodeAPI,这样好奇怪。
          这里我选择官方开源的XCodeAPI进行实践,同时结合雨松的灵感–XClass代码

              Step 1: 分析要做的目标

            我这里用了微信IOS支付、支付宝微信支付、调用IOS照相机、蒲公英 应用内测SDK,故要通过PostEvents完成之。

            需要修改PList文件
            需要修改Project BuildSettings文件
            需要在Unity3D生成的AppController文件修改 UnityAppController.mm

            image

                Step 2: 下载XCodeAPI

            https://bitbucket.org/Unity-Technologies/xcodeapi/src/ 下载,注册账号,或者点击左下角的Downloads。

                Step 3: 配置文件目录

            把XcodeAPi源码,放在Editor文件夹下

                Step 4: IOSPostBuildProcessor.cs 实现PostProcessBuild

            新建一个文件IOSPostBuildProcessor.cs ,添加[PostProcessBuild]标签函数

            [PostProcessBuild]
            public static void OnPostprocessBuild(BuildTarget buildTarget, string pathToBuiltProject)

               

                拷贝系统Framework:

              proj.AddFrameworkToProject(target, "StoreKit.framework", true);

                  添加头文件搜索–非递归方式

                proj.AddBuildProperty(target, "HEADER_SEARCH_PATHS", "$(SRCROOT)/Libraries/Plugins/iOS/AliPay/AliPaySDK/");

                    PList文件修改版本信息

                  rootDict.SetString("CFBundleDevelopmentRegion","China");  //change en=>chinese

                      PList文件添加微信为白名单

                    PlistElementArray array = rootDict.CreateArray("LSApplicationQueriesSchemes");
                            array.AddString("weixin");

                     

                    OpenURL添加
                    PlistElementArray array1 = rootDict.CreateArray("CFBundleURLTypes");
                    PlistElementDict dic = array1.AddDict();
                    dic.SetString("CFBundleTypeRole", "Editor");
                    dic.SetString("CFBundleURLName", "weixin");
                    PlistElementArray array2 = dic.CreateArray("CFBundleURLSchemes");
                    array2.AddString("wx666662196cb2222");  //weixin

                    读取UnityAppController.mm文件,谢谢雨松的启发–XClass 类库
                    XClass UnityAppController = new XClass(filePath + "/Classes/UnityAppController.mm");
                                   
                    //在指定代码后面增加一行代码: import "header.h"
                    UnityAppController.WriteBelow("#include \"PluginBase/AppDelegateListener.h\"","#import \"WeixinPayIOSWrap.h\" \r #import <AlipaySDK/AlipaySDK.h> \r #import <PgySDK/PgyManager.h>");

                        Step 5: 测试

                      现在执行Unity3D生成XCode工程,在生成XCode工程完成后,会自动调用Editor下面的[PostProcessBuild]标签,执行代码(可Debug调试)。

                                开心的总结:

                                     现在,我仅仅需要Unity3D导出为XCode工程,然后选择企业证书,即可:Product–Archive–export了。轻松了许多;代码虽然仅仅100多行,但是对工作的改进,的确能每次少浪费20分钟时间,这是一次极好的通过业余实践,改善工作流程,从而减少无效加班的事情,开心。 下次再见到雨松的话,好得请他喝一杯–大杯,谢谢XClass 源码。

                        Unity3D项目实战笔记(9):Unity3D接入IOS SDK技术预研

                        为了使得Unity3D的程序在IOS下运行,需要做一些SDK接入工作:如访问IOS系统照相机、如调用微信支付、支付宝支付等,故需要先做接入IOS SDK的预研工作,本文整理一下自己的学习心得,总结如下:

                         

                        Unity3D和IOS SDK交互,主要分2个步骤:

                        1 在Object C中,封装一个 extern “C”接口

                        2 然后,在C#通过 dllimport调用即可。

                         

                        下面通过3个例子,来一一实践:

                        例子1: 获取最大数字

                        Object C封装-CWraper.h

                        extern "C"
                        {
                            int GetMax (int left, int right);

                        }

                        Object C封装-CWraper.mm

                        int GetMax (int left, int right)
                        {
                            return left > right? left:right;
                        }

                         

                        Unity3D 封装:

                        [DllImport ("__Internal")]
                        private static extern int GetMax (int left, int right);

                         

                        例子2: 调用IOSAlert对话框

                        Object C封装:

                        extern "C"
                        {
                            const char* CallIOS_ALert(const char * msg);

                        }

                         

                        const char* CallIOS_ALert(const char * msg)
                        {

                            NSString * nsMsg = [NSString stringWithUTF8String: msg];
                            
                                    UIAlertView *alert = [[UIAlertView alloc] init];
                                    [alert setTitle:@"IOS程序世界"];
                                    [alert setMessage:nsMsg];
                                    [alert addButtonWithTitle:@"确定"];
                                    [alert  show];
                            
                            
                            return SafeStringBack("Main Camera");;
                        }

                         

                        Unity3D 封装:

                        [DllImport ("__Internal")]
                        private static extern string CallIOS_ALert (string msg);

                         

                        Object C的工具函数: Const Char* 和NSString转换的

                        //XCode的字符串转换为Unity字符串
                        const char* SafeStringBack(const char *inputMsg)
                        {
                            char* retC = (char*)malloc(strlen(inputMsg) + 1);
                            strcpy(retC, inputMsg);
                            return retC;
                        }

                        const char* SafeStringBack(NSString *inputMsg)
                        {
                            return SafeStringBack([inputMsg UTF8String]);
                        }

                         

                        例子3:Object C回调Unity3D

                        这里我们通过 UnitySendMessage来返回数据,稍微注意,字符串需要封装一下。

                                    const char* obj = SafeStringBack("Main Camera");
                                    const char* method = SafeStringBack("ShowXCodeMessage");
                                    const char* varVal = SafeStringBack("this is xcode.");
                                    UnitySendMessage(obj, method, varVal);

                        Unity3D中,需要有“Main Camera”的对象,以及有一个public的函数"ShowXCodeMessage"。

                         

                        自此,预研的事情搞定了,则其余的接入IOS SDK,则是看各个官方demo、文档,然后估计工作量的事情了。

                         

                        归纳:

                        Unity3D和IOS SDK交互,本质上上C#和Object C(C++)的PInvoke;源码层面的交互,相对Android的Jar包要简单一些—源码在手,了无秘密。

                         

                        备注:

                        1. Android的Unity3D交互博客链接: 《Unity3D项目实战笔记(4):Unity3D接入Android SDK
                        2. Object C如果编译不通过,请修改*.m文件为*.mm文件:Object C、C++混合编译方式
                        3. 一般在Unity导出的XCode工程下,写IOS Plugins,代码写完才可以编译ok。

                        Unity3D项目实战笔记(8):Object C语言 – “一瓶酿了30年陈年老酒

                           Objective-C或者Obj-C或OC,是根据C语言所衍生出来的语言,继承了C语言的特性,是扩充C的面向对象编程语言。  用于MAC App开发、IOS App开发,主要开发工具是MAC上的XCode IDE。

                         

                        下面简述一下Object C要点:

                        • 1983年, object-c诞生了,Objective-C可以认为是继承了C和Smalltalk优点。
                        • 1996年,苹果公司以4亿美金收购了NeXT,NeXTSTEP被重命名为Cocoa因为Mac OS X、iPhone SDK、Xcode可追 溯到NeXT、NeXTStep,所以是以Objective-C为主力开发语言,所以程式码中会出现NX***与NS***字样
                        • 目前使用Objective-C 2.0为开发语言,使用Xcode 7作为集成开发环境
                        • OC有一套预定义的类和类型比如NSNumber,NSstring,NSdate等。NSObject是一个根类(类似C#的Object)
                        • 子类 :父类

                          @interface MyObject : NSObject
                          @end

                          C++中:
                          class MyObject : public NSObject{
                          };

                          备注:类声明以 @interface 类名:继承类 开头,以 @end 结尾,类实现以@implementation 类名 开头,以 @end 结尾

                        • NSLog相当于printf() 
                               NSLog(@"hello Objective-C");
                        • 类方法和实例方法,加号表示类方法,类方法可以直接调用,而不用创建实例(C# static方法);减号表示实例方法,需要创建这个类的实例对象才可以调用

                          中括号可以认为是如何调用你刚才写的这个方法,通常在Objective-C里说“消息”。 
                           
                          this.hello(true);   //C#
                          [self hello:YES];   //Objective-C

                               OC中所有对象都是指针的形式。

                        • OC用self代替this。
                        • OC使用id代替void*
                        • OC使用nil表示NULL
                        • OC只支持单继承
                        • OC使用YES/NO表示TRUE/FALSE
                        • OC使用#import代替#include
                        • OC的用户界面是XIB文件,一个XML封装的UI
                            归档存储:(沙河路径)

                          方法1:NSKeyedArchiver、NSKeyedUnArchiver

                          方法2:CoreData
                            常用数据结构:数组和字典
                            NSArray、NSMutableArray
                            NSDictionary、NSMutableDictionary
                              重绘触发函数:[self SetNeedDisplay]
                              Main函数:
                              入口路径:Main() –> UIApplication –> DidFinishLaunching (初始化函数地方)

                              //在Objective-C 2.0引入了属性合成,相当于之前的get/set方法 
                              @property (nonatomic, copy) NSString *caption; 
                              @property (nonatomic, copy) NSString *photographer;

                               

                              Object C单体(单例):

                              *.h文件

                              #import <Foundation/Foundation.h>

                              #import <UIKit/UIKit.h>

                              @interface BNRImageStore : NSObject

                              +(instancetype)sharedStore;

                              @end

                               

                              *.m 文件

                              #import "BNRImageStore.h"

                              #import "BNRItemStore.h"

                               

                              @interface BNRImageStore ()

                              @property(nonatomic, strong) NSMutableDictionary *dictionary;

                              @end

                               

                              @implementation BNRImageStore

                              +(instancetype)sharedStore

                              {

                              static BNRImageStore* sharedStore = nil;

                              static dispatch_once_t onceToken;

                              dispatch_once(&onceToken, ^{

                              sharedStore = [[self alloc]initPrivate];

                              });

                              // if (!sharedStore) {

                              // sharedStore = [[self alloc]initPrivate];

                              // }

                              return sharedStore;

                              }

                              -(instancetype)init

                              {

                              @throw [NSException exceptionWithName:@"Single" reason:@"use + [BNRImageStore sharedStore]" userInfo:nil];

                              return nil;

                              }

                              -(instancetype)initPrivate

                              {

                              self = [super init];

                              if (self) {

                              self.dictionary = [[NSMutableDictionary alloc]init];

                              //内存过低警告

                              NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

                              [nc addObserver:self selector:@selector(clearImages:)

                              name:UIApplicationDidReceiveMemoryWarningNotification

                              object:nil];

                              }

                              return self;

                              }

                               

                              *.m文件和*.mm文件区别

                              *.m文件是OC编程用的,*.mm文件是混合编程(OC\C++). 例如接入IOS支付的时候,针对一个编译问题:

                              很可能你是在混编文件(也就是.MM)里调用的CreateRSADataSigner方法

                              解决办法 就是DataSigner.m和DataVerifiler.m

                              把这两个类改为MM文件,C++和OC混编。

                               

                              参考材料:

                                *《IOS编程–第4版本》, Big Nerd Ranch Guides 的书,一向是很经典的,强烈推荐

                                * 拿XCode实战写代码,有5年编程经验的,大约写一周,就慢慢就感觉了 — 精通还得3月,呵呵。

                               

                              2014.6 Swift横空出世,且apple说2015年,Swift要开源。 故,Object C的未来,不好说。

                              以苹果的个性,说不定2年后,要求Apple Store上面的应用全部为Swift的,也说不定,呵呵。

                              Unity3D项目实战笔记(7):Texture材质的缩放源码 TextureScale

                              前几天,做一个功能,上传头像。

                              在项目中,有大头像和小头像这两种格式,故需要用到Texture缩放,我在Unity3D官网找了一下,找到了解决方案,非常简单,共享给大家。

                              原型代码:

                              message是Android或者IOS拍照后,返回的字符串:64位格式存储的png图片,已经剪裁为300*300了。

                              byte[] data = Convert.FromBase64String(message);

                              Texture2D texture = new Texture2D(0, 0);

                              texture.LoadImage(bytes);

                              texture.wrapMode = TextureWrapMode.Clamp;

                               

                              texture 是大图,现在要用小图,如何搞?

                              尝试1:

                              Texture2D 自带的Width、Height重新设置大小,然后Apply。

                              结果编译报错,Width和Height无法动态设置,故这个方案失败。

                               

                              尝试2:

                              Texture2D 自带的Resize方法,然后Apply。

                              结果是获得了要的小图像,但是不是缩放,而是莫名其妙的图片,故这个方案失败。

                               

                              尝试3(成功):

                              引入官方解决方案: TextureScale(含js源码和C#源码)

                               

                              TextureScale.Bilinear (texture , 100, 100);  //100*100大小

                              呈现,效果好极了,Cool。

                               

                              TextScale源码没有细究,应该是用到了矩阵变形等算法,使用这个类库,要注意如下约束:

                              1 texture可读写

                              2 ARGB32, RGB24 and Alpha8 textures

                              Unity3D项目实战笔记(6):Hello World, MAC.

                              做为一个Windows平台的老程序员,使用MAC的确挺奇特的:

                              • 精美的OS
                              • 别致的Mac Pro外表
                              • 别扭的OSX操作系统
                                使用MAC是带着既定工作目标的:

                                1 封装苹果内购支付—Object C插件

                                2 Unity打包XCode工程, 签名后导出IPA包

                                3 IPA包上传Apple Store

                               

                              面对这3件事情, 我拿到公司的MAC Pro后,做了个简单的计划:

                              第一步

                              2天

                              系统学习MAC电脑,熟悉快捷键,能开机,关机,上网。。。

                              第二步

                              7天

                              较系统学习Objec C语法;以及IOS编程

                              第三步

                              5天

                              接入苹果内购、IPA发布 (证书、审核不算在内)

                               

                              开发了这么多年, 倒是第一次系统学习MAC电脑, 简单小结如下:

                              • MAC是全球第二大操作系统Macintosh的电脑,目前算是个人电脑高端代表,也是外出演讲装B必备神器
                              • MAC系统独立于Windows的兼容性:自己生产操作系统、自己生产硬件
                              • 程序员中常见的MAC电脑是MAC Pro电脑,类似当年的IBM ThinkPad T**电脑
                              • MAC电脑硬件收费,操作系统免费升级(较微软Windows战略高出一大截)
                              • MAC电脑, 主要开发工具XCode免费升级(较微软VS.Net战略高出一大截)
                              • XCode 最新版本是7.1,支持IOS8.1+开发,不用苹果开发者证书,也能真机部署了
                              • 苹果开发者证书分为2类:99美金、299美金。 前者能上Apple Store,后者在企业内分发
                              • XCode调试Iphone,非常爽,非常稳定,这一点较Eclipse调试Android强
                              • 国外有人说开发IOS较开发Android效率高20%,我估计和XCode完美调试IPhone贡献相关
                              • 使用MAC开发IOS应用,目前从市场看不仅仅收入高;而且包袱轻:IOS8.* +
                              • MAC Pro电脑的Touch Board非常棒,我打满分–既能触摸、也可取代一部分鼠标功能:缩放、翻页
                              • MAC电脑虽然贵,但是考虑到免费的操作系统和开发IDE,比Windows同样配置的高很多

                              小纪:

                              我大约是去年在看到苹果发布了Swift后,有意采购MAC电脑的,后来思绪再三,考虑到做Unity开发,VS是必备工具,而VS不支持MAC,故而未成。

                              儿子看到苹果电脑后, 第一感觉是:爸,这电脑挺好的, 为啥苹果被咬了一个口子呢?

                               

                              参考文献:

                              先有 Mac 还是先有钱?

                              开始使用Mac OS X——写给Mac新人