Cocos Creator开发中的instantiate方法小结
  iwbGD3gmtxyT 2023年11月02日 49 0

简介

instantiate方法在Cocos Creator中有两种作用:

  • 从 Prefab 实例化出新节点
  • 克隆指定的任意类型的对象

对应于框架源代码中的文字介绍如下:

    /**
     * @zh 从 Prefab 实例化出新节点。
     * @en Instantiate a node from the Prefab.
     * @param prefab The prefab.
     * @returns The instantiated node.
     * @example
     * ```ts
     * import { instantiate, director } from 'cc';
     * // Instantiate node from prefab.
     * const node = instantiate(prefabAsset);
     * node.parent = director.getScene();
     * ```
     */
    export function instantiate(prefab: Prefab): Node;
    /**
     * @en Clones the object `original.
     * @zh 克隆指定的任意类型的对象。
     * @param original An existing object that you want to make a copy of.
     * It can be any JavaScript object(`typeof original === 'object'`) but:
     * - it shall not be array or null;
     * - it shall not be object of `Asset`;
     * - if it's an object of `CCObject`, it should not have been destroyed.
     * @returns The newly instantiated object.
     * @example
     * ```ts
     * import { instantiate, director } from 'cc';
     * // Clone a node.
     * const node = instantiate(targetNode);
     * node.parent = director.getScene();
     * ```
     */
    export function instantiate<T>(original: T): T;
    export namespace instantiate {
        export var _clone: typeof __private._cocos_serialization_instantiate__doInstantiate;
        export var _clone: typeof __private._cocos_serialization_instantiate__doInstantiate;
    }

从 Prefab 实例化出新节点

和克隆已有节点相似,你可以设置一个预制(Prefab)并通过 instantiate 生成节点。使用方法如下:

import { _decorator, Component, Prefab, instantiate, director } from 'cc';
const { ccclass, property } = _decorator;

@ccclass("test")
export class test extends Component {

    @property({type:Prefab})
    private target: Prefab = null;

    start(){
        let scene = director.getScene();
        let node = instantiate(this.target);

        scene.addChild(node);
        node.setPosition(0,0,0);
    }
}

需要注意的是,在使用上述的代码时,需将持有该代码的脚本挂在某个节点上,并在 属性检查器 内配置好 target 的值。

操作Prefab对象数组的举例

注:本例程改编自官方示例工程中的event-first场景,修改后的代码如下:

import { _decorator, Component, Node, instantiate, EventTouch, Prefab, Label, Button,Vec2, Vec3 } from 'cc';
const { ccclass, property } = _decorator;


@ccclass('eventFirst')
export class eventFirst extends Component {

    @property({
        type: Prefab,
    })
    public prefabNode: Prefab = null!;

    @property({
        type:Label
    })
    public labelShow: Label = null!;

    @property({
        type: Button,
    })
    public button: Button = null!;

    // @property({
    //     type: Node,
    // })
    //public items: Node[] = null!;//XXXXXX
    public items: Node[] = [];
    
    private static times: number=0;
    public i: Node=null!;

    onLoad () {
        this.i=instantiate(this.prefabNode);

        this.items.push(this.i);//TypeError: Cannot read property 'push' of null

        eventFirst.times++;

        console.log("eventFirst.times: ", eventFirst.times);
    }

    start () {
        // Your initialization goes here.
    }

    onEnable() {
        this.eventOn();
    }

    eventOn() {
        this.i.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.i.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
        this.i.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.i.on(Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);

        this.node.addChild(this.i);
        console.log("addChild(this.i) ");


    }

    onDisable() {
        this.items.forEach(item => {
            item.off(Node.EventType.TOUCH_START, this.onTouchStart, this);
            item.off(Node.EventType.TOUCH_END, this.onTouchEnd, this);
            item.off(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
            item.off(Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
           
        });
    }

    onTouchStart(event: EventTouch){
        this.labelShow.string = `TouchStart: ${event.getLocation()}`;
        console.log(`TouchStart: ${event.getLocation()}`);
    }

    onTouchMove(event: EventTouch){
        this.labelShow.string = `TouchMove: ${event.getLocation()}`;
        console.log(`TouchMove: ${event.getLocation()}`);
    }

    onTouchEnd(event: EventTouch){
        this.labelShow.string = 'TouchEnd';
        console.log('TouchEnd');
    }

    onTouchCancel(event: EventTouch){
        this.labelShow.string = 'TouchCancel';
        console.log('TouchCancel');
    }

    createChild() {
        console.log("eventFirst.times: ", eventFirst.times++);

        let item = instantiate(this.prefabNode);
        item.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
        item.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
        item.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        item.on(Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);

        let tmpItem=this.items[this.items.length-1];
        item.setPosition(new Vec3(tmpItem.position.x+90,
            tmpItem.position.y));
        this.items.push(item);

        this.node.addChild(item);

    //    this.button.node.active = false;
    }
}

这是实战场景中动态创建Prefab对象的方案之一,仅供参考。


克隆指定的任意类型的对象

有时我们希望动态的克隆场景中的已有节点,我们可以通过 instantiate 方法完成。注意事项:

要克隆的JavaScript对象可以是任何JS对象(`typeof original === 'object'`) ,但是:

    * 不是能数组或者null。

    * 也不是能Asset类型的对象。

    *如果是一个CCObject类型的对象,那么被克隆的母对象不能已被销毁。

来自于官方地址的简单应用举例如下:

import { _decorator, Component, Node,instantiate, director } from 'cc';
const { ccclass, property } = _decorator;

@ccclass("test")
export class test extends Component {

    @property({type:Node})
    private target: Node = null;

    start(){
        let scene = director.getScene();
        let node = instantiate(this.target);

        scene.addChild(node);
        node.setPosition(0, 0,-10);
    }
}



参考

https://docs.cocos.com/creator/manual/zh/scripting/create-destroy.html


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论