作者归档:月夜

一个游戏运营项目失败的思考

这是我对自己参与的一个项目失败的思考,有点马后炮的赶脚。仅仅代表个人的观点和看法,不一定正确,仅供记录我这个阶段的一些想法,积累下来以供将来重新的审视与提高。

先简要的介绍一下这个项目,这是一个网络游戏在海外运营的项目,促成这个项目的开始是出自同事以往行业内的从业经历,恰逢其会的是该同事具有前期能引流的人脉并且也愿意一番尝试,在技术上也具有在预期时间内完成基础平台建设的能力。在项目启动之初,可谓「天时、地利、人和」齐活了,一个比较完美的开始就这样诞生了,剩下的就是甩开膀子,在快速迭代试错中迈着小碎步向前奔跑,以成就一番事业。

「愿望总是美好的,现实总是残酷的」,我甚至不知道这个项目最终结束的具体时间,因为项目进行的中间我就已经离开这个游戏创业项目了,很短暂的开始,很短暂的结束,但当整个团队决定开始增加新方向的时候,这个项目终将结束在我看来也是必然的。

gameplatform

按照这个项目来说,项目的主体共有三方组成:游戏厂商、初始用户导入方、平台运营团队。三方各司其职,共同推进整个项目的发展。

(1)被选中且能够与我们开展合作的游戏厂商的主要工作是完成游戏的接入,游戏的升级维护及节日活动的推出与定制,另外就是三方的结算对账。
(2)初始用户导入方完成用户的引流工作,以及运营分成的财务结算对账,完成境外其他资源引流的合作洽谈,找出最佳的引流途径。
(3)平台运营团队就是我们了,主要负责运营平台的建设、游戏的筛选与签订合同、游戏接口与平台的接入、平台的充值及换算、后台数据分析与核对、游戏运营活动的策划与运营推广、游戏客服、「建立自己的用户资源」、与各方财务结算。

游戏厂商在整个进程中的配合是非常良好的,在发生问题的时候总是能及时得到反馈,在活动及游戏内资源的支持上也不遗余力,而且从洽谈的过程中,能明显的感觉到他们是乐意合作的。

初始用户的引流工作虽然是资源方乐意尝试的,但不是其主营,这点上可能力度有待进一步加强,这些可以通过沟通来解决,还有就是对于引流的效果应该由我们结合引流方式给予资源方一定的支持,当然这些是要依据一定的数据方式,比如在游戏中做一些有奖励的调查问卷来获得其大部分的来源途径,其实这些在资源方那边是可以统计出来的。

我主要负责技术这块,并且参与跟游戏厂商的洽谈接触,在初始系统基础上安排设计人员和开发人员进一步定制以后基本上满足开始的运营需求,整个平台就这样开始运营了。我一直认为在一件事开始之后,专注与围绕专注开展工作是一个前提,就这个平台开始运营之初,构成其未来的主要工作集中在两部分:「其一是运营推广,这是重中之重,其长期努力的方向是建立自己的用户资源;其二是围绕运营推广提供强劲持久的技术驱动力,持续发展运营平台及其周边增值服务,保证给不同类别的用户持续输出富有娱乐性的游戏」。

围绕这两部分开展工作就是基础,刚开始运营其实从数据上来看还是比较符合预期的,在差不多一个月单游戏单区的情况下,用户注册数、每日在线数、充值数、日注册及活跃增长数及用户留存率上来看还相对符合预期,下面是一个月的部分充值记录。

paysummary

有了一个好的开始,但随后突然就放下了,主要的工作没有行之有效的开展,或者说没有足够的努力。危机意识不强,对技术长期驱动力的价值也不太认可,加上团队成员的实际生活问题等诸多因素的影响下,又有了开展其他行业新业务想法。在这种情况下,我最终选择了离开,因为我没有更多的资金投入开展新的业务,同时我也不认为当时的团队与投入能够有精力同时开展两条线的业务。

