欢迎光临散文网 会员登陆 & 注册

TypeError: The thing you want to instantiate must be an object是怎

2023-03-21 21:28 作者:merlinzp  | 我要投稿

【故障现象】

点击setting报错
点击setting报错

跟着B站的视频学小游戏,点击的时候会报错,一直找不到原因

点击的时候会调用这个onOpenSetting方法

  onOpenSetting(){

        //打开UISetting

        UIManager.instance.openDialog(DialogDef.UISetting);

    }


然后就会报这个错误:

TypeError: The thing you want to instantiate must be an object

说你想要实例化的东西必须是一个对象


但是我没找到问题,大佬们帮忙看下



【源码】

//UIGame

import { _decorator, Component, Node, director, resources, find, Prefab, instantiate } from 'cc';

import { DialogDef, UIManager } from './UIManagers';

const { ccclass, property } = _decorator;


@ccclass('UIGame')

export class UIGame extends Component {

    start() {


    }


    update(deltaTime: number) {

       

    }


    //点击设置时执行的方法:

    onOpenSetting(){

        //打开UISetting

        UIManager.instance.openDialog(DialogDef.UISetting);


    }


    //点击退出游戏执行的方法:

    onExitGame(){

        console.log("点击了Exit");


        //释放此包中的所有没有用到的资源:

        resources.releaseUnusedAssets();


        //退出游戏,即回到startup开始界面:

        director.loadScene("startup");

    }


    //暂停游戏执行的方法:

    onPauseGame(){

        console.log("点击了Pause");


        //进行判断,如果当前游戏暂停,则恢复暂停。isPaused表示是否暂停,resume表示恢复暂停。否则暂停游戏。

        if(director.isPaused()){

            director.resume();


            //return可以将代码格式化吗?

            return;

        }else{

            director.pause();

        }


    }


}



//UIManager

import { find, instantiate, Node, Prefab, resources } from "cc";


//枚举的作用是列举类型中包含的各个值,一般用它来管理多个相同系列的常量(即不能被修改的变量),用于状态的判断。

export enum DialogDef{

    UISetting = 'UISetting',

    UISkillUpgrade = 'UISkillUpgrade',


}


export class UIManager{


    /*

    把UIManager设置为单例类。

    public表示公开,private表示私有,protected表示只有自己以及继承关系的才可以访问。

    */

    private static _instance:UIManager = null;


    //static表示这个方法是静态的。并且允许外界通过get来获取这个方法。

    static get instance():UIManager{

        //如果这个实例为空,则将UIManager实例化。

        if (this._instance == null) {

            this._instance = new UIManager();

        }

        return this._instance;

       

    }


    //声明uiRoot,类型为节点,初始值为空,用于实例化UIRoot节点。

    uiRoot:Node = null;


    /*

    把加载的数据存放到内存中,避免重复加载。Map()是一种数据结构。

    Map 对象存有键值对,其中的键可以是任何数据类型。Map 对象记得键的原始插入顺序。

    可以把对象放在Map中,方便后续取用,效率更高。

    详细解释可以参考JS文档:https://www.w3school.com.cn/js/js_object_maps.asp

    panels是参数,:后面是类型,类型是Map,Map有两个参数,string字符串和Node节点。

    */

    panels : Map<string, Node> = new Map();


    //打开面板的方法,传入2个参数:name:string表示预制体的名称,bringToTop:Boolean = true表示是否调整预制体的层级:

    openPanel(name:string, bringToTop:Boolean = true){


        /*

        当uiRoot == null时,就是没有实例化时,查找UIRoot并赋值给uiRoot。

        通过if语句进行判断,防止重复初始化。

        */

        if (this.uiRoot == null) {

            this.uiRoot = find("UIRoot");

        }

       

        /*

        后续执行时,因为resources.load中已经将该资源放入Map,因此这里可以直接取出来利用。

        然后再进行激活。

        这个方法的目的时进行判断,如果Map中存在Panel,则直接取出,进行实例化,

        不再执行resources.load,避免重复加载预制体。

        */

        if (this.panels.has(name)) {

            //从Map中取出name,name是panel并实例化。

            let panel = this.panels.get(name);


            //把panel的状态进行激活。

            panel.active = true;


            //判断是否需要将panel的层级进行提升。

            if (bringToTop) {

                //当bringToTop为真时,panel.parent.children.length - 1表示panel所有父节点的子节点场层级-1,就是往上移动一个层级。

                const index = panel.parent.children.length - 1;

                //向上移动一个层级后,将index参数传入,setSiblingIndex表示设置置当前节点在父节点的 children 数组中的位置。

                panel.setSiblingIndex(index);

            }

            //中止函数,不再往下执行。

            return;

        }

        /*

        1.加载面板

        resources.load可以通过相对路径加载资源。

        "ui\prefab" + name表示ui/prefa/这个路径下某个名字的资源,Prefab表示是预制体。

        =>表示箭头函数,这里相当于:

        function(err:Error, data:Prefab) {}

        */

        resources.load("ui/prefab/" + name, Prefab, (err:Error, data:Prefab)=>{

            /*

            实例化预制体并赋值给panel:

            data就是(err:Error,data:Prefab)里面的data,就是从预制体里面取出来的数据。

            */

            let panel = instantiate(data);


            //在uiRoot节点下增加panel子节点:

            this.uiRoot.addChild(panel);


            //this.panels.set就是给Map()设置一个键值,内容是name,而这个name就是节点panel。

            this.panels.set(name,panel);


            if (bringToTop) {


                //当bringToTop为真时,panel.parent.children.length - 1表示panel所有父节点的子节点场层级-1,就是往上移动一个层级。

                const index = panel.parent.children.length - 1;

                //向上移动一个层级后,将index参数传入,setSiblingIndex表示设置置当前节点在父节点的 children 数组中的位置。

                panel.setSiblingIndex(index);

            }


        });

    }

 

    //关闭面板的方法:

    closePanel(name:string, destory:boolean = false){


        //判断面板是否存在,如果不存在,直接中断函数。

        if(!this.panels.has(name)){

            return;

        }


        //如果存在,则从Map中取出预制体。

        let panel = this.panels.get(name);


        /*

        如果需要销毁预制体,则聪Map中删除相关预制体,并从父节点移除

       

        0该节点。

        是否销毁根据closePanel(name:string, destory:boolean = false)传入的

        destory:boolean = false参数决定,如果=true则销毁。这里是false则表示不销毁,

        当前代码只是示例。

        */

        if (destory) {

            this.panels.delete(name);

            panel.removeFromParent();

            return;

        }


        //如果不销毁,只是隐藏,则关闭该节点。

        panel.active = false;


    }


    /*打开弹框:

    通过名字来获取弹框。怎么获取弹框的名字呢,可以通过enum枚举来定义,然后再从枚举中获取。

    */

    openDialog(name:string){

        for(let  dialogDef in DialogDef){

            if (dialogDef == name) {

                this.openPanel(name);

            } else {

                this.closePanel(dialogDef);

            }


        }


    }


    //关闭弹框:

    CloseDialog(destory: boolean =false){

        for (let  dialogDef in DialogDef) {

            this.closePanel(dialogDef,destory);    

        }


    }


}


TypeError: The thing you want to instantiate must be an object是怎的评论 (共 条)

分享到微博请遵守国家法律