В Scene2d, когда действие завершено, оно удаляется из актера, но не возвращается в пул
В Scene2d, когда действие завершено, оно удаляется из субъекта, но не возвращается в пул.
Action.class
/** Sets the actor this action will be used for. This is called automatically when an action is added to an actor. This is also
* called with null when an action is removed from an actor. When set to null, {@link #reset()} is called.
* <p>
* This method is not typically a good place for a subclass to query the actor's state because the action may not be executed
* for some time, eg it may be {@link DelayAction delayed}. The actor's state is best queried in the first call to
* {@link #act(float)}. For a TimedAction, use TimedAction#initialize(). */
public void setActor (Actor actor) {
this.actor = actor;
}
/** Resets the optional state of this action to as if it were newly created, allowing the action to be pooled and reused. State
* required to be set for every usage of this action or computed during the action does not need to be reset.
* <p>
* The default implementation calls {@link #restart()}. Also, if the action has a {@link #setPool(Pool) pool} then the action is
* {@link Pool#free(Object) returned} to the pool.
* <p>
* If a subclass has optional state, it must override this method, call super, and reset the optional state. */
public void reset () {
restart();
if (pool != null) {
pool.free(this);
pool = null;
}
}
Кажется, что метод Action reset () (который является единственным местом, где выполняется отправка в пул)(1), он никогда не вызывается, когда очищается массив действий Actor, и впоследствии резервное копирование в пул не происходит...
(1) - В предыдущих версиях мы могли переопределить метод finish() и отправить действие в пул, но метод, которого он больше не поддерживает...
Я получил эту проблему, когда попытался расширить класс Action на этот:
TimelineAction.class
/**
* Timeline action runs a Timeline (separate from the TweenManager to avoid a second manager/loop cycle)
* with Scene2d
*/
public class TimelineAction extends Action {
private static final Pool<TimelineAction> pool = new Pool<TimelineAction>() {
@Override
protected TimelineAction newObject() {
Gdx.app.log("LOG", "TimelineAction action = new TimelineAction();");
TimelineAction action = new TimelineAction();
return action;
}
};
private Timeline timeline;
private boolean done;
/**
* Get instance from pool.
*
* @param timeline
* The associated tween.
*
* @return Pooled instance.
*/
public static TimelineAction createTimelineAction(Timeline _timeline) {
TimelineAction action = pool.obtain();
action.setPool(pool);
action.setTimeline(_timeline);
return action;
}
@Override
public boolean act(float delta) {
done = timeline.isFinished();
if (!done) {
timeline.update(delta);
} else {
Gdx.app.log("LOG", "timeline.finished()");
timeline.free();
timeline = null;
}
return done;
}
private void setTimeline(Timeline timeline) {
this.timeline = timeline;
}
}
Оригинальная идея от netthreads
Я заметил, что каждый раз, когда добавляется действие, он создает новый объект (TimelineAction action = new TimelineAction()
) вместо возврата объединенного. Затем я попытался отследить окончание действия, переопределив его reset()
метод, чтобы узнать, если это когда-либо называется... Но это не так.
@Override
public void reset () {
Gdx.app.log("LOG", "reset()");
super.reset();
}
Кстати, объекты Timeline и их Tweens успешно отправляются в соответствующие пулы после завершения TimelineAction (2):
(2) - Timeline.getPoolSize() возвращает 1, а Tween.getPoolSize() возвращает 2
actor1.addAction(TimelineAction.createTimelineAction(
Timeline.createSequence()
.push( Tween.to(logo_MUTANT, Element2DAccessor.POS_XY, 3f)
.waypoint(400, 800)
.waypoint(200, 400)
.waypoint(100, 200)
.target(0,0)
)
.ease(Quad.INOUT).path(TweenPaths.catmullRom)).push(Tween.call(callback).setCallbackTriggers(TweenCallback.BACK_COMPLETE)).repeatYoyo(1, 0.5f).start()));
Итак, мне нужна помощь здесь, пожалуйста!:S
Заранее спасибо и извините за плохой английский.;)
Libgdx версия 0.9.6 (24-07-2012)
1 ответ
У вас все еще есть проблема. Я являюсь автором версии TimelineAction для netthreads и не думаю, что у вас должны возникнуть проблемы, если вы используете эту версию:
public class TimelineAction extends Action
{
private static final ActionResetingPool<TimelineAction> pool = new ActionResetingPool<TimelineAction>(10, 100)
{
@Override
protected TimelineAction newObject()
{
TimelineAction action = new TimelineAction();
return action;
}
};
private Timeline timeline;
private Actor target;
protected boolean done;
/**
* Get instance from pool.
*
* @param timeline
* The action time-line to execute.
*
* @return Pooled instance.
*/
public static TimelineAction $(Timeline timeline)
{
TimelineAction action = pool.obtain();
action.setTimeline(timeline);
return action;
}
@Override
public void act(float delta)
{
if (!isDone())
{
timeline.update((int) (delta * 1000));
}
else
{
Gdx.app.log("TimelineAction", "!!!Executing finished timeline, " + timeline.getClass().hashCode());
}
}
@Override
public boolean isDone()
{
return timeline.isFinished();
}
@Override
public Action copy()
{
return this;
}
@Override
public void setTarget(Actor actor)
{
this.target = actor;
}
@Override
public Actor getTarget()
{
return target;
}
@Override
public void finish()
{
super.finish();
pool.free(this);
timeline.free();
}
private void setTimeline(Timeline timeline)
{
this.timeline = timeline;
}
/**
* Fetch TimeLine reference.
*
* @return The TimeLine reference.
*/
public Timeline getTimeline()
{
return timeline;
}
/**
* Set done status.
*
* @param done
*/
public void setDone(boolean done)
{
this.done = done;
}
}
Версия 0.9.6 LibGDX была изменена, чтобы гарантировать, что метод 'finish' вызывается для всех связанных действий для Actor, помеченного для удаления. Если действие завершается до того, как актер помечен для удаления, будет установлен флаг "выполнено", и метод актера "актер" вызовет для него "конец", т.е.
public void act (float delta) {
actions.iter();
Action action;
while ((action = actions.next()) != null) {
action.act(delta);
if (action.isDone()) {
action.finish();
actions.remove();
}
}
}
Я в процессе обновления всех моих демонстраций до 0.9.6.