至于说主要的工作没有行之有效的开展是我个人的观点,对于我这个初次涉足游戏行业的人来说,在开始到离开这段时间其实有不少的想法,比如说在通过资源方引流的原始用户基础上,通过怎样的策划与推广,带来新的朋友用户,能不能制订积分体系加物质激励来完成?能不能通过游戏虚拟物品激励来完成,平台自己是否增加用户推荐体系并给予满足条件的推荐用户以激励?围绕游戏如何建立社区论坛?能否增加周边商城拓展游戏增值服务?满足这些运营平台应怎样重新架构? 诸如此类的想法有不少,但是这些想法没有成文后与团队成员进行充分的沟通,虽然这些想法对于初涉游戏行业的我显得比较稚嫩,但至少也应该跟团队成员讨论一下,在讨论过后相信自己也能获得长足的提高,增加对这个行业的认知。

危机意识不强的很大一部分原因是被这开始的充值额冲昏了头脑,按照一款游戏一个区来计算,想来多款游戏多个区就能达到预期,从我后来离开后的间断性关注中,先后上线了新的两款游戏,并且增加了新开区,但是充值及用户增长却一度中断,中间我没有看到任何针对这些不好影响的调整。这段时间我的猜测是人力资源不能跟进以保证用户的使用引导及足够的支持工作,由于新开展的其他行业新项目占据太多的精力,导致迟迟没有建立初步的用户服务机制、用户引入机制、用户激励机制、用户参与机制等。且在整个行业的发展中,游戏的变化也是急剧的,缺少对端游、页游、手游这些不同类型游戏的持续性关注。

再往后就没有往后了,却留下了诸多的不良影响,影响之一是在合作过程中给其他两方留下了一定的印象;影响之二是给玩过一阵的玩家留下了一定的印象,进而导致资源方也给玩家留下了足够的印象;影响之三是给所有团队成员留下来一定的印象。那么收获呢?

对于我来说这个短暂的创业经历有几点收获:

(1)要一直专注,所有要做的事情都要围绕最初设定的目标来做,尝试能够尝试的一切方法只为向目标迈进或者由目标衍生的新目标,直至结束,在未终止前我们其实没有更多的精力同时专注两件事;
(2)要有危机感,要给自己设定尽量涵盖全范围的最差的情况,然后设法找到解决方式,时刻保持危机感能促使专注;
(3)运营是重中之重,运营始终需要强力的技术作为保障,从这个角度来讲,技术是运营的支撑,技术是驱动力,要尽量获得团队成员对技术的认可,运营平台系统的建设不是一锤子买卖,需要长时间的演变,从功能到架构;
(4)要设定退场时对各方影响的补偿机制,用户从开始使用提供服务的第一天就会投入情感,任何时候不要让用户失望,说不定结束前小小的沟通就能超出用户的预期;
(5)人在任何时候都是关键,保持足够的沟通能够增加互相的了解,比较理想的是在没明确结束前,大家都能全力的参与其中;
(6)多少人做多少事,我们往往太过相信自己能够做的更多,可往往我们并不能做更多的事情,我们往往过高估计自己。

php中的魔术方法

php中内置了不少被赋予魔术性质的「魔术方法」,魔术方法以双下划线开头「__」,在类中使用,在特定的条件下自动在程序中被调用,由于具有在特定条件下自动被调用的特性,使得编程过程得以简化。

在PHP中魔术方法有:__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone(), __autoload()

1. __construct() 和 __destruct()

__construct()和__destruct()分别称为构造函数与析构函数,在对象被创建和销毁的时候由系统自动调用,跟其他编程语言中构造函数与析构函数一样,也是在面向对象编程中使用最频繁的。

构造函数主要完成对象在创建时候的初始化工作,一般用于初始化对象的成员,在PHP中,子类使用父类的构造函数必须使用parent::__construct()显示调用,不支持隐式自动调用。

对应的析构函数是对象在被系统销毁时自动调用。包括对象被显式销毁或者该对象的所用引用都被删除。跟构造函数一样,子类析构函数使用父类析构函数同样使用parent::__destruct()显示调用。

construct

2. __call()和__callStatic()

当调用对象不可访问的方法或者没有的方法时自动调用__call()魔术方法。该魔术方法有两个参数,第一个是调用的方法名称,第二个参数是枚举数组参数列表。用静态方式调用不可访问的方法或者没有的方法时自动调用__callStatic()魔术方法。

测试后发现对于存在但不可访问的方法并不能通过__call来调用,调用顺序为,先在自己类中寻找方法,如没找到,向父类中寻找,如果在父类中找到则调用父类中方法,如果没有找到而本类中有__call方法则执行__call魔术方法。

