2015年个人工作总结

      2015年,对于我是很关键的一年,因为我离开研发团队1年零8个月后,又回归了。 同时也结束了外企优雅的工作生涯,加入到一个Unity3D的手游创业的小团队中,继续日常8小时的编程工作–自学和职业还是不一样的,职业接触的面不一定广、但是对技能要求的深一些。

     另外,自从2013年开始,个人技术博客网站走过了2013、2014、2015三个年头,这个网站也是象征我从传统IT行业往互联网行业转型的心路缩影,对了,现在互联网叫互联网+了。

    还有,研发管理经验是不分行业的,无论做电信行业OSS研发,还是Unity3D手游研发,靠谱的Team Leader都是一样的:他不能为公司挣钱,但是能够为公司省钱—每保质保量的完成一个项目,节约1个月时间,会节约7.5万人民币(1.5万/人月 *5 人)。 尤其在创业公司,不仅仅是钱的问题,靠谱还能够为公司赢得创业最宝贵的竞争力:时间。 例如,8月份发布产品,比11月发布产品,看起来3个月,对于大公司而言差别不大(1、2个合同订单的事情),但是对小公司而言,则很可能会决定公司的生死存亡!

而做好Team Leader这个岗位,可归纳为如下的要点:

不要求Team Leader:

  1. 技能牛B
  2. 长得帅
  3. 性情平和

