在游戏公司工作是什么体验呢?

不知道大家对于一线城市的游戏公司,或者IT公司,是什么印象。亲身经历过,才知道,其实并没有都市爱情电视剧中演的那么高端(😂)。 经历过好几家游戏公司,有十几人的小公司,也有几十人,上百人,多项目组的公司,基本上,除了做的东西内容不一样之外,在其他方面有很多交集。 上班时间一般是9点~10点之间,有的公司弹性制,早上如果晚到了一会,晚上晚点走即可,只要事情保证质量地完成。有的公司严格按照打卡时间来,晚到1秒种也是迟到。第一种心理上会更轻松一点,工作与生活融合,但是也难免有可能出现很多人晚到,做事情拖延的情况。第二种气氛紧张,工作就是工作。说不上哪种更好,各有利弊,主要看公司的文化,以及员工的整体素质更适合哪一种。很荣幸,我现在所在的公司,就是第一种。 上午只有2个小时的工作时间,如果有比较紧急的事情,那就会优先处理紧急的事情。如果没有,那我一般会先处理能够在段时间内完成的事情。或者不开发新功能,修修Bug之类的。 我们中午有一个小时的休息和吃饭时间。下午应该是效率最高,工作密度最高,注意力最集中的阶段。我一般会戴着耳机,写代码,开发新功能。如果一个互联网公司规定上班时间不准戴耳机,那你去的可能是一个假的互联网公司(特殊部门除外),或者管理层是非互联网公司出身的人。 在没有被经常打扰的情况下,一下午,可以处理很多事情。 我们晚上下班时间是18点~19点,根据早上来的时间,也是弹性制。 对于加班呢,平时没有硬性规定,如果感觉自己的任务在规定时间内时间比较紧张,那就多加一会班,完全是根据自己的情况来,只要在规定的时间内保证质量地把功能开发完即可。我们一般是按周来排计划的。当然,也有强制加班的情况,比较一些比较重要的时间节点,要出一些比较重要的阶段性版本时,一般会原则上大家都加班,最晚也就是22点左右。出版本的时间,如果问题比较多,也有可能通宵的,当然,如果搞的太晚,第二天基本上也就不用上班了。不过这种情况是极少的。 有的公司会有一个很不好的现象,就是到了下班时间,如果上司不走,大家没有一个走的,即使没什么事,也是在公司待着,耗时间。我不知道是不是管理层意识不到这个问题。还好,我现在所在的公司不存在这个问题,开心。 有的公司会提供早餐,有的公司,会有下午茶,大部分公司,是没有的。记得以前去面试一家公司时,招聘信息上写着提供免费的零食,饮料。到了后才发现,就是一个小小的桌子,上面放了一些饼干,一些碳酸饮料,一些雀巢咖啡……这让我很是震惊,还不如不写。 公司里喝咖啡的人很多,以前没怎么注意,但是现在可以看到很多同事早晨来公司的第一件事就是去楼下的Luckin点一杯咖啡。也许是因为Luckin的出现,让买咖啡确实变得更容易了。 一个游戏公司的人员,宏观上大概由策划,美术,程序,音频,运营这几部分组成。如果细分的话,策划又分为系统策划,剧情策划,数值策划等。程序分为客户端程序,服务器程序。美术分的会更细,有建模,UI,动作,特效,原画等。建模又可以分为角色建模,场景建模等。原画也可以细分成角色原画,场景原画等等。越大的公司,可能分的越细。小的工作室,往往一人身兼多职。例如建模的把动作也顺便做了。 工作流程上一般由策划先行,设计和提出功能需求。然后资源方面的需求提给美术那边,逻辑实现方面当然就是程序这边做。开发计划,项目的任务分配与跟踪,一般由PM来做。当然是要和大家开会对接的。一个功能由谁开发,并不是PM直接决定的,而是要商量着来。 工作氛围很轻松,但也有充满挑战的时候。有时,也需要去解决一些从未遇到过的技术难题。不管哪一个公司,哪一个项目,可能或多或少都会有这种情况。 当然,也会有产生分歧和争吵的时候,时常发生在程序和策划之间。对于IT界,似乎程序和策划就是"天敌",哈哈哈。其实不是的,分歧归分歧,工作之外大家相处的还是很融洽的,总之就是针对事情争论,而不是针对人。没有网络上传言的那么可怕。 年会,也是很多人所期待的。有的互联网公司会搞的很宏大,各种红包,各种抽奖。获取出国旅行,国内旅行等等。也有比较低调的,就是全公司一起出去吃大餐。具体情况,可能还要根据公司的盈利情况。 大概情况就是这样,暂时想到的就这么多,后面想到了再补充,如果你更多想问的,欢迎在下面留言欧~。