call_01

该魔术方法另外一个比较重要的用途就是实现重载,在PHP手册中这两个魔术方法介绍的标题也是方法重载。

call_02

3. __get() 和 __set()

当读取不可访问或者未定义的属性时,访问__get()方法。当设置不可访问或者未定义的属性时,访问__set()方法。

4. __isset()和__unset()

当在一个未定义或者不可访问的属性中调用isset()函数时访问__isset()方法。当在一个未定义或者不可访问的属性中调用unset()函数时访问__unset()方法。

 5. __sleep()和__wakeup()

这两个魔术方法在进行序列化的时候使用,通过序列化可以将任何类型数据转化为字符串格式,我们可以通过序列化对象,将其转化为字符串格式保存起来。在进行序列化的时候,检查类中是否有__sleep()魔术方法,如果有就调用该方法。在进行反序列化的时候会检查类中是否有__wakeup()魔术方法,如果有就调用该方法。

通常在__sleep()方法中处理不需要序列化的部分内容或者做一些对象的清理工作,而在__wakeup()方法中进行一些初始化操作。这两个方法是配合序列化和反序列化使用的。

6. __toString()

将对象当初字符串在程序中使用时,会自动调用该方法,例如我们echo一个对象时将调用这个方法,如果不存在该方法,则出现错误。

7. __invoke()

当尝试以调用函数的方式调用一个对象时,__invoke 方法会被自动调用。

8. __set_state()

当调用var_export()导出类时,该方法被自动调用。

9. __clone()

复制对象时使用clone方法,在复制完成时,如果定义了__clone方法,则会自动被调用,可用于修改新复制对象的属性或进行初始化工作。

10. __autoload()

使用这个方法可以进行类的自动加载,比如我们可以在该方法中完成包含文件的自动加载。

autoload

怎么「写」产品在同类中具有的优势?

在交流中提及到一个经常碰到的问题,”同类的产品有很多,怎么写产品在同类中具有的优势?“。这样的场景经常会出现在工作当中的介绍产品的文档中,在这里往往都是在关注如何「写」,通常情况下都是赞誉自己的产品,贬低同类的产品,从而让自己的产品显得具有优势,达到往往并不能取得效果的结果。

在企业应用的系统中,这类的事情出现的很频繁,在以往的工作中频频碰到,而且也操刀写了不少如此这类的文档,如今想来,甚是惭愧。企业应用系统,尤其是管理类系统,多数以企业业务场景出发进行业务场景下的信息化工作,一般是对贯穿于企业业务流程及在流程中产生的数据进行管理,从而实行信息化管理。这样的系统从第一感官来看,往往都很相似,UI相似(框架),功能相似(业务),往往都是你家有的我家也有,如何「写」出产品比同类产品的优势就显得是重要的。刨除很特殊的关系这一层面的营销,现在我的看法可能会更多的受到互联网产品及移动产品的影响,不在于如何写,在于如何做。

最近几年互联网/移动互联网类的产品的变化是非常巨大的,可是看企业类的系统,最近这些年的变化却不甚明显,相当一部分都还停留在若干年前的状况,当然规模及功能上的变化是巨大的,看上去很复杂,功能聚合是越来越多,这些是看到的变化,看不到的是交互体验方面的变化。

从实际业务场景建立功能是第一步系统开发要做的,要切实的解决业务场景的需求,这是可以通过进入这个行业实际工作一阵子,或者寻求行业专家的支持,完成后,大部分系统都具有雷同的功能,毕竟都是解决同样业务的。

能够顺畅的完成业务场景的工作或许是大部分企信息化系统之间相互比拼的,随着时间的变化当功能越来越雷同和相似后,同时也有了初步的业务数据,这时候先行者就会抛出几个概念性的东西,凡是跟数据沾边的跨信息孤岛的其他范围就被纳入其中,然后做一些接口以便跟其他系统互通,这是第二步的工作。

随着接口的增多与各个系统之间的数据积累,基于数据的服务或许是第三步要做的工作,企业信息化系统这方面相对比较复杂,其复杂主要集中在各个系统数据接口的建立,然后是从整体上能够提供基于数据的分析、处理、归纳,从整体上提供服务,另外一部分是面对系统的升级带来的复杂性,这几方面共同作用下,让这些年来的企业信息化系统基本上停留在这个阶段,且存在不少实际上依旧互相并不互通的问题。

