2017.3.07

 • 

算起来在北京也过了一周多了。
在二十岁生日当天签了租房的合同。房租在城的东边,地铁加单车去东大桥上班要五十分钟左右,加上地铁日常偏挤一些,到公司只能说不算轻松。
但好处是整租,整间房子都是自己的,洗澡啊做饭啊都比较自由。以及房子是 Loft,房高接近 4m,带一个同样高度的大落地窗。每次从落地窗看到飞过的飞机心情都会变好一点。
工作上的事情推的比较慢,因为目前大致在做一个重构的事情。以及多了件难以抉择的事情,以我总是不会拒绝的性格觉得很棘手,同时也拖累了很多人,希望以后能果断些。
不管怎么说,总算是有点正常生活的样子了。


之前找人推了杭州某大厂。上周某天找电工在新家修电路,一片漆黑中我帮忙开手电筒照明,电工说这个不能碰那个不能碰气氛还有些紧张。突然来了杭州的电话说面试,问我有没有时间,我说现在没。然后那边说那等下次吧。然后到现在校招就处于迷一样的状态,我感觉我应该已经挂了,现在想起来感觉自己像一个智障一样,虽然说起来挺好笑的,还被周围的人吐槽和(善意地)取笑了好几次。


周末和母上聊天,聊到为什么我对挣钱这件事情这么有执念。
原因大概是在初中的时候父母想要我去一个成绩较好的军事化管理的学校,因此被扔进一个不熟的圈子,而小孩子总是喜欢抱团敌视圈子外的人的。为了混进圈子,当时的我在言语中尽力淡化自己作为外来者的特殊性,甚至以贬低自己和学习他人粗鄙的习性来融入集体。在不知不觉的自我暗示中,我开始真的变得不自信起来。因此后来的我总是想竭力证明自己来获得自信,其中就包括挣钱。
如果不是这段经历,我或许不会如此着急而病态地想证明自己,而有一个相对正常的心态。但也正是这段经历,让我真正对自己想要什么有了些启蒙。可以说我是会一直带着这段经历的影响继续下去,我没办法不承认这段经历,因为那意味着我这几年做的事情近乎无意义。
总会有嗤之以鼻的人,我也无意争论。快淹死的人是不会和岸上旁观的人争论游泳的方法对不对的,即使这个人后来侥幸游上了岸。

20.

 • 

我一直对省钱没有什么概念,因此逛超市会一直感到好奇,为什么会有十九块九毛九这种啰嗦又会找一堆零钱的定价方式。等到我变大后开始不断花钱,才算明白了这种明摆着二十却能让人觉得只有十几块的定价套路。
后来开始准备简历,实习,拿工资,像是被贴了超市的价格标签一样被扔到茫茫程序员堆里,终于也到了要被套路的年龄了。十九岁永远是十几岁,而二十岁说出来就是二十几岁了,说起来对自己的冲击力可能更大一些,无力感也会更强一些。

究竟自己价值几何,能卖出去多少的价格,又希望生产什么样的价值。19 岁的后半年里我其实一直在想这几个问题。谈薪资的时候,会有一种虚晃的不真实感,因为父母辈在小城市的事业单位里,兢兢业业,而我第一份实习的工资就差不多是父母两人工资加起来的总和。但再往后看,实习的工资面对大城市租房又不堪一击,想达到和父辈同等买房发车的愿景又不现实起来。如此只能再去期望拿到更高的工资。
尚好的是我足够幸运,处于一个自身喜欢的事业里面。如此,很多挣钱和追求理想之间的冲突简化了起来,因此我过的非常满足。

2017.2.26

 • 

开学的第一周过去了。
讲了中南 iOS 实验室最后一节开发课,和 NodeX 内部吃了一两顿饭。大致确定了下学期的实习公司和薪资,收拾了行李寄到公司。飞去杭州见妹子,连看了两场电影,绕着西湖走了好多路,聊了好多事情。面基了 Luv Letter,然后火车去北京。


在火车上看书。挪威的森林里如是写道:

我折回自己房间,解下领带,把上衣裤子挂在衣架上,换上睡衣,刷牙漱口。随即想起:得得,明天又是星期天。我觉得简直就像每隔四天就来一个星期天。再过两个星期天,我将满20岁。我歪倒在床上,望着墙上的挂历,不觉黯然神伤。

