Skip to content

Commit b4c572b

Browse files
authored
fixed #17876: [bug] callFunc before updateUntil may be invoked more than once. (#18179)
1 parent f5b7fc6 commit b4c572b

File tree

2 files changed

+52
-8
lines changed

2 files changed

+52
-8
lines changed

cocos/tween/actions/action-interval.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ export abstract class ActionInterval extends FiniteTimeAction {
113113
return true;
114114
}
115115

116-
isDone (): boolean {
117-
return (this._elapsed >= this._duration);
116+
override isDone (): boolean {
117+
return this._elapsed >= this._duration && !this.isUnknownDuration();
118118
}
119119

120120
_cloneDecoration (action: ActionInterval): void {
@@ -136,12 +136,16 @@ export abstract class ActionInterval extends FiniteTimeAction {
136136
t = (t < 1 ? t : 1);
137137
this.update(t > 0 ? t : 0);
138138

139-
// NOTE: If the action's duration is unknown, the elapsed time should keep at the point of the last frame,
139+
// NOTE: If the action's duration is unknown, the elapsed time should be kept at the point of the last frame,
140140
// because ActionUnknownDuration will be executed at each frame until its callback returns true.
141141
// After ActionUnknownDuration is finished, the isUnknownDuration method will return false
142142
// and the elapsed time will go as before.
143143
if (this.isUnknownDuration() && !this._firstTick) {
144-
this._elapsed -= dt;
144+
if (t < 1) {
145+
this._elapsed -= dt;
146+
} else {
147+
this._elapsed = this._startTime + this._duration;
148+
}
145149
}
146150

147151
if (this._firstTick) {

tests/tween/tween.test.ts

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ function runFrames(frames: number) {
1818
}
1919
}
2020

21+
function randomTickSeconds(time: number) {
22+
let totalTime = 0;
23+
for (;;) {
24+
const dt = 0.016 * 2 * Math.random();
25+
director.tick(dt);
26+
totalTime += dt;
27+
if (totalTime >= time) {
28+
break;
29+
}
30+
}
31+
}
32+
2133
test('remove actions by tag', function () {
2234
const scene = new Scene('test-tags');
2335
const node = new Node();
@@ -4850,7 +4862,7 @@ test('updateUntil 2', function () {
48504862
const target2 = { x: 0 };
48514863

48524864
tween(node)
4853-
.delay(1)
4865+
.delay(1) // 1s
48544866
.sequence(
48554867
tween(node).parallel(
48564868
tween(node).by(1, { position: v3(90, 90, 90) }).call(cb),
@@ -4863,10 +4875,10 @@ test('updateUntil 2', function () {
48634875
}
48644876
return false;
48654877
}, 1, false, 'hello'),
4866-
tween(node).by(3, { scale: v3(30, 30, 30) })
4878+
tween(node).by(3, { scale: v3(30, 30, 30) }) // 3s
48674879
),
48684880
tween(node).call(cb2),
4869-
tween(target2).by(1, { x: 100 }),
4881+
tween(target2).by(1, { x: 100 }), // 1s
48704882
)
48714883
.updateUntil((target: Node, dt: number, arg0: number, arg1: boolean, arg2: string): boolean => {
48724884
elapsed += dt;
@@ -4876,7 +4888,7 @@ test('updateUntil 2', function () {
48764888
return true;
48774889
}
48784890
return false;
4879-
}, 2, true, 'world')
4891+
}, 2, true, 'world') // 2s
48804892
.start();
48814893

48824894
runFrames(1); // Start
@@ -4911,6 +4923,34 @@ test('updateUntil 2', function () {
49114923
director.unregisterSystem(sys);
49124924
});
49134925

4926+
test('updateUntil 3', function () {
4927+
const sys = new TweenSystem();
4928+
(TweenSystem.instance as any) = sys;
4929+
director.registerSystem(TweenSystem.ID, sys, System.Priority.MEDIUM);
4930+
4931+
const node = new Node();
4932+
4933+
let testNumber = 0;
4934+
tween(node)
4935+
.delay(1)
4936+
.call(() => {
4937+
testNumber++;
4938+
})
4939+
.updateUntil(() => {
4940+
return false;
4941+
})
4942+
.start();
4943+
4944+
runFrames(1); // Start
4945+
randomTickSeconds(1);
4946+
expect(testNumber).toBe(1);
4947+
4948+
randomTickSeconds(1);
4949+
expect(testNumber).toBe(1);
4950+
4951+
director.unregisterSystem(sys);
4952+
});
4953+
49144954
test('parallel with two call tween', function () {
49154955
const sys = new TweenSystem();
49164956
(TweenSystem.instance as any) = sys;

0 commit comments

Comments
 (0)