December 6, 2019 · 1 min · 猫猫

浅谈Unity3D音频可视化效果原理

在游戏开发中,你是否也想将音乐旋律变为漂亮的图形显示?就像这样的效果。 ...

December 4, 2019 · 2 min · 猫猫

怎样在Unity中Reload原生插件

这是一篇翻译文章,原文来自 how-to-reload-native-plugins-in-unity 在Unity编辑器使用原生插件,Dll之类的,经常会遇到一个问题,替换插件时,Unity会提示正在使用,无法替换,这是因为Unity一旦点了Play,加载了Dll,就不会去卸载。 要解决这个问题也很简单,那就是先关掉Unity,然后替换Dll,然后再打开Unity。对于插件的使用者,倒不是什么大问题,但是如果你是插件的开发者,需要频繁的修改和测试插件,那就有点悲惨了。 这篇博客将介绍一个我认为不错的解决方案,有很多开发者已经实现了这个或者类似的解决方案,但是在Google或者Github上很难找到。 TLDR 我写了一个200行的代码,在OnAwake时,会加载所有的Dll,在OnDestroy时会卸载所有的Dll,我们自己去管理Dll的加载和卸载,就可以做到停止Play时,卸载掉所有的Dll,这样就可以在不关闭Unity的情况下,替换Dll。 要做到这个,就不能用 PInvoke 去调用,而是用类似的方式,达到相同的目的。 完整的工程代码在 Github。但是我们只需要一个文件就可以 NativePluginLoader.cs 如何使用: 将 NativePluginLoader.cs 放到你的工程中 在场景中新建一个GameObject,然后挂载 NativePluginLoader.cs 定义一个类,用于声明所有的插件方法,例如命名为 FooPlugin,然后给这个类赋予 PluginAttr 属性 给 delegate 添加 PluginFunctionAttr 属性,示例代码如下 // C# 代码 [PluginAttr("my_cool_plugin")] public static class FooPlugin { [PluginFunctionAttr("sum")] public static Sum sum = null; public delegate float Sum(float a, float b); // 原生方法的 delegate } void CoolFunc() { float s = FooPlugin.sum(1.0, 2.0); } // 这里是原生C代码中的接口, 最后打成Dll给Unity调用 // my_cool_plugin.h extern "C" { __declspec(dllexport) float sum(float a, float b); } 关于 PInvoke 调用原生插件的常规方法是通过 PInvoke...

December 1, 2019 · 2 min · 猫猫

浅谈在Unity3D中使用CriWare播放声音

在游戏开发中的音频解决方案,CriWare 是不错的选择,很多游戏大作也在使用。为什么使用CriWare呢?对于游戏运行时,可以显著提高加载速度和减小包体大小。而对于音频制作上,可以很方便地做更多的效果,例如多音源的避让等。 今天我们就来浅浅地聊一下在 Unity3D 中使用 CriWare 播放声音,以及声音的管理等问题。 音频文件由做音频的同学使用CriWare的软件去制作,最终导出的文件是以acb或awb为扩展名的文件。如果采用的是Memory的形式,则导出的acb文件。 对于开发来说,首先要知道两个东西,一个是CueSheet,一个是CueName。在音频制作的时候,多个音频可以打成一个组,每一个音频的名字,就是CueName,而这个组,就是CueSheet。我们要播放一个声音,首先要知道声音的名字,就是CueName,还要知道它所在的组,因为要加载到内存中。即使要播放组中的一个音频,也是要把整个组加载到内存中的。 所以在制作时,音频那边的同学要规划好,哪些音频要在同一个组,哪些音频要在另外的组。当然,可以一个音频一个组,但是打成组可以做很多事情,这个等我请教一个音频那边的同学再补充。 先将声音播放出来 首先把CriWare插件导入到Unity中 将做好的声音ACB文件放入StreamingAssets目录中 新建一个空物体,然后挂载CriAtom组件如下图 CriAtom 用于管理CueSheet,只有将CueSheet加入到CriAtom中,才能播放其中的某一个音频。将CueSheet加入到CriAtom中,意味着这个CueSheet会被加载到内存中,移除CueSheet,则会从内存中卸载。 上图中每点击 Add CueSheet,就可以填入一个新的CueSheet,Name字段就是ACB文件的名字(不带扩展名),ACB File字段填写ACB文件名字(带扩展名)。例如上图中我已经填了一个示例。 新建一个空物体,然后挂载 CriAtomSource 组件。这个组件,可以理解为Unity的AudioSource,就是用来播声音的。 上图中,CueSheet字段,填写要播放的音源,所在的CueSheet名(不带扩展名),而CueName,就填写要播放的声音的名字。这些名字,都是做音频的同学定好的。勾选上 Play On Start,然后运行Unity,就可以听到声音。 上面只是实现了声音能够播出来,要在真正的项目中使用,还需要管理声音,下面将说一下大概的思路。 声音管理器 基本思路是这样的,首先有一个声音管理器我们称为AudioManager,提供接口播放声音,停止声音,暂停声音,恢复声音,播放完毕,CueSheet加载卸载。外面模块调用AudioManager去控制声音。 调用 AudioManager 播放声音的接口时,会生成一个新的对象, GameObject,挂载一个脚本,我们称为 AudioPlayer,这个 AudioPlayer 中会动态的挂载 CriAudioSource,然后将我们要播放的CueSheet,CueName这些值通过AudioManager传进去,设置 CriAudioSource 参数,然后调用 CriAudioSource的 Play 函数。 当调用 AudioManager 的播放声音接口时,AudioManager 会动态记录这个 CueSheet 是否已经添加到 CriAtom 中,如果没有,则会添加,这时,CriAtom会去加载声音文件到内存中。 AudioManager 在声音播放完,或者 GameObject 被销毁时,需要调用 AudioManager 的播放完毕接口,用于计数。这个计数,是为了让 AudioManager 知道一个CueSheet中,是否还有声音在播放,如果没有了,则要动态将 CueSheet 从 CriAtom 中移除掉,释放内存。 具体代码我还没写,请等待我有时间再补充~。