2017.02.16

 • 

聊了几个工作机会,大致的感觉是大公司对于实习都还是按照流程来,无论是快速入职还是定工资都没有多少余地。长沙本地公司不是很多(而且我也没打算在长沙找),而很多北上广公司的实习是提供给当地有宿舍的学生的,按天算的工资不是太高,若是像我这样的再去租房基本工资就要被花完。或许我目前还是更适合在初创企业干活,入职不用跟着大部队校招,工资也不会太低。
此外有两个感想,一个是我需要了解下 iOS 开发的新潮流(Swift,函数式等)了,一个是我今年应该尽力入了 3D Art / CG 这个坑,特别是在 Octane Renderer 改成订阅制后。


今天前司被百度收购一事终于公布了,陈叔说需要我回来。因此这学期应该就还是回渡鸦 RavenLab 干活。工作地点自然不在杭州,这里面的困难就和妹子两个人努力克服好了。
至于工作本身,我还是挺满意的。本身我是不在乎什么大小公司头衔的,但现在可以顶着百度 offer 名义的话还是容易和学校就大三离校这件事上交涉些。工作的其他方面都和被收购之前差不多,也不详谈了。
工作定下来后,预计下周就要回去入职。突然发现有很多事情要赶在入职前收尾,但不管怎么说都算是个好事。


十四号和妹子看了 La La Land,推荐。此外电影的原声可以一听。
和妹子在一起是一个非常有趣的过程,因为自己很多做得不到位的地方会被发现出来。此外,我日常是一个即使和我开玩笑我也会考虑实施可行性的人,结果遇到了一个脑洞略大又充满好奇心的女生。有时候聊天时会莫名地被感染,觉得倒也不是什么事情都需要细细考虑一番,也不是什么事情都需要想得那么清楚,开心就好。


本周听了 FKJ - SkylineJellis - OriginPiper - Hot SandJustin Hurwitz - Epilogue

关于找实习

 • 

昨晚突然觉得有些累,就睡觉去了。结果今天凌晨三点多就醒了,睡不着,不如找点活干。
周围的朋友在找春招,自己也在朋友圈发了一条找实习的状态,因此在博客上也写下吧。

Cocoa 或 Unity 岗都行,地点随意(若是杭州最好)。
简历:https://fincher.im/CV.pdf
英文 CV:https://fincher.im/CV(en).pdf
Portfolio:http://portfolio.justzht.com/

Cocoa 岗位,macOS 只能说会写一些小软件(参见 ArtWallWebDrop),大的项目(比如 Cetacea for Mac)至今还在跳票,貌似也没有什么能证明自己的东西了,至于 iOS 的话个人还是挺有自信的,毕竟做过一些外包,虽然写法以现在的潮流(函数式,Promise,动态化)看起来有些古典了。Unity 岗因为我一直是独立开发,不是行业内的所以也不是很清楚游戏行业的要求标准,个人水平就先参照 Lonely Planet 或者前公司 Raven H-1 的三维小人部分吧,虽然貌似我走了后同事改进了很多。

2017.2.08

 • 

昨天是妹子的生日。跑去找她,玩得很开心。今早醒来后,想起来又是异地了,有些失落。
妹子提前送了我一个 Kindle PaperWhite,挺喜欢的。


发现寒假里貌似不太可能做完任何一个项目了,因此就随便写写,给四五月份要发布的几个大新闻做些基础建设。写了会 Rails 和 ObjC,给 Lonely Planet 迁移到了 Unity 5.5。我开始变得不太那么追求项目和代码的产出了,不知道是我心态变平和了还是因为我懒,也不知道是好事是坏事。


听了 Jake Miller - RumorsObserver Drift - Warm Waves

2017.2.02

 • 

FinGameWorks 的新域名上线了。同时我和陈叔还在准备 FinGameWorks 的 AssetStore Publisher Page
最近略嗜睡。每天都是一点左右睡,十一点多醒。每天都有大人们的饭局,留给自己的时间也不多。几个进行中的项目都稍微做了些修修补补,只不过都没有较大的进展罢了。
考虑下学期找一家 base 杭州的实习,这样离妹子近一些。
看了 降临(Arrival),听了 Moving On and Getting Over by John MayerOcean 7, Pt. 2 by CrayonTreat Me Like Fire by LION BABE

