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  Unity3D项目实战笔记(10):Unity3D编译IPA的PostEvents&#8211;节约时间利器 image thumb

    方案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  Unity3D项目实战笔记(10):Unity3D编译IPA的PostEvents&#8211;节约时间利器 image thumb1
              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新人