ios 上sigpipe需要屏蔽

ios号sigpipe会导致app被杀死。

因此需要对sigpipe进行屏蔽。

 

signal(SIGPIPE, SIG_IGN)

如果连xcode进行调试,还会继续捕获sigpipe,但不影响app,点击继续即可。

测试下unity中的异常在各平台上的表现

测试目的:

测试异常在android及ios64下的表现,查看是否导致闪退或崩溃。

测试代码:

	private void onclick1( ){
		Debug.Log("click1");
		int m=3;
		int n=0;
		Debug.Log(m/n);
	}
	private void onclick2( ){
		Debug.Log("click2");
		TestA test=null;
		Debug.Log(test.m);
	}

在unity editor中:

表现正常,没有导致app死掉。

在Android中:

可以在ddms中收集到异常,同时app没有崩溃。

在IOS中:

也是可以正常打出log及堆栈

发现也没有引起崩溃。

IOS上32位mono闪退的原因找到了:

解决方案:

http://developer.xamarin.com/guides/ios/troubleshooting/troubleshooting/

unity中计算使用的时间

基本上有几种方式

1、DateTime.UtcNow,性能好,速度快,但是精度低一此,10ms左右

2、第二种是用StopWatch,但是据称在多核多线程环境会有时有误差。

3、Process.GetCurrentProcess().TotalProcessorTime;时间准确度高,但相应的是性能较低下。可以使用宏定义,在测试版本中才开启,在正式发布版本中关闭这个功能。

噢,我们用时间,主要是用来埋点查看性能热点的地方。

fmod在ios64上无声音的问题

以前解决一个加载慢的问题时,发现fmod写的加载代码很差,尤其在android平台,做了很多无用功。

于是我就重写了fmod加载代码,使用www异步加载,加载的字节数组放在cache中,然后供fmod调用:

FMOD.RESULT result = FMOD_StudioSystem.sInstance.System.loadBankMemory(pair.Value,LOAD_BANK_FLAGS.NORMAL,out bank);

结果发现在ios上无法播放声音。

开始怀疑过il2cpp的问题,但是没有log,不能随便下定论。

添加过很多log后,定位到上面的函数出问题了,但是log中只记录执行到这里就没了。没有输出为什么错。

丝毫没有头绪后,在fmod官方发现有新版本了,下载新版本后,测试下,发现还是没有声音,但是至少有异常log了。

il2cpp暂时不支持从c/c++对c#进行调用,或者说至少不支持现在fmod的用法。

解决方法也很简单,修改为使用

	FMOD.RESULT result = FMOD_StudioSystem.instance.System.loadBankFile(bankPath, LOAD_BANK_FLAGS.NORMAL, out bank);

 

网上还有一个哥们遇到同样问题了,关注下看看他怎么解决。

http://forum.unity3d.com/threads/making-calls-from-c-to-c-with-il2cpp-instead-of-mono_runtime_invoke.295697/

 

看到一篇文件比较的unity下的各种调用的性能

http://forum.unity3d.com/threads/pinvoke-mono_add_internal_call-c-and-c.172886/

以备自己学习用。

这里还有一篇:http://www.snowbolt.com/index.php/blog/28-tech/91-pinvoke

目前看起来,mono要比c/c++慢一个数量级,lua又比mono慢一个数量级。

如果想要最好的性能,应该还是lua直接建在c/c++上,但是又如何去调用MonoBehaviour,如果能跳过mono,直接通过c/c++调用,则性能应该是最优的。但是需要确认下如何调用?

如果能实现,则是c/c++ + lua,直接跳过了 mono。

还有不确定的因素:il2cpp会不会可以直接实现这些性能提升?未来 需要确认下。

网上有位兄弟反编译的unity editor,看了下,不知道能否实现 lua 直接像调用c接口一样来调用MonoBehaviour.

namespace UnityEngine
{
    using System;
    using System.Collections;
    using System.Runtime.CompilerServices;

    public class MonoBehaviour : Behaviour
    {
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern MonoBehaviour();
        public void CancelInvoke()
        {
            this.Internal_CancelInvokeAll();
        }

        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern void CancelInvoke(string methodName);
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        private extern void Internal_CancelInvokeAll();
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        private extern bool Internal_IsInvokingAll();
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern void Invoke(string methodName, float time);
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern void InvokeRepeating(string methodName, float time, float repeatRate);
        public bool IsInvoking()
        {
            return this.Internal_IsInvokingAll();
        }

        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern bool IsInvoking(string methodName);
        public static void print(object message)
        {
            Debug.Log(message);
        }

        public Coroutine StartCoroutine(IEnumerator routine)
        {
            return this.StartCoroutine_Auto(routine);
        }

