Blog logoJustZht

Blog logo

2017.10.9

 • 

在家呆了几天,精神终于放松了些,慢慢也想通了些事情。
我一直没有认真去融入到大学生活里去,传统宣传口径下的国内大学生活无非是前三年青春年少和最后一年踏入社会,看起来朝气蓬勃,但那种所谓的被外界觉得青春年少的大学生活,对于我来说是一半太无聊一半太奢侈了。所以为了我最后一年能相对轻松地踏入社会,或者不如从一开始我就觉得社会比学校更有趣些,因此我前三年一直照着自己的路线做事情。
结果到了大四我突然发现,已经没有所谓体验踏入社会的机会了。学校课很多,马原毛概大四才上,再加上毕设等都是毕业的关键,我只能一直呆在学校里。而面试我的公司到后面一致问我什么时候有空去实习,我只能说学校这边事情较多去不了,然后几家公司都渐渐没了消息。至此我突然有种感觉自己虽然上了所大学,但是从来没有真正体验过所谓的大学生活,连实习找工作熟悉新生活这种大学生活的结尾都被迫狼狈地夹在各种学校的事物中匆匆结尾,周围的同学大部分找到一家不需要实习的公司就赶紧签了三方,然后生活照常继续。而我偶尔去上马原和毛概,把电脑放在腿上偷偷写自己的项目和外包,过着自己并不熟悉的要上课的生活。
而我想尝试新的机会,但现在是我性价比最低的时候:之前大二大三有大把时间翘课,能给实习工资做出来还不错的东西。而现在留在学校没时间去实习,最快入职也要等到毕业后,一入职就是应届生工资水平,很多公司宁愿要两个可以立刻入职拿较低的实习工资的人来代替我,一方面可以慢慢熟悉业务,另一方面大公司很多时候也并不需要一个设计和技术都吃一点的应届生,不像初创公司缺人,来一个又能做三维又能写代码的人很划算,大公司里拿我放哪里都尴尬。
明知这种状况下几乎没啥公司会要我,但之前我还是想去投各种公司,因为我总觉得,靠着之前所在公司的提前批 offer 就不参加其他招聘的话,就是连最后一年也这么安静地过去了,大学四年是真的没有体验过了,这种事情上我觉得还是需要些仪式感的,即使面试的公司到后来都没消息。

放松了点后我想通了些。既然都这个样子了,不如呆在学校写我的 Epoch,没有更好的选择的话就安心签之前公司的 offer,然后准备出国。至于我现在的这个大学,毕业了以后我是再也不想有关联了。

2017.9.19

 • 

学校的生产实习结束了。关于生产实习没什么好说的,就是用 python 写黑盒测试,每天要去市内一个培训班。闷热(不开空调),没网(意味着没 pip),外加没有 IDE 的一排电脑。
实习老师提供了一些基础的文档,自己遇到了一些文档没说的坑,不过都还好。后来带着自己的笔记本跑着 Windows 虚拟机过去写。怎么说我也是做工程向的,这种项目上相对其他同学总会有些优势,最后答辩也很顺利。
这期间面了一些公司,做了一些笔试。之前在百度的经历让我转正容易很多,我暂时能确定的也只有这个了,但我想去其他公司和其他城市看看,所以也没有停止投递。投了 Unity 的上海校招,不过没消息,估计是不符合吧。
越是面试越是在说项目经验的时候觉得自己最近产出的东西怎么这么匮乏,但学校的事情在可见的几个月内不会变少,同时我认识的一些朋友都在做非常有趣的事情,比如 AR Camera,比如 RSS Reader,让我有点羡慕别人。
因为忙着学校和校招,我自己的几个软件和游戏都没有进一步更新的计划。GitHub Contributions 的 ARKit 初步集成效果不是很好被我先暂停了。Cetacea 编辑器我想进行第三次重写,从 NSRegularExpression 改为 CMark,从基于 iCloud 的自定义 NSDocument 改为基于任意云平台的 plain text 储存,但开始时间未定。Epoch 的进展也就是加上了能在 runtime 用的云层,其余内容我也不知道何时有时间实现出来。这让我有一种自己停止生产内容的感觉,我多想一天到晚只写自己的东西啊。