November 30, 2019 · 1 min · 猫猫

图形学相关的基本数学

这一篇博客会比较长,目前还没写完,处于不断更新中… 这一节会用一些通俗的语言去解释一些数学上的概念,有一些解释可能并不是严谨,我们更多地是把焦点放在理解这些概念是什么,为后面的应用做铺垫。如果有一些点不能理解,也没关系,只要知道有这样一个东西就行,等真正用到的时候,有点印象,这样就会有解决问题的方向,再回来查相关的知识就可以。单纯记住一些知识是没有太多意义的,只有会应用了,才有意义。 集合 (Sets) 一堆东西,就是一个集合。例如桌子上有一堆苹果,就可以说,这是一个苹果的集合。旁边放了一堆干果,就可以说,那是一个干果的集合。这里有100个数字,都是整数,那这就是一个整数集合。 下面是一些常用的集合 ℝ 实数集合 实数包含有理数 和无理数,有理数包括整数和分数,无理数就是无限不循环小数 ℝ+ 非负实数集合 理解了实数集,这个非负实数集合就好理解了,就是把把负数去掉 ℝ2 有序对,像二维的坐标,就属于一个有限对,(x,y) ℝn 在n维笛卡尔空间中的点 ℤ 整数集合 S2 在单位球面上的3D点 上面的这些常用的集合,大概了解一下就好了,不用详细的去探究,只要大概知道是什么,有这个名词的印象就OK,等用到的时候自然就了解了。 映射 (Mappings) 映射和编程上的函数很类似,输入参数,输出结果,或者说,给函数一个A,函数进行运算后,会返回给你一个B。而映射,类似,就是将一个东西从A变成B。 f:ℝ↦ℤ 这个东东,可以这样解释,有一个函数叫做f,这个函数呢,接收一个输入,这个输入是ℝ,也就是上面说到的实数类型的数,注意,这里是输入一个实数,而不是输入实数集合,这里的ℝ可以理解成编程函数中的数据类型。然后呢输出一个整数类型的数。基本上可以当作编程语言中的函数调用。 映射,是将一个集合中的元素,映射成另一个集合中的元素。可以说,你从A集合中找一个元素,扔进映射函数里,那么映射函数会从B集合中找一个元素,再扔给你。 逆映射 (Inverse Mappings) 通俗来讲,逆映射就是映射反过来,你从B集后找一个元素扔进映射函数,映射函数会从A集合中根据映射规则找一个元素还给你。映射中,有一个名词,叫做 双射,就是说,对于A集合中的任何一个元素,都能在B集后中找到唯一一个与它一一对应的元素,并且,对于B集后中的任何一个元素,也都在能A集合找到唯一一个与它一一对应的元素。这种情况,就叫做双射。 区间 (Intervals) 区间可以理解为一个数值范围,这个范围内的元素放在一起,也就是我们前面学到的集合。例如一周有7天,数值范围就是从星期一到星期日,某幼儿园小朋友的身高范围是80cm到140cm之间的,这些都是区间。我们从整数集合上定义一个区间,例如[1, 15],意思就是从1到15这15个数。用中括号[] 表示的区间叫做闭区间,用小括号()表示的区间叫做开区间,还可以混合使用,例如 (] 或者 [),这种分别叫做半开区间和半闭区间。那它们有什么区别呢?中括号,表示区间范围包含起始或结束数值,小括号表示区间范围不包含起始或结束数值。 [1, 10] 表示区间范围是从 1到10 (1, 10) 表示区间范围是从 2到9 (1, 10] 表示区间范围是从 2到10 [1, 10) 表示区间范围是从 1到9 并集: 给定两个集合A,B,把他们所有的元素合并在一起组成的集合,叫做集合A与集合B的 并集,记作A∪B,读作A并B。 交集: 给定两个集合A,B,把所有即属于A,又属于B的元素拿出来,组成一个新的集合,这个集合,就叫做A与B的 交集,记作A∩B。 区间可以做减法操作,A-B,表示的是,从区间A中,去掉属于属于区间B中的元素。 对数 (Logarithms) 我们先来看一个简单的计算 $3^{4} = 3 * 3 * 3 * 3 = 81$ 这个是不是很简单?3的4次方就是4个3连续相乘,最后结果是81。这叫做幂运算。...

