这次要来说一个吹水的话题,关于性能方面,最近在用Cocos2d-x + Lua写一个小游戏,因为实在太简单,就完全没想过会有什么掉帧的情况。

结果一到手机上运行,在关卡场景里的帧率立刻降低了,大概只有16到30帧,这个帧率对这个游戏来说,实在是有点可怕。

找了一下原因,凶手是某个update函数,因为每帧都要调用,遍历200到400个对象,主要是做碰撞检测,就在这里帧率下降了一半。
优化也很简单,把当前不在屏幕范围的对象都忽略碰撞就好了。
可奇怪的是,帧数还是不够高,于是,我发现了一个小问题…
来自未来的PS:
  今天收到偶尔e网事发来的贺电,才知道这不是lua binding的性能缺陷,而是Cocos Code IDE的bug~!
我想了这么个奇葩的解决方案、还花了这么多时间写这篇文章,原来都是假的!只是一个Bug而已。
  没关系,我已经醉了。
   这个Bug会引起debug模式下效率问题,下个版本的Cocos Code IDE会解决。
  以下的文章正文内容,大家就随意看看吧,关于lua binding的观点是错误的,就当娱乐吧~

By 木头 2014.09.29 10:53

1.那些Lua-binding
我们都知道,Cocos2d-x的API大部分都绑定到lua里了,可以直接使用。
而我的问题就出在这里了,通过lua去调用c++,这之间的损耗我没有去研究过。
但有一点,这之间的损耗比直接调用lua里的table大多了。

我们来看看这样一个测试吧:
        -- 随便创建500个Node
        local nodes = {};
        for i = 1,500 do
            nodes[i] = cc.Node:create();
            layerMenu:addChild(nodes[i]);
        end
        -- 注册update函数
        self:scheduleUpdateWithPriorityLua(function(dt)
            local pos = nil;
            local size = nil;
           
            -- 遍历所有节点,仅仅是进行了获取坐标和大小的操作
            for index,node in pairs(nodes) do
                pos = node:getPosition();
                size = node:getContentSize();
            end
        end,0);

这段代码是在一个Layer里的,模拟的就是我游戏里的情况(当然,这里简化了很多)。
创建了500个Node节点,然后在update函数里遍历这些节点,取出它们的坐标和大小,就这么简单的操作。
然而,如果在电脑上用调试模式(这样才更接近手机环境)运行游戏,帧数是这样的:

cocos2dxluabinding1
虽然电脑的数据不能说明什么,但是,我移植到手机上的情况也是不容乐观的,帧数也很低。
经过测试,造成帧数低的凶手就是getPosition和getContentSize函数,是的,我完全没有想过竟然是它们T_T,我是如此的信任…



2.简单的处理,让帧数飞回来
当然,我这代码每帧都要执行,所以才这么损耗帧数,但从另一个角度来说,我无法接受凶手竟然是两个不起眼的函数。
所以,我要解决它。
看如下代码:
 -- 随便创建500个Node
    local nodes = {};
    for i = 1,500 do
        nodes[i] = cc.Node:create();
        nodes[i].pos = cc.p(100,200 * i);
        nodes[i].size = nodes[i]:getContentSize();
        layerMenu:addChild(nodes[i]);

    end
    -- 注册update函数
    self:scheduleUpdateWithPriorityLua(function(dt)
       local pos = nil;
       local size = nil;
        -- 遍历所有节点,仅仅是进行了获取坐标和大小的操作
        for index,node in pairs(nodes) do
            pos = node.pos;
            size = node.size;
        end
    end,0);

注意,我只是改动了一点点,在创建Node节点的时候,我使用pos和size字段将节点的坐标和大小预先保存起来了。
接着,在遍历节点坐标和大小时,就仅仅是从table中取值了。

结果,帧数的情况如下:


cocos2dxluabinding2
怎么样,这变化实在是太大了。