和 Kevin 聊天的时候我说我想做 Art,不管是软件,游戏,还是 VFX,只要有我的风格我都想做。这让我的简历有点尴尬:我同时在做 Cocoa 和 Unity 这两个技术栈,写过点 Android 和 Rails。这导致我在每个平台上的深度都没有到面试官期望的程度,然后我还做过 UI Design,Adobe AE,MODO,Substance Painter 以及其他奇奇怪怪的东西,但这些对于技术面试并没有什么太大用处。
我的博客也是技术和生活混杂在一起的,虽然我一直以来都觉得挺好,毕竟本来就是自己的博客嘛,但面试的时候面试官想找我的技术文就会有些尴尬。不过我暂时没有分拆的想法,估计以后也不一定会有吧。

Epoch Dev Log 9

 • 

上一篇 Epoch Dev Log 还是去年九月。一年过去由于实习,其他项目,以及懒,Epoch 本身并没有进展多少,不过 Unity 引擎自身倒是多了很多功能,我得以突破之前的一些问题。
首先,Epoch 的云层终于加上了,不过现有的 Ray Marching 部分还是一个 Cube,我需要后面改为一个 Sphere 的表达式。其次,得益于 Instacing API,大规模的 SpeedTree 在没有物理(风速)的影响下是可以重新实现一遍了。

接下来要实现的是升级之前的 Noise Shader。之前的 Shader 实现是靠 C# 对 Shader SetFloatArray 插入了一个 Lookup Table,而在老版本的 Unity 部分是有这个长度限制的,因此当时的 Lookup Table 从 LibNoise 的 1024 压缩到了 768。但我的新实现将完全抛弃 Lookup Table,也尽量独立于 LibNoise 的做法,这样 HeightMap 生成时间会进一步缩短。
以及基于 DepthMap 的 Runtime Culling,这个之前看到过一些 Paper 有说过,据说 BattleField 4 也有一个小分辨率的 DepthMap 用来做这个事情。但我预计要做的肯定没那么复杂,就是在某个 Layer 上的所有 GameObject 依附的 Renderer 如果在相机的 Z 轴百分比大于 DepthMap 即设置为非活跃。不过这个做法有两个隐藏的担忧:1. Mesh 过多的话是不是每 Update 检测 Depth 消耗的时间会大于省去的时间 2. Depth 的 Float 精度对于 zMin = 0.1 zMax = 99999 的游戏是否足够。

UniOSIntegrationKit

 • 

UniOSIntegrationKit 是在做之前的一个外包的时候面临需求临时写的一些代码和脚本的集合。之前给 Unity 写 iOS 插件,基本上都是 Unity 为主包,iOS 代码放在 Plugins 文件夹内。但是如果有一个现成的 iOS 项目需要插入 Unity 部分,则问题就比较多了,主要有这几点:

  • Unity Xcode 工程是代码生成,每次都会覆盖
  • Unity Xcode 工程自身有一个 AppDelegate
  • 直接把 Unity Xcode 文件拖入 iOS Xcode 工程会导致结构特别乱

UniOSIntegrationKit 主要解决的是第一和第二个问题,即在不改动 Unity Xcode 生成工程的前提下,使用各类方法(Method-Swizzling,Build Script)在外部对 Unity 的行为进行改动,避免每次重新生成 Unity Xcode 工程的时候需要重新修改。
有关 iOS 和 Unity 项目如何接入可以去看 Integrating Unity3D with native iOS application for Xcode 7 & Unity 5,这里的很多思路都是从程序的方式上去把这个视频做的事情自动化地做一遍。

NSObject+UnitySwizzling 是用来做 Method-Swizzling 的,不过也包括了对于 UnityWindow 的操作。Unity 的 AppDelegate 称之为 UnityAppController,如果进入看可以发现 .mm 文件里有 didFinishLaunchingWithOptions 等 delegate 方法的实现。而 iOS 本身自己已经有了一个 AppDelegate 文件,则在保留 iOS 的文件同时要把 Delegate 事件(软件进入后台,软件即将结束等)传给 Unity,所以使用 Method-Swizzling,关于此可以看 nshipster.cn,这里就直接给代码了,作用是在 iOS 本身的 AppDelegate 实现里都加上发给 UnityAppController 的代码。

首先,把 iOS 工程自带的 main.mm 替换为 unity 自带的 main.mm,然后修改

const char* AppControllerClassName = "AppDelegate"; // iOS 工程自己的实现了 AppDelegate 的那个类的名字  

然后可以把 unity 的 main.mm 删除了,当然也可以直接删除 iOS 的 main.mm 修改 Unity 的,自己决定。

NSObject+UnitySwizzling.h

#import <Foundation/Foundation.h>
#import "AppDelegate.h"


