Skip to content
026编辑器新增严格编译功能下报错的解决方案

026编辑器新增严格编译功能下报错的解决方案

口袋方舟v0.26新增了严格编译模式,在编译脚本时主要增加了4种检测:

  1. deprecated检测(过时功能的检测):这个检测能够提示你使用了已经过时的API,并给出相应的替代方案。只是提醒该功能可能会在未来的版本中移除或改变,不会导致编译失败。在提示中会如下图以黄色图标显示:
    1. img
  2. 语法检测:严格模式对代码中的语法进行更加严格的检查,帮助你发现一些潜在问题和常见错误。如果发现这类问题,编译器将会报告错误,并阻止代码的编译,便于提早发现并修复这些问题。
  3. 类型检测:严格模式将执行更加严谨的类型检查,包括强制进行变量赋值、方法参数校验等。这样可以防止类型安全性问题,提高代码的可靠性和稳定性。
  4. 非法操作检测:严格模式将禁止一些不合法或风险较大的操作,例如未经初始化的局部变量访问、精度损失的数值转换以及非法的类型转换等操作会被检测出来并且报错,以避免运行时出现异常或意外结果。

严格编译模式可以提供更高的语法检查、类型安全和代码质量,帮助开发者避免常见错误,并增强代码的可靠性和稳定性。

以下是修改方法和一些注意事项

1.语法检测报错

1.1由于UI组件命名重复导致的UI导出文件重复定义

提示为“Duplicate identifier”错误,并且该错误出现在导出 UI 脚本文件中,很可能是由于工程中的 UI 组件命名重复,导致导出的脚本出现了重复定义。报错如图所示:

img

错误示例:

在UI中有相同名字并且以小写字母开头命名的UI组件,在导出后Generate脚本中会出现重复定义的变量,例如:

img

在代码中就会报错,如图:

img

情况1处理方案

代码中无需使用该控件的情况:遇到重复命名直接改为大写开头即可

例如,将重复的starcanvas控件命名,改为Starcanvas,并且再次导出脚本即可:

改之前如图:

img

改之后如图:

img

情况2处理方案

代码中需要操作该控件,分为两种情况:

  • 使用编辑器的“导出所有脚本”来使用该控件:需要将需要通过generate脚本调用的控件的名字区分开,以便于代码中使用(实际情况应该很少,此处不做演示)
  • 使用代码Find该控件来使用:直接修改对应控件的命名为大写开头,在代码中寻找时也改为大写开头即可

如果存在代码中没有直接调用组件,而是通过名字查找组件,同样可以将重复的UI改为大写开头,这样可以在保证代码复用的情况下解决报错。

修改之前如图:

img

修改之后如图:

img

记得要修改代码中使用名字查找的部分哟~

img

img

2.方法(函数)参数变更

2.1对象池接口参数变更

构造对象池的方法(函数)添加了新的参数,这导致在构造对象池的时候出现传递参数错误,在编译的时候就会提示参数不匹配,例如:

img

进入报错的脚本后,报错提示为赋值错误,如图:

img

处理方案:

增加的参数为归还对象的回调,只需要将此参数填null即可解决报错。

※如果此对象池是在预制体中的,那么可以直接在数字前面多加一个输入参数并且填上null

修改前如图:

img

修改后如图:

img

  1. LoadSlotByGuid方法移除

loadSlotByGuid方法已经废弃,在编译时会提示该方法不存在,如图:

img

进入脚本后,如图报错显示loadSlotByGuid方法不存在:

img

处理方案:

将废弃的loadSlotByGuid用setSlot方法代替,具体实现代码如下

typescript
player.character.getAppearance<Gameplay.HumanoidV2>().setSlot(guid,true); 
//第二个参数为是否将修改的状态同步给其他玩家`
player.character.getAppearance<Gameplay.HumanoidV2>().setSlot(guid,true); 
//第二个参数为是否将修改的状态同步给其他玩家`

将上述代码替换为原有代码即可解决报错。

修改前如图:

img

修改后如图:

img

2.3isServer变更为Util.SystemUtil内方法

isServer已变为Util.SystemUtil下的方法,导致之前使用Gameplay.isServer的脚本报错,进入工程时报错提示如图:

img

进入脚本后,报错显示Gameplay下无isServer方法,是因为isServer方法现已移动到SystemUtil下

img

处理方案:

将Gameplay.isServer()直接替换为SystemUtil.isServer()即可解决

TypeScript
SystemUtil.isServer()
SystemUtil.isServer()

修改前如图:

img

修改后如图:

img

3.引用报错

3.1UE与puerts import报错

现在工程中只会编译在JavaScript文件夹下的typeScript脚本,其他位置下的脚本将不会被编译,因此会导致一些引用报错,此问题通常会在一些较旧的prefab中出现,报错显示如图:

img

进入脚本,报错显示无法找到导入的文件:

img

解决方案:

方案1:如果报错脚本为预制体内的脚本,将工程中预制体的脚本替换为最新版本的预制体脚本即可解决报错,具体步骤如下:

新版本预制体包

下载预制体包解压后,找到需要替换的预制体,例如显示报错的脚本位于换装功能的预制体内:

img

打开工程文件夹,找到工程JavaScripts文件夹下Prefab内的预制体文件夹:

img

如果对应预制体文件夹下存在AssestManager和ToolUtils文件,则需要将这两个文件删除。若不存在,则可以跳过此步操作:

img

方案2:如果报错脚本为非预制体的脚本,或者使用的预制体未找到更新版本。可以用以下方法分几步解决报错:

第一步:将报错的import替换为如下代码块

typescript
declare global {    var UE: any;    var puerts: any; }
declare global {    var UE: any;    var puerts: any; }

修改前如图:

img

修改后如图:

img

第二步:使用代码块替换后会出现UE的引用报错,此时将报错的UE类替换为any即可解决报错

修改前如图:

img

修改后如图:

img

需要将UE命名空间下报错的部分都用any替换,例如

img

修改后后变为:

img

再例如定义的方法:

img

修改后变为:

img

3.2Gameplay成员报错

由于Gameplay的一部份成员与GameObject功能类似。为了方便大家的代码管理,现在将Gameplay.Prefab等成统一为Gameplay.GameObject,所以在升到026时会出现命名空间Gameplay下找不到类的情况。

报错如:

img

进入脚本,报错显示Gameplay命名空间下没有XXX,图中情况就是在命名空间下没有Prefab:

img

解决方案:

用Gameplay.GameObject替换一系列报错的Gameplay.XXX

TypeScript
Gameplay.GameObject //将一系列报错的Gameplay.XXX直接替换为Gameplay.GameObject
Gameplay.GameObject //将一系列报错的Gameplay.XXX直接替换为Gameplay.GameObject

修改前如图:

img

修改后如图:

img

3.3其他需要替换的代码块

有些代码块现在编辑器里已经有了新方法可以替代了,可以选择性替换。

img

将(puerts.argv.getByName("Proxy") as any).ProjectDir.indexOf("😊 < 0 替换为 SystemUtil.isMobile()

TypeScript
SystemUtil.isMobile()
SystemUtil.isMobile()

img

4.类型检测报错

026上增加了更严格的类型检测,目的是防止类型安全性问题,提高代码的可靠性和稳定性,所以当变量的类型不确定时,在做比较等运算时会导致出错。

所以当编写代码时,尤其是在进行业务逻辑的设计和实现时,我们应该尽量确保所有变量或对象的类型是确定的。这就需要每个变量都应该明确地声明为特定的数据类型。

通过指定变量的数据类型,可以让一起协作开发的搭档以及我们的编译器获得更多变量的信息,包括变量可以存储哪些值?可用的操作?以及如何与其他变量交互等。这样可以减少潜在的错误,并提高代码的清晰度和稳定性。

当然,如果是两个类之间存在包含关系,比如A类是B类的一部分,那么在声明相关变量时,可以使用B类(容器类)来表示更具体的类型。

4.1 使用了类对象未定义的属性

在脚本中引用了对象的某个属性,但是这个属性不确定是否存在,在编译的时候就会导致报错,报错显示如图:

img

进入脚本中,可以看到在代码中引用了skinConfig中的fly属性,skinConfig由上方的或关系中得到,需要或关系中的每个结果都存在fly属性,skinConfig.fly才能正常运行:

img

进入SkinConfig类中发现,在default下不存在此属性,从而导致了前面的报错:

img

解决方案:

需要在类中加入引用的属性,可以用布尔值实现区分有无此属性

修改前如图:

img

修改后如图:

img

4.2变量类型不明确时进行比较操作

在声明动态获取的变量时TS会将该值设为安全类型unknown。此时若进行比较运算则会导致报错,报错提示如下:

img

进入脚本,报错显示如图,无法将unknow类型与number类型做比较操作:

img

解决方案:

需要在做比较运算时明确变量的类型,在代码中有几种方式可以实现,例如:

报错的代码如图的情况下:

img

解决方案1:在比较操作前加入类型断言。修改后的代码如图:

img

解决方案2:在声明变量时定义好类型。修改后的代码如图:

img

解决方案3:使用“as”关键字转换变量类型。修改后的代码如图:

TypeScript
curStage as number;//curStage为后面用做对比的变量名
curStage as number;//curStage为后面用做对比的变量名

img

4.3 函数返回值的类型不明确,并且使用返回值进行比较操作。

报错显示如图,

img

img

由于返回值有number和boolean两种,boolean无法与number进行比较操作从而导致报错

img

解决方法:需要确定函数返回值的类型,可以用以下几种方法

A.在函数声明时即确定好返回值的类型。在新声明函数时可以尝试确定返回值类型,这样能让代码扽可读性更强并且功能更稳定。但如果是改动现有代码的话可能会影响功能,可以使用B方法更改现有代码。

img

B.将函数返回值先定义变量保存,将保存的变量用上面的方法明确类型后,再进行比较操作

img