2017.1.26

 • 

近日的剧情像是《挪威的森林》一样。然后渡边碰到了绿子
从大一开始我过的生活就是自己规划自己做,什么事情和亲人和朋友说声就好,但从没有和别人认真商量过。这么一种过法当然随心所欲而且效率极高,但是习惯一切都自己规划好后,想要冒险过一把有趣的生活反而会发怵。比如和妹子在一起这个事情,要考虑好多事情:我以后在哪里工作,妹子还不确定以后做什么工作,妹子以后想要去哪里工作,诸如此类。抱着这些顾虑去思考,总会觉得希望渺茫。后来问了问周边的朋友,大多都是建议我不要因为这些遥不可及的事情去断了可能的感情。想了下也的确,自己是时候鼓足勇气尝试去改变下,了解下其他人了。
感谢给我建议的各位。


China Startup Simulator 这周的开发进度有些缓慢。除去因为大部分时间在聊天以外,我对游戏本身事件的平衡性还在改来改去,导致真正需要填充的事件条目没有扩充到一个可玩的状态。以及这款游戏到底需不需要一个游戏场景?Reigns 和 Toggl 的模拟器都是纯 GUI 的游戏,也没有见多少人抱怨。而如果加上了游戏场景,必然要是一个动态的,根据事件响应的场景,这势必会需要我写很多代码。仅仅把这个游戏当作一个文字游戏来看,场景完全可以砍掉,但如果只是一个文字游戏,目前的事件条目又能保证多少玩家觉得有趣呢?

2017.1.21

 • 

昨天回到了合肥一中,参加了聚会。算是有两年没回去过了,发现女生都不同程度地变了,而男生还是一眼就能认出来。有一对高中就存在的情侣现在公开了,挺美好的一件事情。
最近母上倒是挺多次问我有没有找女朋友,或许是因为我平时表现的实在是太宅了。我倒觉得自在,虽然平时或许会心生悲寥之情,但有喜欢的事情可做,有钱可赚,倒也不觉得什么。而且我总是觉得我这样的人,大学课不上,Gap 几年再出国的计划也没定,毕业后的工作去向也没定哪个城市(虽然应该就先北京了),各种时间和空间上的不确定性,就会有各种各样的等,而我本人对等这件事情是有恐惧的。这让我对自己都有种深深的怀疑,所以还是先不要祸害别人了。


上一篇 Emoji 文章里截图的游戏还在开发,最近主要是在给 Android 设备接入 Everyplay,为了方便在移动设备上 Debug 又买了一些 Assets,深感好贵啊游戏开发人员的钱好赚啊。准备写完游戏在 Asset Store 上上架 Emojify。


Contributions 用 Element 3D 的 Promo Video 做好了。第一个版本在 Youtube 上,不过太短了(10 秒)不能用于 App Store Preview,所以做了第二个,下一个上架版本就能看到了。
此外:真的有人因为 Contributions 用 JazzHands 重写后显得只有 App Intro 而没有 App Main View 而认为软件本身有不能进入 Main View 的 bug,给了我 2 star。我思考了下,Main View 存在的意义真的不大,除非做一个游戏嵌入在里面。

Dear Pahitoz:
~~We will add a small 'flappy octocat' game as app main view soon! ~~


看了太空旅客,听了一堆存在硬盘上的老音乐。

Achieve slack-like emoji input in Unity UI Text component.

 • 

TLDR:
Copy code and use by writing

textToAddEmoji.Emojify();

最近在做一个小游戏,一开始只需要在某些文字的地方展示 Emoji 显示人物心情,所以直接用了 TextMesh Pro 的 Sprite 功能,自己拼了 8 个 Emoji:

然后选中 Texture 后新建一个 Sprite Asset,设置为默认 Sprite Asset 后在对应的 TextMesh Pro UGUI 脚本里面设置 text 属性:

<sprite=1><sprite=1><sprite=1>