@interface AppDelegate ()
@property(strong, nonatomic) UnityAppController *unityAppController;
@end

@interface AppDelegate (UnitySwizzling)

+ (NSMutableArray *)getUnityOriginalList;
+ (NSMutableArray *)getUnitySwizzlingList;
+ (NSMutableDictionary *)getUnitySwizzlingDict;

- (UIWindow *)getUnityWindow;
- (void)showUnityWindow;
- (void)hideUnityWindow;
@end

NSObject+UnitySwizzling.m

//
//  NSObject+UnitySwizzling.m
//
//  Created by Fincher Justin on 25/6/17.
//  Copyright © 2017年. All rights reserved.
//
#import <objc/runtime.h>
#import "NSObject+UnitySwizzling.h"


#import "AppDelegate.h"

#import "UnityAppController.h"
#import "UnityMessageCenter.h"


@implementation AppDelegate (UnitySwizzling)

+ (NSMutableArray *)getUnityOriginalList
{
    return [NSMutableArray arrayWithObjects:
            @"application:didFinishLaunchingWithOptions:",
            @"applicationWillResignActive:",
            @"applicationDidEnterBackground:",
            @"applicationWillEnterForeground:",
            @"applicationDidBecomeActive:",
            @"applicationWillTerminate:",
            nil];
}
+ (NSMutableArray *)getUnitySwizzlingList
{
    NSMutableArray *array = [[AppDelegate getUnityOriginalList] mutableCopy];
    for (int i = 0; i < [array count]; i ++)
    {
        NSString *originalString = (NSString *)[array objectAtIndex:i];
        NSString *swizzledString = [NSString stringWithFormat:@"xxx%@", originalString];
        [array replaceObjectAtIndex:i withObject:swizzledString];
    }
    return array;
}
+ (NSMutableDictionary *)getUnitySwizzlingDict
{
    return [NSMutableDictionary dictionaryWithObjects:
            [AppDelegate getUnitySwizzlingList]
                                              forKeys:
            [AppDelegate getUnityOriginalList]];
}

- (UIWindow *)getUnityWindow
{
    return UnityGetMainWindow();
}


- (void)showUnityWindow
{
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [[UnityMessageCenter sharedManager] runCommand:@"OnUniShow" WithParameter:@""];
        [[self getUnityWindow] makeKeyAndVisible];
    }];

}

- (void)hideUnityWindow
{
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [[self window] makeKeyAndVisible];
    }];
}

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];

        NSMutableDictionary *dict = [AppDelegate getUnitySwizzlingDict];
        NSArray* keys = [dict allKeys];

        for (NSString *originalSelectorString in keys)
        {
            NSString *swizzledSelectorString = dict[originalSelectorString];
            NSLog(@"Method Swizzling From %@ to %@ ",originalSelectorString,swizzledSelectorString);

            SEL originalSelector = NSSelectorFromString(originalSelectorString);
            SEL swizzledSelector = NSSelectorFromString(swizzledSelectorString);

            Method originalMethod = class_getInstanceMethod(class, originalSelector);
            Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

            BOOL didAddMethod =
            class_addMethod(class,
                            originalSelector,
                            method_getImplementation(swizzledMethod),
                            method_getTypeEncoding(swizzledMethod));

            if (didAddMethod) {
                class_replaceMethod(class,
                                    swizzledSelector,
                                    method_getImplementation(originalMethod),
                                    method_getTypeEncoding(originalMethod));
            } else {
                method_exchangeImplementations(originalMethod, swizzledMethod);
            }
        }

    });
}

#pragma mark - Method Swizzling

- (BOOL)xxxapplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSLog(@"xxxapplication:didFinishLaunchingWithOptions:launchOptions: Begin");
    [self xxxapplication:application didFinishLaunchingWithOptions:launchOptions];
    [self hideUnityWindow];

    self.unityAppController = [[UnityAppController alloc] init];
    [self.unityAppController application:application didFinishLaunchingWithOptions:launchOptions];

    NSLog(@"xxxapplication:didFinishLaunchingWithOptions:launchOptions: End");
    [self hideUnityWindow];
    return YES;
}

- (void)xxxapplicationWillResignActive:(UIApplication *)application
{
    [self.unityAppController applicationWillResignActive:application];
    [self xxxapplicationWillResignActive:application];
}


- (void)xxxapplicationDidEnterBackground:(UIApplication *)application
{
    NSLog(@"xxxapplicationDidEnterBackground: Begin");
    [self.unityAppController applicationDidEnterBackground:application];
    [self xxxapplicationDidEnterBackground:application];
}