November 20, 2019 · 2 min · 猫猫

数据结构概述

经常有小伙伴想系统地学习一下数据结构,但很难找到适合自己的教程。好吧,其实说的是我自己。那今天就来聊一聊这个问题。 我们先把一些常用的数据结构列表出,大概讲一下他们的结构及应用,后面分篇细细讲解。在分篇讲解时,我们的关注点是某个数据结构是什么,怎样用代码描述出来。而更多涉及到这个数据结构的一些算法,将在后面的算法系列中详细讲解。 这个系列的博客,是面向那些和我差不多,大概了解数一些数据结构(知道一些名字,不太了解内部详细实现),又想系统地巩固一下,深入一下的小朋友们~ 快来一起学习吧 ^_^ 数组 [Array] 数组用于存储同种类型的数据,数据与数据之间在内存中是连续的(相邻的),在使用数组前,要预先分配好指定的内存大小。 应用: 例如我们想存储幼儿员小班所有小朋友有的名字,就可以用数组。 [第一个小朋友名字, 第二个小朋友名字, 第三个小朋友名字, …] 链表 [Linked List] 链表,是由一个个节点,相连而成。每一个节点,都是独立的元素,它们在内存中的位置也不一定是连续的。每一个节点,都拥有两个部分,数据部分,和一个指向下一个节点的引用。刚刚说的是单向链表。 还有一种叫做双向链表,区别就是一个节点有三个部分,数据部分,一个指向下一个节点的引用,一个指向上一个节点的引用。 还有一种叫做循环链表,区别就是尾部和头部会连起来。 应用: 链表常应用于存储不能事先确认数据个数的情况,对于这种情况,使用链表不需像数组一样预先分配内存,当有新的数据要存储时,只需要新申请一个节点的内存空间,然后将这个节点添加到链表即可。 堆栈 [Stack] 想象这样一个场景,往一个箱子里放书,先放进一本漫画书,再放进一本故事书,再放进一本数学书。现在最上面的是数学书,如果要把里面的书一本一本都拿出来,就要先拿出数学书,再拿出故事书,再拿出漫画书,正好与放下的顺序相反。这就叫先进后出,FILO (First in last out)。 而堆栈就是这一种结构,堆栈通常拥有两个方法,Push 和 Pop,分别就是放入数据,和拿出数据。后放入的数据,总是在最上面,往外拿数据时,也像从箱子里拿书一样,要从最上面开始拿。是不是很形象~ 应用: 堆栈是一个很有用的东西,我们平常用的很多软件中,都能找到它的应用,例如文本编辑器的撤销功能,其实就是在特定时间将用户的操作Push入栈,然后撤销时,从栈中Pop出最近的一个操作。再例如浏览器的后退功能,也是依次将用户浏览的网址Push入栈,然后后退时,依次Pop出最近的浏览网址。 队列 [Queue] 大家排队买冰激凌,就是一种队列结构,这个人买完冰激凌,然后下一个。在这个过程中,后面不断的有人在排队,队伍越来越长,服务员从前面一个一个处理顾客的需求。 队列也是这样,先入列的,也会先出列,就像排队。先排队的,先拿到冰激凌,然后走人。所以队列通常有两个操作,入列(Enqueue) 和 出列 (Dequeue)。队列是先进先出,FIFO (First in first out)。 还有一种队列叫做环形队列,会循环利用已经分配好的内存空间,而不是入列和出列时执行分配和销毁内存操作。 应用: 需要依次处理的事情,都可以使用队列,例如网络通信数据包,当客户端收到消息时,就可以放入队列,而消息处理器,不断地尝试从队列中取消息,如果有,则处理。 咦?刚才好像说到冰激凌了~ 二叉树 [Binary Tree] 树,就像我们平时在公园里看到的那种树的结构,分叉。而二叉树呢,就是只能分两叉,一分为二,每一个分叉,又可以最多一分为二。就像下面的这种形状。 二叉树的结构,也可以理解为由 “节点” 组成,就像链表那样的节点。对于二叉树来说,每一个节点有三个部分,数据部分,指向左边分叉节点的引用,指向右边分叉节点的引用。 二叉树,每一个节点,最多能分两叉,也就是,每一个节点,最多拥有两个直接子节点,也可能有一个,也可能没有。其实,二叉树的实现,很多也是用链表来做的。这个后面的博客再详细介绍,嘿嘿~ 应用: 树型结构在计算机中也有很多应用,例如我们很熟悉的文件浏览器。一个目录下,可以有多个目录,子目录下,又可以有多个文件,然后还可以再分叉继续往下深入。不过,真正的文件系统并不一定用的是二叉树,也可能是n叉树,具体的我还不是很清楚,尴尬ing… 二叉查找树 [Binary Search Tree] 二叉查找树,简称 BST,是在二叉树的基础上,增加了额外的规则。首先,我们给每一个节点赋予一个权重,这个权重,可以用任何东西代替,例如小朋友的分数,例如冰激凌的价格等等。然后,每一个节点,满足下面的规则 如果一个节点左子树不为空,则整个左子树上的所有节点,权重都要小于当前节点 如果一个节点右子树不为空,则整个右子树上的所有节点,权重都要大于当前节点 左右子树,也都是二叉查找树,也就是说,子树,也要满足上面也条规则 应用: 二叉查找树常常应用一些需要数据保持有序状态,但是又经常需要插入和删除某些数据的场景。例如电商平台中的商品数据组织,可能就经常用到二叉查找树。...