        public Coroutine StartCoroutine(string methodName)
        {
            object obj2 = null;
            return this.StartCoroutine(methodName, obj2);
        }

        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern Coroutine StartCoroutine(string methodName, object value);
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern Coroutine StartCoroutine_Auto(IEnumerator routine);
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern void StopAllCoroutines();
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern void StopCoroutine(string methodName);

        public bool useGUILayout { [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall] get; [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall] set; }
    }
}

大计算量的代码,尽量避免使用c#代码,能用c/c++实现,就使用c/c++实现,然后暴露接口给c#层使用。

No matching provisioning profiles

这个错可能是证书或签名出问题了。

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重新导入了一遍。

unity中的streaming文件路径

	IEnumerator test1(){
		String filePath1=Application.streamingAssetsPath+"/Boss.bank";
		String filePath2="file:///"+Application.streamingAssetsPath+"/Boss.bank";
		String filePath3=System.IO.Path.Combine(Application.streamingAssetsPath,"/Boss.bank");
		String filePath4=System.IO.Path.Combine(Application.streamingAssetsPath,"Boss.bank");


		textbox1.label.text=filePath1+"\n\n"+filePath2+"\n\n"+filePath3+"\n\n"+filePath4+"\n\n";

		textbox1.label.text+=File.Exists(filePath1)+"\n";
		textbox1.label.text+=File.Exists(filePath2)+"\n";
		textbox1.label.text+=File.Exists(filePath3)+"\n";
		textbox1.label.text+=File.Exists(filePath4)+"\n";

		WWW www1=new WWW(filePath1);
		yield return www1;

		WWW www2=new WWW(filePath2);
		yield return www2; 

		WWW www3=new WWW(filePath3);
		yield return www3;

		WWW www4=new WWW(filePath4);
		yield return www4;

		textbox1.label.text+=www1.bytesDownloaded+" "+www1.error+"\n";
		textbox1.label.text+=www2.bytesDownloaded+" "+www2.error+"\n";		
		textbox1.label.text+=www3.bytesDownloaded+" "+www3.error+"\n";		
		textbox1.label.text+=www4.bytesDownloaded+" "+www4.error+"\n";
	}

 

PC 运行如图:

android手机运行如图:

如果在unity中取文件:

string filePath = System.IO.Path.Combine(Application.streamingAssetsPath, "csv/"+configName);
		byte[] result=null;
		if (filePath.Contains("://")) {
			WWW www = new WWW(filePath);
			yield return www;
                        while(!www.isDone()){
                             yield return null;
                        }
			result = www.bytes;
		} else {
			result = System.IO.File.ReadAllBytes(filePath);
		}

如果在unity中想全部用www取文件

string filePath3 = Application.streamingAssetsPath + "/bt2/android/";
         if (!filePath3.Contains("://"))
         {
            filePath3 = "file:///" + filePath3;
         }

在android下需要注意,因为apk本身是压缩格式,无法直接用File取文件,必须用www取文件。

用www取文件注意格式,一定要等www.isDone

今天查找unity中加载配置表卡的问题(二)

接上一重篇:

http://blog.zhukunqian.com/?p=1234

上次修改完成后,配置加载已经非常快了, 但发现了另外一个现象,在检查配置更新时会卡上约6秒左右。

检查更新做的事情很简单,就是去网上请求一个静态文件,这里为什么卡成这样。

添加了一些埋点代码记录运行的时间后发现,卡在了加载音频那里,游戏中的音频有30M,而且那里是同步加载 -.-!! ,现在需要对音频进行拆分,

1、一部分需要在登陆前加载,比如UI上绑定的音频之类(按钮声)

2、一部分需要在战斗前加载成功,比如战斗中的音频

3、一部分需要异步加载,比如背景音乐之类

4、一部分只需要用时再加载,用完立即释放掉,比如人物对话音频之类。

另外在splash image后第一个场景需要update执行完后才会显示出来,因此有些非常耗时的操作避免在第一次update时执行。

图片格式压缩

记录,避免自己忘记

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/

协议压缩:

1、https://code.google.com/p/snappy/  可以考虑下这个。另外如果想要最优,可以考虑比较下各种压缩算法在实际项目中使用的效果。

 

注:如果游戏中对其它文件使用了压缩算法,需要专门测试一下以下几个方面

1、是否为系统原生提供,是否为第三方库方式提供。(c#如果有原生库速度会更快)

2、各种算法比较,主要比较的是速度和压缩比。如果是第三库可以考虑将crc32校验都去除。

3、是否有条件使用c/c++编译为so提供给mono使用。