3.一些小麻烦
不管怎么说,我这次的优化算是建立在一个奇怪的基础上?
又或许是我这个游戏实在是太简单了(逻辑上),仅仅只有碰撞检测和一些简单的碰撞处理。
我也想过,不要每帧都这么遍历一次,可以间隔一小段时间进行遍历。
但又觉得,还是每一帧都遍历比较好,避免造成其他的bug。
由于我这游戏里参与碰撞检测的对象基本上是不会动的,也基本不会改变大小,所以把坐标和大小这么特殊处理,也不会造成管理上的麻烦。
并且,只是针对特定的对象才进行这些处理。
另外,经过这么处理之后,我这游戏即使在跑分8000的安卓机器上,也能基本维持58帧/s了。
当然,缺点呢?这么处理的话,就要自己另外处理对象的坐标和大小属性了,不能使用原来的getPosition、setPosition之类的。
关于这些的细节处理,我就不多说了,如果你也希望这么处理的话,可以给我留言~我再简单说说实现的思路,其实很简单的。
总而言之,我的目的只是,想表达一下我的惊讶——竟然是getPosition成为了我这游戏的性能障碍。


4.结束
今天的文章可能写得比较死板、难懂,这是因为我最近有点累,也好多天没写文章了。

嗯,就这样吧。

原文地址:http://www.benmutou.com/archives/1844

Cocos2d-x-Lua出乎意料的性能短板——那个getPosition的binding的更多相关文章

  1. 初识Swift集合之字典集合

    这个函数也会返回被替换或者增加的值。

  2. swift的一些知识点演练

    表示可以有值,也可以没有值//?如果对象为空,就不会调用后面的方法,感觉上和oc中给nil发送消息类似varstr:Nsstring?str="hello"//打印可选项的时候,同时会输出一个Optional,提示开发者,这是一个可选项println(str?.length)letl=10//目前的代码存在什么风险?如果str没有设置初始值,会直接崩溃//苹果把判断对象是否有内容的工作交给了程序员//letlen=l+str!用来快速判断对象是否为nilletlen2=l+(str?0)//以下代码和上面

  3. swift 基础笔记四数组

  4. Swift值字典使用

    字典是一种用来存放相同类型的数据项的集合。Swift中字典的概念和现实世界中的字典的概念很相似,都是通过索引来查里面特定的值。修改一个值5、删除字典键值对四、字典遍历同数组一样,字典遍历也需要使用forin循环。

  5. Swift学习笔记十三——区间运算符和for-in循环

    区间运算符RangeOperator也是Swift的一个比较突出的特点。可以用来表示一段数据的区域。区间运算符主要可以分为以下两类:ClosedRangeOperator:闭区间[a,b]a...b:注意:a和b之间是三个点Half-ClosedRangeOperator:前闭后开区间a..

  6. Swift遍历数组的三种方式

    1.forindexin0..

  7. Swift入门五——数组Array

    集合集合的定义Swift中提供了两种数据结构用于存放数据的集合,分别是数组和字典。一共有三种方法来定义数组的类型:第一种是数组类型的完整定义,即Array关键字加上一对尖括号,括号内写上数组元素的类型。1]其实是一个SubArray,在Swift中它的类型叫做ArraySlice,即Int类型的数组切片,而右边是一个Array类型变量,根据Swift类型安全的特性,这样的操作自然是被禁止的。

  8. swift-07-使用for-in 遍历数组

    //for-in/*for迭代变量in集合变量{使用迭代变量便利所有数据}*///遍历数组vararr=["a","b","c","d"]fortempinarr{printprint}//vararray:[]=[,("王三",30,("张浩",50,"女")]forvinarr{ifv.0=="王三"{print(v)break}}

  9. Swift 字典的常用方法

    /***要正确使用字典,也需要一些条件*1,字典键值对的键和值的类型必须明确,可以直接指定,也可以类似数组直接赋值由编译器自动识别*2,字典必须要初始化*3,键的类型必须是可以被哈希Hashable的**///字典的几种声明方式常用方法见下方代码苹果开发群:414319235欢迎加入欢迎讨论

  10. Swift中实现Array数组和NSArray数组的相互转换与遍历

    Array是Swift中的数组数据类型,而NSArray是OC中的数组数据类型,两者有区别有联系。在Swift中有时候难免会使用到OC中的一些东西,今天我们就来Swift中使用NSArray和Array,并且进行转化。可见NSArray数组也可以在Swift中直接进行声明并进行遍历。

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部