一般「写」产品优势就是从上面这三步出发,很多企业基本上没进入第二步就折戟沉沙,太过专注「写」,其实在「写」的同时,更应该关注做,做好每一步而不是「写」好每一步更能让企业持续的经营下去,而大部分企业,这里中小型企业居多更多的是关注写,不能沉下心来好好做,这样的企业不死谁死?所以还是在市场营销反馈良好的情况下,应该做好这些,从而自然写起来就有优势了。

同样的,这些年来企业信息化系统的交互体验同样不能获得重视,从交互性和体验性上来讲,往往开发这类系统的公司投入都相对较小,或者压根就不注意这些地方,这样的第一个要面对的就是在实施后的培训时间周期很长,而大多是基于操作层面的培训。最终使用用户使用体验比较差劲,相对比较生硬,亲和力比较低。持续的注重交互体验,让系统变得能够很大程度上提高效率应该是能让你的系统脱颖而出的很重要的优势,交互体验应该贯穿于整个企业信息化系统开发之中。或许也会是让你的企业信息化系统脱颖而出的开始。

前两天朋友在交流中问我“如何才能写出我现在的系统的优势?“,我给的建议是「根植于业务,向服务靠拢,产品体验贯彻整个过程」。做好这些就具有了水到渠成的优势,你的系统做到哪一步了?

mysqli中多语句查询insert_id和affected_rows

在php的mysqli中有多条SQL语句执行的函数multi_query,可以一次执行多条SQL语句,对于不返回结果集的SQL语句在使用中发现获取insert_id和affected_rows不能自动进行多语句的累加数据,还得配合more_results「是否还有结果集」和next_result「下一个结果集」来进行计算,按照预计的来讲对于不返回结果集的SQL语句来说,应该能直接返回最后插入的ID和受影响的行数,结果却不然,在此记录一下。

<!--?php
/*
 *  使用mysqli的多语句查询multi_query中获得最后插入ID和受影响的行数
 *  数据库表为shops,字段有id,name,price,nums,desc,id为子增长字段
 */
header('Content-Type: text/html; charset=utf-8');

$mysqli = new mysqli("localhost", "root", "liutao", "test");

if($mysqli--->connect_error) {
  echo '错误:' . $mysqli-&gt;connect_error;
  exit;
}

$sqls = "insert into shops(name,price,nums,desc) 
  values('笔记本','1.2','1000','B5 笔记本');
insert into shops(name,price,nums,desc) 
  values('0.5中性笔','1.8','30','0.5的黑色中性笔');
insert into shops(name,price,nums,desc) 
  values('档案袋','2.2','100','A4透明塑料档案袋');
insert into shops(name,price,nums,desc) 
  values('订书钉','3.5','50','订书钉');";

if($mysqli-&gt;multi_query($sqls)) {
  $affectRows = 1; 
  do {
    $affectRows += $mysqli-&gt;affected_rows;
    $mysqli-&gt;next_result();
  } while($mysqli-&gt;more_results());
  echo "执行成功!<br> 最后插入的id:{$mysqli-&gt;insert_id} <br> ";
  echo "共影响的行数:{$affectRows} <br>";
} else {
  echo '错误:' . $mysqli-&gt;errno . '(' . $mysqli-&gt;error . ')';
}

$mysqli-&gt;close();

?&gt;

执行结果:

mutiquery_id_affectedrows

常见的腻子脚本功能摘要

经常见到一些网站中用一些腻子脚本「polyfill」,对其主要的功能进行一下摘要记录。

html5shiv.js  让IE8及更低版本的IE浏览器识别section、article、nav等HTML5元素;
selectivizr 让IE6/7/8 支持:first-child 等CSS选择符;
CSS3Pie 让低版本的IE支持圆角、渐变、边框图片、阴影等可视化CSS3功能;
Respond.js 让旧浏览器支持媒体查询;
-prefix-free 为需要厂商前缀的CSS3声明增加前缀;
borderBoxModel.js 让IE6/7支持CSS3的box-sizing属性;

这些腻子脚本主要用于弥补IE及低版本浏览器的不足,在GitHub有一个腻子脚本列表,参见「这里」。