November 17, 2019 · 1 min · 猫猫

2023.03.15

生活 今天终于看完了《黑暗荣耀》第一季,女主牛B,人生中的每一个重要选择,都是心中那个复仇目标为导向。 工作 《异能失控》项目今天把工程整理了一下,整理了一下Lua层的启动代码,比起上个项目来清晰了许多。使用ChatGPT生成了几十个怪物的名称和描述,以及单个技能,更想细的信息还需要再做一下。 学习 学习了Rust多线程并发编程相关的东西,Mutex,Condvar,信号量什么的,不过还是模模糊糊,看来还是得具体项目实践才能彻底熟练。

1 min · 猫猫

2023.03.16

生活 又炖了鸡腿肉。今天在博客里加上了 Tid 页面,用来简要地的记录每天的生活、工作、学习相关的东西。 工作 异能失控游戏开场界面搞完了,确定了基本的背景颜色,按钮颜色,输入框颜色,修改了几个界面的字体。开场的文本使用 ChatGPT 生成然后人工进行了一定的修改。背景音乐也找到了。 学习 准备系统地学习一下伯克利的CS相关的课程。Crash Course Computer Science 看了一点。学习了Rust多线程相关的 Atomic 和 Send、Sync 相关的东西。

1 min · 猫猫

2023.03.17

生活 今天一整天都在下雨,起床比较晚。中午的时候点了麻辣香锅,可是不是很好吃,还不如我买包料自己做,再也不点这一家了。今天还试了一下把 ChatGPT 跟微信连起来,但是不是很好用,很慢,而且一旦电脑上登录了微信,这个服务就直接停了。 工作 今天使用 ChatGPT 生成了地图的区域名字。把地图界面搭建了一下,大概的逻辑也有方向了。 学习 学了一点点Rust。继续阅读《剑与电-角色扮演游戏设计艺术》

1 min · 猫猫

2023.03.18

生活 今天干了啥,忘记了。找了一部动漫在看,末日曙光。 工作 今天尝试了一下在Mac下使用 Stable Diffusion,还是不太好用,麻烦。没有写代码,但是跟一个玩家聊了一下异能这个游戏,找到了一些新的方向,开发路线逐渐清晰了。 学习 继续阅读《剑与电-角色扮演游戏设计艺术》

1 min · 猫猫