要求Team Leader:

  1. 组织动员能力强
  2. 责任心强
  3. 谦虚的学习和反省能力强
    吐槽一下;

     

    1  创业公司的合伙人制度决定了公司的成败! 一般而言,选择大学同学、较熟悉的同事,则成功的概率高(有共同的理念和做事原则的默契度)。

    2  网上凑人未经过严格考核的“试用期”、10年不见的发小、传说中幼儿园同学关系,这些合伙人“组成”的创业公司大多会生死未卜!(开公司不是玩过家家的事情)

    3 原因很简单:嘴上说的,仅占50%,能不能和得来,得靠“试用期”— 先磨合3个月,试试看嘛!

    例如我曾经招聘过的一个程序员,其简历上吹NB,做过5个大项目,仅工作5年,貌似已经精通C#、C++,管理团队超过10人+….., 我K,项目目前正缺这样的人才–将才,好像是老天爷赐给你的似的; 给其争取到offer后,入职,在一起工作了1个月,才发现人才水的厉害,真的不是我嫉贤妒能呀,后来在试用期内不得不“挥泪斩马谡–辞退掉”— 我良心上也不安,寝夜难眠,但是为了团队大局利益考虑,砍!

    2015年的个人“大事记”:

    • 2015年1月:第三次系统学习Unity3D编程技术,体验了500元在线教育,效果–酷。
    • 2015年4月:赴北京参加Unite Beging 2015大会–游学、交友、自省
    • 2015年5月:最后一次参与组织技术大会 开源中国.西安
    • 2015年6月:入职西安**(一个创业仅3个月的棋牌手游公司),做全职Unity3D职业程序员
    • 2015年7月:荣获微软.NET MVP 2015
    • 2015年8月:系统自学Android开发,并和Unity3D完美应用,完成了多个插件模块接入
    • 2015年9月:公司岗位小调整,我“擢升”研发的Team Leader,同时兼任Unity3D程序
    • 2015年10月:VR/AR见闻(4月份黑人类社区上线;2015.10月份西安高调举行AWE Asia大会)
    • 2015年11月:系统自学IOS开发,并发布Unity3D在MAC下的ipa版本,完成Unity3D的跨平台实践

    2015年,博客写了30+篇

    今年博客网址(www.xifarm.com, www.codepiao.com)已经满2岁了,累计总发布博客112篇。

    2015年,书读了12本吧,有据可考的2015年书单如下:

    • 《iOS编程(第4版) 》  读完,并在11月份实践1.5个月。
    • 《Android 编程》 读完,并在8月份实践
    • 《小狗钱钱》本来是给儿子购买的,结果我自己悄悄先看完了。
    • 《火星救援》小说,电影当时还未来得及看,故看的Kindle的电子书。
    • 《游戏改变世界 》游戏行业一本重要的哲学书籍,游戏不仅仅是玩物丧志的事物。
    • 《Unity 2D游戏开发从入门到精通 》  2D游戏必备书籍
    • 《Sun 公司核心技术丛书:Effective Java中文版(第2版) 》 JAVA程序员必备
    • 《安德的影子》、《安德的代言》、《安德的游戏》 科幻三部曲
    • 《幽灵舰队 》 科幻小说大作
    • 《时间移民》 ,《三体》拿到雨果奖后,我看的又一部大刘的科幻小说。呵呵,我还抢注了“执剑人”的域名www.zhijianren.com
    • 《通关!游戏设计之道 》 雨松朋友圈推荐过的一本游戏设计的书,写得不错。
    • 《NGUI 实战教程》: NGUI未商用过,但是这本书,写得真好–有内容,的确是干货一本。

    历年个人工作总结链接:

    2013年总结
    2014年总结

    2016年个人的愿景:

    继续从事靠谱的Unity3D技术研发工作。

    在做好手游日常工作的同时,业余时间也会涉猎VR、AR技术的预研:demo。

    同时,会参加Unite Shanghai 2016大会–继续和全国的大牛们学习、交流、切磋。

    Unity3D项目实战笔记(12):手游优化之异步策略

         前面曾提到过《prefab的插件方式》,结果大量使用prefab,导致几个重要的prefab非常重! 也导致了游戏加载“卡顿”,一点点分析得知,是因为Resource.Load(*.prefab)导致的,对于框架的Prefab,把他做的很大,实在不是什么好主意的:一级界面在prefab上即可,点击二级界面在动态加载,即大prefab化小,以减少用户体验明显的“卡顿”现象。

        我的实践如下:

    Step1:优先采用协成

    private IEnumerator FinishProcessBar()

    {

    //Step1: 100%进度条

    finish = true;

    //Step2: 停止0.2s

    yield return new WaitForSeconds(0.2f); //在100%进度条上,停止0.2f

    //Step3: 切换页面

    Controller.Get().PushNext();

    }

    但是有问题,仅仅这个方法是无法解决问题的,因为:

    Coroutines aren’t async whatsoever – they’re completely synchronous with the main unity thread。

    Coroutines 往往是主线程里面的,无法实现C#中的多线程效果。

    Step2:查Unity自带的函数  Resources.LoadAsync

    Unity4.5.3 新增的函数,可以动态异步加载资源,如prefab、大图片、声音文件等,使用也很简单。

    req = Resources.LoadAsync("/Prefabs/Func1");

    yield return req;

    LLWindow = (GameObject)GameObject.Instantiate(req.asset); //5s

    LLWindow.SetActive(false);

    这里结合了协成和系统异步加载函数,完美解决问题.

    类似的方案, AB也采用了– AssetBundle.LoadAssetAsync

    还可以异步加载场景—Application.LoadLevelAsync

     

    Step3: 异步策略后,善后的事情

    我在prefab的Enable函数中,多次用到了GC.Collect函数,希望尽快让Mono.NET及时回收不用的内存,但是这个却会导致手游卡顿现象–在红米测试机上体验,故得删除之:

    GC.Collect(); 频繁调用,启动会导致程序"卡顿"

     

    另外,“启动黑屏2~3s”问题:

    打包Android APK包的时候,选择Script debuging、profiler、Development Build模式,也会导致启动“卡顿”,且包会增大2M ==》 调试完毕后后,及时记得去掉这些选项。

    最重要的,一定要有一个打包的文件夹,开发的和打包时2份不同代码,也省的每次切换配置可能导致的这种手误错误。

    Unity3D项目实战笔记(11):Unity 2D会用到的知识点小结

         全职编程Unity 2D手游已8个月了,已经上线了1款,还有1款正在研发中,预计1月中旬上线,这里小结2015年做的2D手游棋牌项目部分2D知识点。

    (考虑到我是研发,故这里仅列出了用到的知识点,不会涉及公司研发的细节–毕竟签署过保密协议的,呵呵.)

    image  Unity3D项目实战笔记(11):Unity 2D会用到的知识点小结 image thumb1

     

    注:服务器用的是商业化比较不错的SmartFoxServer、JAVA、MySql搞的,稳定性非常不错。

     

    • UI: 一般考虑UI布局,可使用TK2D、NGUI或者UGUI的解决方案,经验是不要混合使用。 这3种UI方案,均提供UI auto layout的; 另外,字体也是UI的重点考虑要素,有ttf动态字体方案和bmfont图片字方案,不考虑特色特色方案情况下,ttf一般不用过多考虑—用Unity做的手游,输入文字、输入数字是很蛋疼的事情,故动态字体绝对是鸡肋功能,使用概率非常非常低。
    • 物理: Unity从4.6开始加大了对原生2D的支持,故提供了2D特有的组件,主要是物理组件。如Collider 2D,Rigibody 2D, Joint 2D等。
    • 动画: 2D下的动画主要是用多张图片做帧动画,例如牌型动画。 也有一些特殊需求是骨骼动画–例如人物动画。 TK2D和UGUI提供的帧动画,非常简洁。
    • Sprite: 中文翻译为精灵,也就是图片;这个是2D中除了UI外最重要的界面元素了,一般有九宫格的切图需求,还有就是可采用TexturePackager进行图集打包压缩。
    • Advance: 项目进行过程中,对于有项目实战经验而言,有些事情要提前考虑和布局了,如AssetBundle的应用–涉及到服务器设计架构,以及粒子和shader的应用。 另外在项目的中期要考虑手游的优化–以k为文件大小的优化apk包大小。这里吐槽一个事情,Unity5.*开始,Android下默认支持X86和Arm架构,导致空包有18M大小,但是国内很少有Android的X86设备–据说小米平板是,故为了减少包大小,方便运营推广裁剪了X86版本,缩小了8MAndroid apk文件大小。
    • 公共规范:和具体编程关系不大,但是决定了团队合作的默契度。 项目的组织,规范好文件和文件夹是非常重要的事情,能提高沟通效率。另外在和美术团队沟通的时候,定好约束,如960*640 2D横板的美术标准。因为2D上,Unity已经很强大了,这里也引入了一些第三方插件—DOTween、VP_Timer、PoolManager。

          学习Unity2D知识,都知道和能够上线一款产品,差距还有有的,要不,一般公司招聘会特别标明–成功上线一款手游的实际开发经验呢。

     

    手游推广:  扫描二维码,下载《坑王争霸》手机版(Android、IOS):

    http://www.pgyer.com/wakeng

    image  Unity3D项目实战笔记(11):Unity 2D会用到的知识点小结 image thumb2 image  Unity3D项目实战笔记(11):Unity 2D会用到的知识点小结 image thumb3

    谢谢大家下载支持,指教的和报bug的,请QQ联系我:21372550。

    Unity3D左右出击:Unity 2D新功能发布会、Unity VR大师课程

       做为Unity3D技术的从业者, 非常关注一举一动—Unity3D大中华区. 如自从11月中到12月中,短短的1个月时间,对于Unity3D大中华区, 发生3件大事, 可以说算是三把火:

     

    11.23日 唐嘉隆任Unity大中华区总经理

           这种重大的人士变迁,对外企大公司而言,应该是内部有了一些“地震”了,要不中国这边的boss都换了。据说国内手游、VR市场火热,2015年Unity已经有2名内部骨干出去创业,或者加入创业公司了。 全球450万Unity程序员,中国占了40%,热火程度可见一斑。

           新的干部队伍应该会有较大的作为的。目前看已经稳住阵脚了,以方便我等广大的Unity程序员们的心里:减少内耗、服务好开发者先。

     

    12.15日  Unity VR大师课程

             从资本、技术角度看,VR、AR是未来5年的战略制高点,这一点Unity非常清楚,自从5.2开始,Unity已经支持了全球4个重要的VR硬件头盔–原生支持;这次举行VR聚会,将会进一步增强Unity在VR行业的领头羊角色。 目前全球跨平台开发VR的IDE工具,Unity占了约70%,另外的对手主要是虚幻引擎,这次Unity在北京开会,有主动求战的意味,毕竟牛B的虚幻在国内行事低调的多。

              看好Unity在VR、AR领域的领头羊角色:跨平台、免费、Android、PC、IOS多平台快速demo原型。

     

    12.17日 Unity 2D新功能发布会

              尽管Unity以3D著名–其Unity3D.com网站为公司官网的。但是在手游时代—包括2015年,主要的手游还是以2D为主,据说手机上3D手游开始看起来很酷,但是巨大的耗电量\发热\玩时间长了晕等硬伤, 只能是手游的一个宣传噱头,很多公司是2D\2.5D为主的—我了解的.  而在2D上,Unity在4.*前无原生的2D支撑,一般依赖第三方插件,如TK2D

               2D手游,Unity的劲敌为触控科技的 cocos2d x。  本次高调举行Unity2D新功能发布会,属于和cocos2d x 主动求战PK,以弥补2D的先天不足。

     

    • 做2D手游,首选 cocos2d x, 然后是Unity 2D
    • 做3D手游,首选Unity3D,然后是虚幻引擎
    • 做VR技术,首选Unity3D,然后是虚幻引擎

    故,如此对比,cocos2d x必然要逊色不少,而Unity3D固然问题很多,但是却是2D、3D、VR技术全栈也,有利于一个靠谱程序员的更长的生命周期—不用频繁更换技术架构和技术知识储备了。

     

     

    小结一下,我的Unity技术栈,如图所示:

    image  Unity3D左右出击:Unity 2D新功能发布会、Unity VR大师课程 image thumb

    1. Unity3D技术: 2013.6月份开始了业余了解Unity,做demo,翻译了14篇Unity技术文章
    2. Unity2D技术: 2015.6月份开始了全职Unity程序员,做的是2D棋牌手游。
    3. Unity VR技术: 计划2016年业余玩玩,前几天采购的暴风魔镜4 预计春节前能到货。

    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新人

                                  Unity3D项目实战笔记(5):延时功能的几种实现

                                  我所做过的系统,分单机版系统(2005年)、CS系统(2010年)、实时系统(2015年),各个系统均有“延时”功能:定时调度的; 本博客说的是实时系统中的延时功能(基于Unity3D游戏引擎)。

                                  image  Unity3D项目实战笔记(5):延时功能的几种实现 image thumb3

                                   

                                  在Unity3D中,新建的脚本会默认继承MonoBehaviour,其中Update函数会被引擎自动调度,如在我的电脑上,Update函数被调用的周期为0.012s。

                                  那么Unity3D中,仅有通过Update函数来实现延时功能吗?  还有无其他的实现呢?

                                  怎么才能让一个界面只显示1秒之后 然后再执行其他的操作~

                                  比如 游戏的胜利界面 只让他显示一秒 然后执行其他操作

                                   

                                  答案是有的,下面就用过的几种延时功能(定时器)一一列出来:

                                  延时功能

                                  是否继承MonoBehaviour

                                  备注

                                  Update函数

                                  配合使用的函数:

                                  Timer.timer

                                  Invoke

                                  配合使用的函数:

                                  CancelInvoke

                                  InvokeRepeating

                                  IsInvoking

                                  Coroutine

                                  配合使用的函数:

                                  StartCoroutine

                                  StopAllCoroutines

                                  StopCoroutine

                                  DOTween (HOTween v2)

                                  Assetstore 商业授权

                                  VisionTimer.VP_Timer

                                  Assetstore 商业授权

                                   

                                  下面的几个例子,我们在ShowA函数中,延时5s调用ShowB函数,通过代码看看各个实现方法的异同。

                                  为了方便,我仅截取部分关键代码,是否继承MonoBehaviour等自行添加即可。

                                   

                                  • Update函数 实现定时器

                                    float m_timer = 0;
                                        void Update ()
                                        {
                                            m_timer += Time.time;
                                            if (m_timer >= 5)
                                            {
                                                ShowB();

                                                m_timer = 0;
                                            }

                                        }
                                       
                                        private void ShowB()
                                        {

                                        }

                                    Update函数实现定时器,几乎是学习Unity3D必修的功课。 但是,在实战项目中需要维护m_timer这个变量,且从设计角度看,代码写得有些不整齐。

                                   

                                  • Invoke函数 实现定时器

                                    GameController.Get().CancelInvoke();

                                    GameController.Get().Invoke("ShowB", 5f);

                                    private void ShowB()

                                    {

                                    game.ShowCardInTurn();

                                    }

                                    Invoke是MonoBehaviour提供的函数,可以延时调用函数,且可以通过CancelInvoke控制调度器的停止。 但是,Invoke的调用是在运行时生效的,对于ShowB函数,很容易导致在代码审查阶段被误杀—函数删除后,编译不会报错,你可能会误认为这个函数是废弃的函数。

                                   

                                  • Coroutine 协成 实现定时器

                                    private IEnumerator ShowA()
                                        {
                                            yield return new WaitForSeconds(5);

                                            ShowB();
                                        }
                                       
                                        private void ShowB()
                                        {

                                        }

                                    使用协成的WaitForSeconds可以实现定时器,使用起来比较简单。

                                   

                                  • DOTween 实现定时器

                                    DOTween动画插件,是在Unity 4.6时代,为了弥补UGUI无动画脚本的先天不足而云起的商业插件,当然雨松MoMO的《UGUI研究院之界面中使用DoTween(七)》对普及DOTWeen功不可没。

                                  private void ShowA()
                                      {
                                          GameObject go;

                                          go.transform.DOMoveZ(0.1f, 5f)
                                              .OnComplete(new TweenCallback(ShowB));
                                      }
                                     
                                      private void ShowB()
                                      {

                                      }

                                  DOTween的主要作用不是为了做延时调度用的,但是其带有这个功能,且思想非常酷。

                                   

                                  • VP_Timer 实现定时器

                                    vp_Timer.Handle Timer = new vp_Timer.Handle();

                                    vp_Timer.In(5, new vp_Timer.Callback(() =>

                                    {

                                    Timer.Cancel();

                                    ShowB();

                                    }), Timer);

                                    VP_Timer是某天下午,在网上搜索中,无意找到了,其简洁的用法,着实让人眼前一亮。 目前项目中,涉及的地方超过10处,极大的方便了延时功能的实现,非常不错。 也为项目节约了大量的时间。

                                    谢谢给我普及这个插件的博主啦: 《Unity时钟定时器插件——Vision Timer源码分析之一》。

                                      上面的几种方法,在实战Unity3D项目中,均有所涉及,我本人用的比较多的是DOTWeen和VP_Timer,这2个不依赖继承MonoBehaviour,相对比较灵活,且其是商业项目,封装还是挺给力的。

                                      如果大家还有其他实现方法,也欢迎分享,我们共同提高、进步。