分类存档: game-game - 第2页

关于游戏的登陆

今天有一个玩家提到,每次游戏断线后,再进入都需要重新输入帐号名和密码。非常麻烦。

这里我想到了一个关于玩家体验的问题:

玩家希望是的流畅的玩游戏,包含在开始游戏时,可以快速的进入。

断线后能不退游戏最好。如果实在不行,要走登陆流程,至少也要避免掉玩家输入帐号名和密码。

 

 

ios上 “已购买此 App 内购买项目 此项目将免费恢复” 解决方案

参考文章:

http://www.cnblogs.com/meteoric_cry/p/4598304.html

原因应该是:订单因为各种原因,没有记录finishTransaction,导致的无法继续进行支付。

正确的解决方案应该是:

检测未处理订单,进行处理。

fmod ERR_HTTP_PROXY_AUTH

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

protobuf使用遇到一个坑

项目压力测试,发现一个协议非常卡,吞吐量不足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打包User interaction is not allowed

最近在做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调整分辨率在android下闪屏

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

一篇优化android 性能的文章

http://android-developers.blogspot.it/2013/09/using-hardware-scaler-for-performance.html

text配置表优化

项目中字符串配置表是最大的一张表,足足有一万多条记录。

我们目前的存储方式是按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%的空间。