为什么在帧率低的情况下,帧事件会提早回调的?

理论上?怎么说?

cocos引擎中,director的runloop,当前帧率超过你预设的就sleep一阵子,而帧率不足就只是一直run而已,逻辑还是会走完了,不需要处理掉帧的情况。
而在flash中,掉帧是要处理掉帧过程的逻辑的。

尝试用3.4beta0测试没出问题吗?

刚尝试用3.4beta0,然后也修复了你的那个cctimeline的bug,还是不行。我也用2.1的cocostudio重新导出过资源,那个问题还是存在。
end的帧事件回调的时候,我把frame的frameIndex输出来,确实是114,但是跟cocos引擎跑过的帧数对不上。
还是那个老问题,帧数低的时候,明明那个动画是22帧的,但只跑了10帧不到。
然后我看ccactiontime的源码,发现时间间隔是写死了1/60?

但我上次用3.3final的时候,在debug模式下,掉帧环境也出现了这个问题了。应该和我主动把帧率设成20帧没关系吧?

这个能解决吗?我怕以后掉帧的时候会出现问题.

可否提供你的代码我瞧瞧。
我有空的时候会测试下。

因为是公司内部代码,不能发出来,我写了一个demo让你测试下,好吗?
资源还是那只鲨鱼,flash转cocos的那个例子的。

帧事件:
我在鲨鱼的generalshark_left_foot部件(第一个)的68帧添加了一个start事件,151帧添加了一个end事件。

环境:
Cocos2dx-3.3final,CocoStudio2.05,CocosCodeIDE1.10

代码如下:

cc.FileUtils:getInstance():addSearchPath(“src”)
cc.FileUtils:getInstance():addSearchPath(“res”)

– CC_USE_DEPRECATED_API = true
require “cocos.init”

– cclog
local cclog = function(…)
print(string.format(…))
end

– for CCLuaEngine traceback
function G__TRACKBACK(msg)
cclog("----------------------------------------")
cclog(“LUA ERROR: " … tostring(msg) … “\n”)
cclog(debug.traceback())
cclog(”----------------------------------------")
return msg
end

local function main()
collectgarbage(“collect”)
– avoid memory leak
collectgarbage(“setpause”, 100)
collectgarbage(“setstepmul”, 5000)

-- initialize director
local director = cc.Director:getInstance()

--turn on display FPS
director:setDisplayStats(true)

--set FPS. the default value is 1.0/60 if you don't call this
director:setAnimationInterval(1.0 / 60)

cc.Director:getInstance():getOpenGLView():setDesignResolutionSize(1280, 720, 1)

--create scene
local gameScene = cc.Scene:create();

if cc.Director:getInstance():getRunningScene() then
    cc.Director:getInstance():replaceScene(gameScene)
else
    cc.Director:getInstance():runWithScene(gameScene)
end

local i = 1;
cc.Director:getInstance():getScheduler():scheduleScriptFunc(function(dt)
    i = i + 1;
end,0,false);

local node = cc.CSLoader:createNode("generalshark.csb");
local action = cc.CSLoader:createTimeline("generalshark.csb");
node:runAction(action);
gameScene:addChild(node);
node:setPosition(150,100);
action:setFrameEventCallFunc(function(frame)
    local index = frame:getFrameIndex();
    local event = frame:getEvent();
    print(string.format("frames:%i index:%i event:%s",i,index,event));
end);
action:gotoFrameAndPlay(68,151,false);

end

local status, msg = xpcall(main, G__TRACKBACK)
if not status then
error(msg)
end

输出:
frames:1 index:68 event:start
frames:208 index:151 event:end
因为这个资源是24fps的,所以它把83帧的动画拉到207帧,这是没问题的。
因为只有一只怪,在debug模式下也不能模拟掉帧的情况,所以我把帧率调成20帧。
director:setAnimationInterval(1.0 / 20)
输出:
frames:1 index:68 event:start
frames:69 index:151 event:end
问题就来了,cocos引擎只跑了68帧,end事件就回调出来了。

方便把那个鲨鱼的资源上传上来么?
我这儿没有flash没法转。

flash是这个:
http://www.cocoachina.com/bbs/read.php?tid-236927-keyword-flash.html
如果要csd的话,我今晚回家再上传吧。

嗯,好的!

昨天回去竟然忘了这件事了。

你所谓的跑了10帧就回调帧事件是什么意思?
是在引擎中mainLoop跑了10次还是动画走了10帧?

那个动画正常情况下,start与end事件回调间隔,引擎中mainLoop应该要跑207帧才对。
而在掉帧到20fps的时候,start与end事件回调间隔,引擎中mainLoop跑了才68帧。
在cocos中,cocostudio的动画不是按照引擎的mainLoop来跑的吗?

如果你不修改动画播放速度的话,这个动画不管你mainLoop每秒多少帧,动画的播放时间都是固定的。

那么在掉帧的环境下,还能保证逻辑的完整性吗,每个用户的手机的mainloop每秒多少帧都是不固定的,而cocostudio的动画却先播完了,显然不合理啊。

— Begin quote from ____

引用楼主panzhihao51于2015-01-14 15:45发表的 为什么在帧率低的情况下,帧事件会提早回调的? :
cocostudio2.06+cocos2dx-3.3final
我把flash的动画导到cocostudio,例子和插件都是论坛的那个。
然后我播放一个动画是从92帧到114帧的,一共22帧,在92帧加了一个start的帧事件,在114帧加了一个end事件。
在60帧是没什么问题的,但我把游戏引擎的帧率从60帧设到20帧,发现动画跑了10帧左右就回调end事件了,没有跑足22帧,求解。 http://www.cocoachina.com/bbs/job.php?action=topost&tid=281695&pid=tpc

— End quote

楼主,你遇到的这个现象并不是一个bug,你需要理解CocosStudio和Cocos2d-x里不同的帧概念。

在CocosStudio下面的动画面板,如果显示出动画长度是60帧,那么这个动画的总时长不一定是1秒。

只有当csd的帧速率是1的时候才是1秒。
楼主的鲨鱼测试例里,帧速率是0.4,因此导入到CocosStudio中,会发现1秒钟的时间下面的动画面板跑了24帧。
动画的总时长是帧速率1.0时的2.5倍。

Cocos2d-x的FPS指的是每秒渲染多少帧,即使调用setAnimationInterval改变程序的FPS,动画的总时长也不会改变。

帧速率0.4(也就是楼主所说的24FPS)的动画83帧,总时长为83/24秒。引擎用60的FPS跑这个时长的动画,则引擎一共渲染了6083/24≈221帧,楼主实测207帧,可能是因为性能不够,引擎没有跑满60FPS。
当楼主把引擎限制为每秒渲染20帧,则跑这段动画时,引擎一共渲染了20
83/24≈69帧,接近楼主实测的68帧,因为引擎跑满20FPS还是无压力的。

综上,楼主能够理解遇到的现象了吗?

看了楼上和东杨的解析,我理解了。
就是说cocostudio的动画播放时间无论在引擎帧率是多少的情况下,在真实世界的时间是一样的。

可以用setTimeSpeed 修改播放速度

没有自动适应cocos引擎的每秒帧率的办法吗?帧率低的时候帧事件会跳过吗?

这个需要改源码,有个计算这次loop跑了多少帧的地方,改成固定1就行