就可以显示序号对应的表情了。
但是这个方案的问题在于,TMP 作为一个矢量文字显示方案,对中文的支持不是很好,在中英文都有可能出现的地方我还是尽量少用 TMP,转而使用 Unity built-in Text。而且 Unity 本身对 emoji 输入也有问题,不能像正常输入框一样输入即显示,所以还需要一个标记符替代 emoji 序列化在游戏里面。
对于前一个问题我找到了 Unity-UI-emoji,而后一个问题就准备用 Slack 的方案,在 Unity-UI-emoji 的基础上实现了。


Image refernce from slack.

Slack 对这个功能解释如下:"Slack uses the standard emoji codes found at Emoji Cheat Sheet."

Emoji Cheat Sheet 的确提供了我想要的信息,但是是用 Flash 展示的。还好找到了一个 GitHub 仓库 Emoji Alpha Codes,提供了 csv 和 json 两种格式,因此用 MiniJSON 转成 C# 的字典就可以用了。此外还需要反向转换一次,成为 alpha codes 为 key 而 emoji 为 value 的字典。

using System.Linq;
public Dictionary<string,string> InitDict ()
	{
		emojiCodeJSONTextAsset = (TextAsset)Resources.Load(emojiCodeJSONPath,typeof(TextAsset));
		deserializedEmojiCodeJSONObject = (Dictionary<string,object>)MiniJSON.Json.Deserialize(emojiCodeJSONTextAsset.text);

		_reversedCodeEmojiDict = new Dictionary<string, string>();
		List<string> arrayOfAllKeys = deserializedEmojiCodeJSONObject.Keys.ToList();
		foreach (string key in arrayOfAllKeys)
		{
			Dictionary<string,object> subDict =	(Dictionary<string,object>)deserializedEmojiCodeJSONObject[key];
			string code = (string) subDict["alpha_code"];
			string unicodeKey = GetConvertedString(key);
			//Debug.Log ("Key " + code + " ForValue " + unicodeKey);
			_reversedCodeEmojiDict[code] = unicodeKey;
		}
		return _reversedCodeEmojiDict;
	}
private static string GetConvertedString(string inputString)
	{
//有些 emoji 的图片名称带有 '-' ,这里需要拆开为两个 '\U'开头的字串拼接
		char[] chars = { '-' };
		return string.Join(string.Empty, inputString.Split(chars).Select(hex => char.ConvertFromUtf32(Convert.ToInt32(hex, 16))).ToArray());
	}

字典完成了,接下来看 GitHub 这个仓库。Unity-UI-emoji 的解决方案是读取 Text 中的 Emoji 并替换为 emSpace = '\u2001' 以保持字的长度,同时在 Text 层级下生成 RawImage 放置于 emSpace 的位置上,因为所有 emoji 都是打包成一个大贴图的,所以所有 RawImage 还是用的同一个 material,理论上可以节省 Draw Call,不过我也没测试罢了。
但是这个仓库有一个问题,在复杂的 Canvas / Text 条件下生成的Emoji 位置是错的。在我的游戏里测试下,Emoji 经常会跑到界面外。所以需要对 SetUITextThatHasEmoji 这个方法做些修改。这里需要引用到一个 SOF 回答 以及一个 BitBucket 仓库,照着 Unity 仓库源码改改就好了:

// One rawimage per emoji
for (int j = 0; j < emojiReplacements.Count; j++)
{
int emojiIndex = emojiReplacements[j].pos;

if (emojiIndex * 4 < textGen.verts.Count)
{
	GameObject newRawImage = GameObject.Instantiate(this.rawImageToClone.gameObject);
	newRawImage.transform.SetParent(textToEdit.transform);
	
	
	Vector2 locUpperLeft = new Vector2(textGen.verts[emojiIndex * 4].position.x, textGen.verts[emojiIndex * 4].position.y);
	Vector2 locBottomRight = new Vector2(textGen.verts[emojiIndex * 4 + 2].position.x, textGen.verts[emojiIndex * 4 + 2].position.y);
	
	Vector3 mid = (locUpperLeft + locBottomRight) / 2.0f;
	Vector3 size = locBottomRight - locUpperLeft;
	
	
	//Vector3 imagePos = new Vector3(textGen.verts[emojiIndex * 4].position.x, textGen.verts[emojiIndex * 4].position.y, 0);
	
	Rect inputRect = textToEdit.rectTransform.rect;
	// get the text alignment anchor point for the text in local space
	Vector2 textAnchorPivot = GetTextAnchorPivot(textToEdit.alignment);
	Vector2 refPoint = Vector2.zero;
	refPoint.x = (textAnchorPivot.x == 1 ? inputRect.xMax : inputRect.xMin);
	refPoint.y = (textAnchorPivot.y == 0 ? inputRect.yMin : inputRect.yMax);
	Vector2 roundingOffset = textToEdit.PixelAdjustPoint(refPoint) - refPoint;
	IList<UIVertex> verts = textGen.verts;
	FontData fontData = FontData.defaultFontData;
	fontData.font = textToEdit.font;
	float pixelsPerUnit = 0.0f;
	var localCanvas = GameObject.Find("GameCanvas").GetComponent<Canvas>();
	if (!localCanvas)
	{
		pixelsPerUnit = 1.0f;
	}else if (!textToEdit.font || textToEdit.font.dynamic)
	{
		pixelsPerUnit = localCanvas.scaleFactor;
	}else
	{
		pixelsPerUnit = textToEdit.font.fontSize / (float)fontData.fontSize;
	}
	float unitsPerPixel = 1 / pixelsPerUnit;
	int vertCount = verts.Count - 4;
	if (roundingOffset != Vector2.zero)
	{
		mid *= unitsPerPixel;
		mid.x += roundingOffset.x;
		mid.y += roundingOffset.y;
	}else
	{
		mid *= unitsPerPixel;
	}
	
	
	Debug.Log ("EMOJI mid X" + mid.x + " Y " + mid.y + " Z " + mid.z);
	newRawImage.transform.localPosition = mid;
	
	RawImage ri = newRawImage.GetComponent<RawImage>();
	ri.uvRect = emojiRects[emojiReplacements[j].emoji];
	ri.rectTransform.pivot = new Vector2(0.0f,0.0f);
	ri.rectTransform.localScale = Vector3.one;
	ri.rectTransform.sizeDelta = Vector2.one * textToEdit.font.lineHeight * unitsPerPixel;
	
}

代码很脏,但能用,等做完游戏后这块再重构下。
然后就是给 UnityEngine.UI.Text 加一个方法拓展,我命名为 Emojify();

static public void Emojify (this UnityEngine.UI.Text self)
{
	if (JZEmojiUITextManager.Instance.reversedCodeEmojiDict == null)
	{
		return;
	}
	string currentCodeBasedString = self.text;
	
	// 使用正则把 emoji alpha code 转换为 对应的 Unicode
	Dictionary<string,string> map = (Dictionary<string,string>)JZEmojiUITextManager.Instance.reversedCodeEmojiDict;
	var regex = new Regex(string.Join("|",map.Keys.ToArray()));
	var newStr = regex.Replace(currentCodeBasedString, m => map[m.Value]);
	// 第一次正则的 Unicode 还没有 Unscape,需要把 '\\' 改为 '\'
	Regex regex1 = new Regex (@"\\U([0-9A-F]{4})", RegexOptions.IgnoreCase);
	var newStrUnescape = regex1.Replace (newStr, match => ((char)int.Parse (match.Groups[1].Value,
		NumberStyles.HexNumber)).ToString ());
	JZEmojiUITextManager.Instance.StartCoroutine(JZEmojiUITextManager.Instance.SetUITextThatHasEmoji(self, newStrUnescape));
}

至于 JZEmojiUITextManager 就是一个简单的单例,用于生成和存放刚才的那个字典,以及把 Unity-UI-emoji 仓库的大部分方法复制了一份。现在就可以直接对某个 Text 组建直接写:

textToAddEmoji.Emojify();

另外我还替换了这个仓库的 Emoji 图片,从 Twitter Emoji 换到了 iOS Emoji,链接为 github.com/iamcal/emoji-data。现在效果如下:

Morning! Here is your new phone. 
:flag_us:
You can reply to new messages by swiping cards to left or right. Different reply will lead to different impact on company valuation and staff happiness.
Our goal is to hit $ 1 Billion valuation by the end of the year while keep our staff from leaving.