LibGDX中Actions随点击累积错误致对话框动画卡顿问题排查
问题根源与解决方案
嘿,这问题我太熟了——你这卡顿完全是重复累积的监听器和未清理的动画动作搞的鬼!咱们一步步拆解:
1. 重复添加点击监听器是核心元凶
你每次触发touchDown时,都给button_close新建一个ClickListener并添加进去:
button_close.addListener(new ClickListener() { ... });
点10次就会有10个监听器绑定在按钮上!每次点击关闭时,这10个监听器会同时触发,导致对话框执行10遍关闭动画,动作队列直接炸了,不卡才怪。
解决办法:
把监听器的绑定逻辑移到touchDown外面——比如在win_dialog_01_1的初始化代码里只加一次,或者每次添加前先移除旧监听器:
// 先清除旧监听器,再添加新的(如果必须在touchDown里加的话) button_close.clearListeners(); button_close.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { // 你的关闭逻辑... } });
2. 重复将对话框添加到Stage
每次touchDown都执行stage_dialogs.addActor(win_dialog_01_1),如果对话框已经在Stage里了,重复添加会导致Stage多次渲染同一个Actor,额外消耗性能。
解决办法:
添加前先判断对话框是否已经在Stage中:
if (!win_dialog_01_1.hasParent()) { stage_dialogs.addActor(win_dialog_01_1); }
3. 未清理残留的动画动作
每次打开/关闭对话框时,没有清空之前可能未完成的动画动作,导致新动作和旧动作叠加执行,动作队列越堆越长。
解决办法:
在添加新动作前,先清空对话框的现有动作:
// 打开对话框前清空残留动作 win_dialog_01_1.clearActions(); win_dialog_01_1.addAction(Actions.fadeOut(0)); win_dialog_01_1.addAction(Actions.parallel(Actions.fadeIn(.2f), Actions.scaleTo(1.05f, 1.05f, .2f))); win_dialog_01_1.addAction(Actions.sequence(Actions.delay(.2f), Actions.scaleTo(1, 1, .2f)));
修改后的简化代码示例
@Override public boolean touchDown(int screenX, int screenY, int pointer, int button) { vector2 = new Vector2(screenX, Gdx.graphics.getHeight() - screenY); if (sprite_1.getBoundingRectangle().contains(vector2)) { switch (serverClass.point1) { case 0: Gdx.app.log("1", "drops"); win_dialog_alpha_white.clearActions(); win_dialog_alpha_white.addAction(Actions.fadeIn(.2f)); // 确保对话框只被添加一次 if (!win_dialog_01_1.hasParent()) { stage_dialogs.addActor(win_dialog_01_1); } win_dialog_01_1.setModal(true); // 清空残留动作再添加新动画 win_dialog_01_1.clearActions(); win_dialog_01_1.addAction(Actions.fadeOut(0)); win_dialog_01_1.addAction(Actions.parallel(Actions.fadeIn(.2f), Actions.scaleTo(1.05f, 1.05f, .2f))); win_dialog_01_1.addAction(Actions.sequence(Actions.delay(.2f), Actions.scaleTo(1, 1, .2f))); // 只绑定一次监听器(建议移到初始化代码中) if (button_close.getListeners().isEmpty()) { button_close.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { win_dialog_alpha_white.clearActions(); win_dialog_alpha_white.addAction(Actions.fadeOut(.3f)); win_dialog_01_1.setModal(false); win_dialog_01_1.clearActions(); win_dialog_01_1.addAction(Actions.parallel(Actions.fadeOut(.4f), Actions.scaleTo(1.05f, 1.05f, .2f))); win_dialog_01_1.addAction(Actions.sequence(Actions.delay(.2f), Actions.scaleTo(1, 1, .2f))); } }); } break; // 其他case... } } return super.touchDown(screenX, screenY, pointer, button); }
按照上面的方法改完,你再测试个几十次开关,应该就不会卡顿了——本质就是别让重复的监听器和动作在内存里堆着,每次操作前做好清理和判断就行。
内容的提问来源于stack exchange,提问作者Retron
相关产品推荐
相关产品推荐