- (void)xxxapplicationWillEnterForeground:(UIApplication *)application
{
    NSLog(@"xxxapplicationWillEnterForeground: Begin");
    [self.unityAppController applicationWillEnterForeground:application];
    [self xxxapplicationWillEnterForeground:application];
}


- (void)xxxapplicationDidBecomeActive:(UIApplication *)application
{
    NSLog(@"xxxapplicationDidBecomeActive: Begin");
    [self.unityAppController applicationDidBecomeActive:application];
    [self xxxapplicationDidBecomeActive:application];
}


- (void)xxxapplicationWillTerminate:(UIApplication *)application
{
    NSLog(@"xxxapplicationWillTerminate: Begin");
    [self.unityAppController applicationWillTerminate:application];
    [self xxxapplicationWillTerminate:application];
}
@end

UniOSIntegrationKitScript 是一个 Build Script,作用是将 UnityAppController.h 里的这段:

inline UnityAppController*  GetAppController()  
{
    return (UnityAppController*)[UIApplication sharedApplication].delegate;
}

改为

inline UnityAppController*  GetAppController()  
{
    return (UnityAppController*)[UIApplication sharedApplication].unityAppController;
}

原因是当我们使用 iOS 工程本身的实现了 AppDelegate 的文件后,对于 Unity Xcode 工程来说 [UIApplication sharedApplication].delegate 就不再是 UnityAppController 了,而 [UIApplication sharedApplication].unityAppController 才是,这是因为我们在之前的文件里声明了:

@interface AppDelegate ()
@property(strong, nonatomic) UnityAppController *unityAppController;
@end

UniOSIntegrationKitScript.sh

#!/bin/sh

#  UniOSIntegrationKitScript.sh
#
#  Created by Fincher Justin on 27/6/17.
#  Copyright © 2017年. All rights reserved.

set -x

echo "UniOSIntegrationKit"  
find $SRCROOT/../ -name "UnityAppController.h"  
find $SRCROOT/../ -name "UnityAppController.h" -print0 | xargs -0 sed -i "" "s/return (UnityAppController\*)\[UIApplication sharedApplication\]\.delegate;/return ((AppDelegate *)[UIApplication sharedApplication]\.delegate)\.unityAppController;/"  

基本上问题一和二都差不多解决了,至于问题三我原本想把整个 Unity 部分打成一个 Pod,不过外包一直在拖,我也开学了,就没再继续下去。等什么时候还有这类集成 Unity 到 iOS 的项目再说吧。

2017.08.11

 • 

之前事务较多,博客写的少了,即使写了也大多是抱怨和吐槽,还有一些私人邮件也没来得及回复。
好在八月初从公司走了,外包的事情做了大半,屋子也和房东阿姨交代妥了,和喵喵一起收拾屋子里的东西寄回家,然后带着行李去上海玩,总算是少了很多事情。


在上海的时候刷朋友圈,发现之前住的屋子已经被中介挂出来出租了,拍的照片和我三月份看到的时候变了很多,多了毯子,桌子和晾衣架以及很多细细碎碎的东西,都是这半年生活和装饰的痕迹,留给下一个租户了。
由于外包,工资,奖金加起来的原因,七八月是我月入最高的两个月份,想起来今年三四月份是我最拮据的时候,去杭州找喵喵玩的时候觉得车票都好贵,结果现在暂时不需要为出游的各种花销担忧了。换了一台新的 MBP 15 替代之前已经不能胜任 Unity 工作的 MBP 13,在游乐园玩了两天,买了很多迪斯尼的小纪念品,看了场烟花,这么闲散总觉得恍然隔世。


