typescriptcocoscreator

Call a function after action from previous function is completed


I have the following JavaScript code:

if (condition == 'true'){
    this.function1();
    this.function2();
}

function1() code:

function1(){
    this.node.getChildByName("spriteName").active = true;
    this.node.getChildByName("spriteName").runAction(cc.moveTo(0.1, x, y));
}

function2() code:

function2(){
    this.node.getChildByName("spriteName").active = false;
}

How can I ensure that function2 is called only after function1 has completed? I have tried cc.delayTime() but it's not proper.


Solution

  • I'm gonna assume that you're using Cocos Creator 2.4.

    The action system is currently deprecated (source). It might be wise to use cc.tween instead.

    Solution using cc.tween (recommended)

    You can use cc.tween methods such as to and call to move your node and call a method.

    Example

    Here's an example made using the code that you provided (in TypeScript).

    const {ccclass, property} = cc._decorator;
    
    @ccclass
    export default class TestScript extends cc.Component
    {
        private x: number = 15;
        private y: number = 15;
    
        start()
        {
            this.function1();
        }
    
        function1()
        {
            const sprite = this.node.getChildByName("spriteName");
            sprite.active = true;
    
            cc.tween(sprite)
                .to(1, { position: cc.v3(this.x, this.y, 0) })
                .call(() => this.function2())
                .start();
        }
    
        function2()
        {
            this.node.getChildByName("spriteName").active = false;
        }
    }
    

    Solution using Action System (deprecated)

    If you still wish to stay with your initial solution, you can call a method after an action is done by using cc.sequence and cc.callFunc. The first method will be used to call actions in sequence one by one and the other one will be used as an action that just calls a method.

    Example

    Here's an another example made using the code that you provided (in TypeScript).

    const {ccclass, property} = cc._decorator;
    
    @ccclass
    export default class TestScript extends cc.Component
    {
        private x: number = 15;
        private y: number = 15;
    
        start()
        {
            this.function1();
        }
    
        function1()
        {
            const sprite = this.node.getChildByName("spriteName");
            sprite.active = true;
    
            const moveAndDisable = cc.sequence(
                cc.moveTo(1, this.x, this.y),
                cc.callFunc(() => this.function2()));
            
            sprite.runAction(moveAndDisable);
        }
    
        function2()
        {
            this.node.getChildByName("spriteName").active = false;
        }
    }
    

    Extra solution - cc.tween + Promise

    If you wish to move several objects simultaneously with various different durations but wish to run a method after all of them have finished moving, you can use cc.tween in combination with Promise class.

    Example

    const {ccclass, property} = cc._decorator;
    
    @ccclass
    export default class TestScript extends cc.Component
    {
        @property(cc.Sprite)
        private sprite1: cc.Sprite = null;
    
        @property(cc.Sprite)
        private sprite2: cc.Sprite = null;
    
        @property(cc.Sprite)
        private sprite3: cc.Sprite = null;
    
        private x: number = 15;
        private y: number = 15;
    
        start()
        {
            this.function1();
        }
    
        function1()
        {
            Promise
                .all([
                    this.moveNodeToPosition(this.sprite1.node, cc.v3(this.x, this.y, 0), 1.0),
                    this.moveNodeToPosition(this.sprite2.node, cc.v3(this.x, this.y, 0), 1.5),
                    this.moveNodeToPosition(this.sprite3.node, cc.v3(this.x, this.y, 0), 2.0),
                ])
                .then(this.function2);
        }
    
        function2()
        {
            cc.log("done");
        }
    
        moveNodeToPosition(
            target: cc.Node,
            position: cc.Vec3,
            duration: number) : Promise<unknown>
        {
            return new Promise(resolve =>
            {
                cc.tween(target)
                    .to(duration, { position: position })
                    .call(() => resolve(null))
                    .start();
            });
        }
    }