今天有一个玩家提到,每次游戏断线后,再进入都需要重新输入帐号名和密码。非常麻烦。
这里我想到了一个关于玩家体验的问题:
玩家希望是的流畅的玩游戏,包含在开始游戏时,可以快速的进入。
断线后能不退游戏最好。如果实在不行,要走登陆流程,至少也要避免掉玩家输入帐号名和密码。
今天有一个玩家提到,每次游戏断线后,再进入都需要重新输入帐号名和密码。非常麻烦。
这里我想到了一个关于玩家体验的问题:
玩家希望是的流畅的玩游戏,包含在开始游戏时,可以快速的进入。
断线后能不退游戏最好。如果实在不行,要走登陆流程,至少也要避免掉玩家输入帐号名和密码。
参考文章:
http://www.cnblogs.com/meteoric_cry/p/4598304.html
原因应该是:订单因为各种原因,没有记录finishTransaction,导致的无法继续进行支付。
正确的解决方案应该是:
检测未处理订单,进行处理。
FMOD Error (ERR_HTTP_PROXY_AUTH): Proxy authentication is required to access the specified resource. UnityEngine.Debug:LogWarning(Object) FMOD.Studio.UnityUtil:LogWarning(String) (at Assets/Plugins/FMOD/FMOD_StudioSystem.cs:53) FMOD.Studio.UnityUtil:ERRCHECK(RESULT) (at Assets/Plugins/FMOD/FMOD_StudioSystem.cs:120) FMOD_StudioSystem:ERRCHECK(RESULT) (at Assets/Plugins/FMOD/FMOD_StudioSystem.cs:401) FMOD_StudioSystem:Init() (at Assets/Plugins/FMOD/FMOD_StudioSystem.cs:274) FMOD_StudioSystem:get_instance() (at Assets/Plugins/FMOD/FMOD_StudioSystem.cs:153) TestLoading:Awake() (at Assets/scripts/config_model/TestLoading.cs:47)
这个错误之前遇到过一次。
这次遇到后忘记如何解决的了,白白费了半天工夫。这里记录下,免得自己又忘记了。
解决方式也很傻瓜式,把fmod的script及so,dll重新导入了一遍。
记录,避免自己忘记
1、http://bellard.org/bpg/ bgp压缩格式。
2、https://github.com/nagadomi/waifu2x 相关文章:http://blog.codingnow.com/2015/05/rgbyuv.html#more 卡通图片压缩格式
3、WebP google家的图片压缩算法,facebook也在使用。(注:cpu密集型,不适合游戏)
4、云风的ejoy2d使用的 ppm 和 pgm 格式。
韦一笑:
同信噪比情况下,图片尺寸: Jpeg > JPEG2000 > webp > hdphoto > BPG Webp:使用 vp8 I帧编码 hdphoto:微软自己私有格式,扩展名为wdp bpg:H.265 的I帧编码算法,应该是目前压缩效果最好的格式,具体对比见Fabrice 的个人主页:http://bellard.org/ 新格式一直都有,只是应用滞后了而已。比如google开源webp,挺好的,微软就是不买账,不支持。fabrice比较聪明,直接给他的bpg写了两套解码库:C的和javascript的,于是浏览器支持问题被解决了,只是各个网站跟进慢了而已。
bpg更好,png8 存alpha bpg存rgb,载入时自动生成并缓存成pvr,很多快速生成pvr的算法,webp弱爆了 游戏包里放bpg,然后弄一个pvr cache,读取时先找cache,没有就从bpg里转一份出来放倒cache中,只有一次转码,你担心啥呢,何况每次下载更新时边下边转,基本感觉不到
想起来了以前听过一次,说是如果将是全透或全不透,是否可以将alpha信息存在颜色信息的最后一位上。没有试过。可以测试下看看效果如何。
linux下两个好用的图像转换工具(自己造轮子太笨重了): ImageMagick和convert。
几个压缩图片的工具,图片会轻微失真,UI不建议用
https://tinypng.com/
https://tinyjpg.com/
http://www.gimp.org/
https://pngquant.org/
协议压缩:
1、https://code.google.com/p/snappy/ 可以考虑下这个。另外如果想要最优,可以考虑比较下各种压缩算法在实际项目中使用的效果。
注:如果游戏中对其它文件使用了压缩算法,需要专门测试一下以下几个方面
1、是否为系统原生提供,是否为第三方库方式提供。(c#如果有原生库速度会更快)
2、各种算法比较,主要比较的是速度和压缩比。如果是第三库可以考虑将crc32校验都去除。
3、是否有条件使用c/c++编译为so提供给mono使用。
又一篇关于压缩的文章:
https://zhuanlan.zhihu.com/p/21543787
项目压力测试,发现一个协议非常卡,吞吐量不足100/s,查看那个协议,发现是在玩家登陆成功后取玩家数据。
这个protobuf结构体 A 中定义了接近300个属性。
专门测试了一下,生成100000个对象,属性全不设置使用默认值,A结构体序列化是仅有几个属性的40倍消耗。
这个地方是我们之前没有想到的情况,不过这还不足已是瓶项的原因。
再继续确认,发现A里面有一个list,list中存放了271个B结构体。大约40%的时间都消耗在这里了。
基本上以下是我们之前未发现的:
1、protobuf属性多了会导致性能下载,既然属性值使用optional,而且不设置值。属性尽量控制在比较少的范围内。
2、属性多了后,感觉性能消耗是几何数级增加。
针对我们项目目前的情况,A结构体进行拆分不太可能,所以只把其中几个数量多的list拆分出来。把上面的271个使用另外一个协议发送,每次发送一条,总共发送271条。可能会感觉271条协议比一个协议要慢,实际上发现,这样做了后,问题顺利解决,271条比1条消耗的时间要小2个数量级,可能protobuf天生只适合小数据包的情况。
最近看了下数据流加密。
最初项目组采用了rc4加密,但双方密钥直接明文存储。被确解的可能性很大。
看了云风介绍了,使用dh进行rc4密钥交换,遂动手进行处理。
dh是非对称加密算法,用于交换密钥。
服务器使用java
客户端使用c#
采了几个坑:
1、java中pubkey使用X509格式存储,prikey使用PKCS8格式存储,如果要取到原始明文,需要使用:
public static Map<String, BigInteger> initKeyRaw() { try { KeyPairGenerator gen = KeyPairGenerator.getInstance("DH"); gen.initialize(KEY_SIZE); KeyPair keyPair = gen.generateKeyPair(); DHPublicKey dhPublicKey = (DHPublicKey) keyPair.getPublic(); DHPrivateKey dhPrivateKey = (DHPrivateKey) keyPair.getPrivate(); Map<String, BigInteger> ret = Maps.newHashMap(); ret.put("x", dhPrivateKey.getX()); ret.put("y", dhPublicKey.getY()); ret.put("p", dhPublicKey.getParams().getP()); ret.put("g", dhPublicKey.getParams().getG()); return ret; } catch (Exception e) { e.printStackTrace(); } return null; } public static Map<String, BigInteger> initKeyRaw(BigInteger y, BigInteger p, BigInteger g) { try { KeySpec keySpec = new DHPublicKeySpec(y, p, g); KeyFactory keyFactory = KeyFactory.getInstance("DH"); PublicKey pubKey = keyFactory.generatePublic(keySpec); DHParameterSpec dhParamSpec = ((DHPublicKey) pubKey).getParams(); KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyFactory.getAlgorithm()); keyPairGenerator.initialize(dhParamSpec); KeyPair keyPair = keyPairGenerator.generateKeyPair(); DHPublicKey dhPublicKey = (DHPublicKey) keyPair.getPublic(); DHPrivateKey dhPrivateKey = (DHPrivateKey) keyPair.getPrivate(); Map<String, BigInteger> ret = Maps.newHashMap(); ret.put("x", dhPrivateKey.getX()); ret.put("y", dhPublicKey.getY()); ret.put("p", dhPublicKey.getParams().getP()); ret.put("g", dhPublicKey.getParams().getG()); return ret; } catch (Exception e) { e.printStackTrace(); } return null; }
2、第二个坑
在网上找了一个c#版的dh源码,如果发现两边生成的key怎么都不对,最后定位到,java 中的biginteger是带符号位的。c#版中的biginteger是无符号位的,计算结果当然就不正确了。
我的解决方式是在java中转为biginterger前,添加“00”,这样避免了biginteger变为负数。
最近在做xcode自动打包的工具,遇到不少错误,列一下遇到错误的解决方案,以方便自己以后查看:
1、
2015-03-23 15:48:25.015 xcodebuild[10166:204416] [MT] DVTAssertions: Warning in /SourceCache/IDEFrameworks/IDEFrameworks-6611/IDEFoundation/SourceControl/Model/IDESourceControlManager.m:423 Details: Error Domain=com.apple.dt.IDESourceControlErrorDomain Code=-1 "Missing extension: public.vcs.subversion" UserInfo=0x7f84ace487c0 {NSLocalizedDescription=Missing extension: public.vcs.subversion} Object: <IDESourceControlManager: 0x7f84acd73ee0> Method: -loadRepositories Thread: <NSThread: 0x7f84aac35bc0>{number = 1, name = main} Please file a bug at http://bugreport.apple.com with this warning message and any useful information you can provide.
只是一个警告,原因和svn有关,可以直接忽略。
2、
User interaction is not allowed。
这是网上很多人遇到问题。
是因为苹果因为安全原因,默认不允许ssh登陆读取keychain。
这里使用http://www.egeek.me/2013/02/23/jenkins-and-xcode-user-interaction-is-not-allowed/提供的解决方法。
#允许使用login.keychain security unlock ~/Library/Keychains/login.keychain #修改过期时间 security set-keychain-settings -t 3600 -l ~/Library/Keychains/login.keychain #查看修改后的时间 security show-keychain-info ~/Library/Keychains/login.keychain
xcode 自动打包的原理很简单:
1、使用xcodebuild编译工程。
2、使用xcrun -sdk iphoneos PackageApplication,打包为ipa。
unity版本 4.3.1
为了减少发热量,我们游戏对分辨率进行的缩减,但在缩小的那一祯可以明显看到闪烁。
参考了一些文章,了解了下闪烁的原因:
1、在unity启动时默认是使用上层layout的width/height,游戏基本上都是全屏,所以上来就是全屏显示。
2、在unity中使用Screen.SetResolution,可以调整分辨率,反编译unity android层代码可以看到是调用了surface.setFixedSize,就是这里的原因,在调整期间会闪屏。
既然默认使用的是上层layout的width/height,我们直接修改上层的layout不就OK了?噢,不行,layout是指实际显示的分辨大小,我们的目标是指渲染的界面要小,然后通过缩放进行全屏显示。
所以只能使用surface.setFixedSize方法,那这样只需要在调整分辨前在main acitivity.onCreate方法中设置上就OK了。
查看了unityplayer.surcefaceview,发现是私有的。私有的也难不倒我们,直接使用反射取出私有变量。
需要同时在onCreate和onConfigurationChanged中修改。
修改完后发现触点和unity中的对应不上了,检查一下问题:
1、发现unity中触点是设置的缩小分辨率后对应的,但如果将竖屏和横屏切换一下,即可正确对应上,应该是在oncreate调整分辨率后还需要调整触点。
上述错误。经过很辛苦的查找,终于查找到原来是unity中提供的classes.jar有bug。反编译后,发现:
protected void triggerResizeCall() { Log.i("hack unity", "triggerResizeCall v:" + v + " w:" + w + " v:" + v + " w:" + w); this.nativeResize(this.v, this.w, this.v, this.w); }
这里第三个参数和第四个参数应该使用屏幕的大小,而不应该是使用分辨率的大小。坑啊。
找到原因就好处理了,hack掉unityplayer,重新提供一个triggerResizeCall,完美解决闪屏问题。
实际上调整分辨率闪屏还有很多更便捷的解决方法,比如unity的splash image设置为全黑,然后在第一个场景加载时,调用分辨率玩家就看不到闪屏了,反正都是黑的,在第一个场景调整完分辨后,再伪造显示一个splash image,哈哈。
附github:
unity classes.jar 反编译后的源码:https://github.com/zhukunqian/unity_java_4_3_1/tree/master
demo 代码:https://github.com/zhukunqian/unity_scale_resolution
参考文章:
1) http://stackoverflow.com/questions/7185644/android-opengl-crazy-aspect-ratio-after-sleep
2)http://android-developers.blogspot.it/2013/09/using-hardware-scaler-for-performance.html
http://android-developers.blogspot.it/2013/09/using-hardware-scaler-for-performance.html
项目中字符串配置表是最大的一张表,足足有一万多条记录。
我们目前的存储方式是按csv类似格式存为scriptableobject。这张表的解析基本上占用总解析时间的25%~35%,因此优化这张表非常有必要。
查看了下text表中。其中重复内容大概按25%左右。因为表是按key,value键值对存储,计算了下key占用了45%的空间,这里优化的余地非常大。
1、不再存储key,而是将key改为int型的hashcode,这样,可以节省45%的空间
以下是java中的hashcode实现,测试了下,目前没发现有重复。
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
2、针对有重复的value的情况,另存一个Map<hashcode,hashcode>,如果发现在map中存在当前使用的hashcode,则替代为使用map中的对应的value hashcode去查找。这样可以再减少25%的空间。
近期评论