在今年三月份之前我还是对自己有充分的自信的,所谓充分的自信指,我觉得自己够厉害,不该在这个傻逼学校读书,即使辍学也能干得一份好工作。
但当时的我其实在此基础上还有更高的自信,因为不论如何,现在辍学的我靠着写写软件肯定都暂时饿不死,但总在饿死的事情上考虑总是略失体面,当时的我认为自己能去做更酷的事情,认为自己能战胜所有 hackathon,能吊打世界,能去做别人做不到的事情。
然后我就挨了一锤子,类似于王小波所说的一锤子,这四个月在被收购后的公司里,做啥貌似都不太顺,我自己的业务实现我自己知道和 PR 宣传的效果有多远,因为内部实现对于我来说其实一团糟,我是来重构的,即使过程中改了需求或加了功能,结果最后的产物仍然保持着丑陋的形态,这就是我的责任了。这种事情总归会让人心灰意冷。
有时候要回趟学校或者去看喵喵,然后就很拮据。学校的破事一堆堆,天天和辅导员扯皮,校招跪了两次,连带着有些压力,觉得自己怎么这么弱。到后来我的职位暂时闲了下来,也不知道去做什么,研究了会其他的技术栈就走了。
挨了这一锤子,我倒不算迷茫,只是想休息一会了。我的大学这几年一直是认准了目标直接做,学 iOS,学 Unity,去实习,都是能让我明白的感觉自己有成果的事情。这几个月我说不来自己做了什么成果,只是看了很多人和很多事情。


接下来暂时不回北京和百度了,因为有很多学校的事情要我去处理,大四还要准备毕设。
玩够了我就回家,想好了事情就去面对。

大三一年

 • 

七月了,考试成绩逐渐都出了,大三也算完结了。
成绩自然不是很好,包括因为我在北京没去参加实验所以一分没有的,不过大四会在学校呆一段时间,学分什么的还是能过的罢。
这一年算是我和学校各个管理人员摩擦最大的一年,包括和辅导员,课程设计的检查老师等。贵校贵院的作风大概就是在学院内部弄弄简历大赛看谁做的最好看,让文院出身的辅导员来检查计算机科学专业学生的职业规划,在信息院就业群里发红星美凯龙的管理岗位实习信息,和百度的 PM 以及 HR 说管不住我实习让我好自为之,我见过的至少有两三个大厂的实习生被学院逼离职回学校。
我只想说,贵校贵学院再这样下去估计是真的要完了。

大二一年里面写到的 GitHub Star 貌似目前有 800 个了,不过没有什么太大用处,该被腾讯面挂还是要挂,等忙完这一阵要多看看算法和数据结构了。今年也没有些什么开源的大项目,大多数 Commit 都提交给了私有仓库 Epoch,Cetacea 以及一些小的 macOS 软件。
至于公司,渡鸦变成了百度,人马还是同一批,中间动过去小米的心思,但是没去成。准备辞职了,忙完目前的项目后就走,回学校处理学校的破事,自己也要好好想想后面的发展。

写在最后,我想说,为了所谓管理上的方便,教学计划的安排而拖累一个人的发展,是有很大的恶的。很不幸在贵校的大三一年就是这个样子被拖累,看着各种机会被学院的破事干扰,心情和效率都会下降,祝我在贵校的最后一年赶紧走人。

2017.6.16

 • 

期末考试过半,呆在学校里总算是有了点空闲时间,更新了 BoardForGitHub,写了一个软件发布时间表 https://justinfincher.github.io/Status/
或许是喵喵还没工作的原因,很多时候和喵喵沟通起来不是很顺利。喵喵是没有经历过社会但是对社会又已经有一部分自己的看法的女生,很想积极地表达自己的想法。而我自己算是工作了一段时间,已经不想表达看法了。
不想表达的原因很简单,很多烦心事最后归根结底大致就这几条:自己误会了,自己能力不够和自己没钱。对于自己误会了的事情,贸然表达看法是一件很蠢的事情,对于自己能力不够的事情,表达了看法也不会有人高看一眼,没钱也是一样。最终,表达看法被我归类成一种毫无用处的举动,因为对事实不能产生任何影响,而我所做的,就是埋头干活改变现状就好了。而且我个人还有另外一条准则是尽量不去污染别人看到的时间线,在推特上自己偶尔发发俏皮的东西,但是一般是不怎么会去吐槽的,因为我不想让别人看到我的吐槽也跟着心情不好而已,本来大家都各有各的烦心事,何必要自己发泄让别人看到了跟着不开心。
有时候我会和喵喵表达我的看法,喵喵会觉得那连说出来都不行吗,就会很委屈。我倒也不是要别人遵从自己的行为准则,只是自己这么过惯了,突然要与喵喵分享喵喵的想法,就会觉得喵喵很多对烦心事情的看法都是没必要的,而我因为听了喵喵的话,自己也会去跟着心烦。
但我知道自己现在最好什么也不做,因为喵喵现在的情景还很闲适,而我这么要求别人的确有些刻薄了,或许等喵喵实习过后会好一点,谁知道呢,或者从头来说,我自己的所有认为都是反常人的,我有什么资格去指导别人呢。所以我更加沉默寡言,默默地做自己的事情,生产自己所认为的价值罢。

2017.6.10

 • 

自己的 20 岁已经过了四分之一了。
妹子早上起来总是会和我说她做的梦,那个时候我一般在上班的地铁上。有时候我会感叹自己已经不怎么做梦了,我对妹子的解释是做梦是一个消耗额外精力的事情,所以小孩子精力充沛会多梦,而长大后精力不够就不怎么做梦了。但我总觉得自己是刻意把做梦的功能给关掉了,就像是电闸一样,那个功能再也不会用了。
在百度实习这段时间后,觉得自己的心态越来越糟糕了,因此博客也一直没更新,毕竟去总结自己为什么过的不开心本来就已经够令人不开心了。回到学校过后细细想了下,主要还是觉得现在的生活有种隐隐的约束感,而我这个人对于不自由是非常敏感的。
每天通勤 2 小时,白天上班要写的项目处于维护状态没有什么新鲜感,晚上不加班的情况下下班后到家一般要八九点,然后妹子和我妈会打电话过来,接完差不多就要去洗漱了,晚上就没什么时间写自己的项目。有时候会觉得自己难道要一辈子一直这样下去,在公司写没有意义的代码,也没有时间做自己的事情,所有的时间貌似都在为别人而过。
当然这种担心肯定是不可能发生的,因为我还只是大三,还是实习,所有这些担忧都只是自己在某种情绪下的极度担忧而已,况且离职就可以立刻解决这种问题,因为这样的话白天的时间就会有大部分是自己的了。但这种隐隐的对不自由的担忧会仍然存在,而一旦我觉得自己不自由了,就会各种折腾,最后把大家都弄的不开心。我生性如此,而且貌似可见的十年之内不会有改动,而且我自己无计可施。

Funny Things About the Launch of BoardForGitHub

 • 

  • 发了 40 个 Promo Code,V2EX 和 Product Hunt 各 20。
  • Product Hunt 上当日(五月 25 日)排名第四,目前 520 个 Upvotes。
  • 特性请求(Feature Request)最多的两个:1.发布 Windows/Linux 版本 2.发布 GitLab 版本(上次的 Contributions 也有小哥问我能不能写 GitLab 的)
  • 有很多人以为这是一个 Electron 包装的软件,其实并不是。BoardForGitHub 是一个 ObjC + WebView 的软件。
  • 昨天 61 和我说 BoardForGitHub 在主显示器里被拖到边缘的时候不能自动移动到另一个 Space 上去,这个貌似是因为 Override 了 NSWindow 的 MouseDragged 方法
  • Softpedia 给这个软件写了一个 Review,功能介绍比我自己的都详细(我自己很懒的),因此我决定以后使用他们写的 Review 来介绍自己的软件 hhhh
  • Paddle 的 Fee 特别高,而且是每次购买都收费,因此 $1.99 会去除 $0.6 的 Fee 和 $0 - $0.4 的 Tax,截止目前大概有十几个人购买,差不多挣了二十刀。
  • 最近也说不出是忙还是闲,很多邮件一直没来得及回,这次 launch 后也多了一些邮件,问合作的,提功能需求的,还好没有要退款的

CSS & Cetacea Dev Blog

 • 

最近在进行两个项目的重写,进度都还不错。

China Startup Simulator (CSS)

CSS 作为一个小型游戏其实没什么好说的,但特殊的是 CSS 是一个类似于 Regins 的文字游戏,因此有特别多的文本。之前用的是 xls 文件进行事件(JZEvent)和事件回应(JZEventResponse)的储存,能用但比较繁琐,比如 xls 文件修改一次就要重新 deploy 一次。所以最近把储存改为了 Google Doc,可以在 iOS / Android 上实时地从 Google Drive 上拉取解析。
不过整个数据库仍然是基于列表的,对于文字对话类游戏来说,或许是一个好的序列化方式,但不是一个好的编辑方式。
所以最近在基于 https://github.com/Seneral/Node_Editor/ 写一个可视化的节点故事流程图,拖拽故事节点后编辑内容,然后序列化到 ScriptableObject 中。

Cetacea

把 Cetacea-Mac 拆成了包含四个 project 的大 workspace:

- Cetacea-Mac
- Cetacea-iOS
- CetaceaSharedFramework
- Pods

其中 CetaceaSharedFramework 包含了 Data 层的大部分内容,让 iCloud 这部分写起来更容易了些。目前两个系统的 Cetacea 如下: