bit-core:拆出来的基础工具库,其他模块都靠它兜底

它解决什么问题

写 Cocos Creator 游戏的时候,有一堆代码几乎每个项目都要写一遍:判断当前是不是微信小游戏、拿屏幕安全区做适配、搞个全局定时器管技能冷却、格式化一个倒计时文案……这些东西单独看都不难,但项目多了之后,同样的逻辑在不同项目里重复实现,风格还都不一样,改一次 bug 只改了一个项目,其他项目还带着老问题。

bit-core 就是把这些”每个项目都要写”的基础功能收拢到一个包里:时间处理、定时器、平台检测、屏幕适配、日志、常用数据结构。它是 bit-framework 里被依赖最多的模块,bit-uibit-conditionbit-minigamebit-hotupdate 都把它当 peer 依赖。

安装

npm install @gongxh/bit-core

不需要任何其他依赖,可以独立使用。

主要能力

时间工具(Time)

除了拿时间戳这种基础操作,比较实用的是内置了网络时间同步——很多游戏对本地时间不完全信任(怕玩家改系统时间作弊),可以把服务器时间同步进来做基准:

import { Time } from '@gongxh/bit-core';

Time.setNetTime(serverTimestamp); // 用服务器时间校正
Time.now(); // 之后拿到的都是校正后的时间

Time.getDayStartTime(); // 当天 0 点时间戳,结算日重置常用
Time.isSameDay(t1, t2); // 判断是否同一天

时长格式化这块也做了两种粒度:formatDuration 按你给的 pattern 精确格式化,formatSmart / formatSmartSimple 会自动隐藏为 0 的单位,适合倒计时文案不想手动拼接的场景。

全局定时器(GlobalTimer)

游戏里散落的 setInterval/setTimeout 最容易出的问题是场景切换时忘记清理,导致回调打在已经销毁的对象上。GlobalTimer 统一管理,还支持暂停恢复:

import { GlobalTimer } from '@gongxh/bit-core';

// 每秒执行一次,无限重复
const timerId = GlobalTimer.startTimer(() => {
    console.log('心跳');
}, 1, -1);

GlobalTimer.pauseTimer(timerId);  // 比如切到后台时暂停
GlobalTimer.resumeTimer(timerId);
GlobalTimer.stopTimer(timerId);

平台检测(Platform)

小游戏平台一多,if-else 判断平台的代码到处都是。Platform 把这些判断收成一批只读属性:

import { Platform } from '@gongxh/bit-core';

if (Platform.isWX) {
    // 微信小游戏
} else if (Platform.isNativeMobile) {
    // 原生移动端(Android/iOS/HarmonyOS)
}

屏幕适配(Screen)

刘海屏、挖孔屏这些异形屏,安全区不处理好,UI 元素会被摄像头或者虚拟按键挡住。Screen 提供了拿到手就能用的安全区信息:

import { Screen } from '@gongxh/bit-core';

console.log(Screen.SafeWidth, Screen.SafeHeight);   // 安全区宽高
console.log(Screen.SafeAreaTop, Screen.SafeAreaBottom); // 四边 inset

有个细节要注意:横屏因为没法区分设备是左手还是右手朝向,左右两侧的安全区会对称地都用 safeAreaTop 的配置值,不是分别计算。长边和短边比例小于等于 16:9 的设备(大多数平板),四边 inset 会直接清零,安全区等于全屏。

日志系统

统一的日志输出,方便上线后统一关闭调试日志:

import { enableDebugMode, debug, warn, error } from '@gongxh/bit-core';

enableDebugMode(false); // 生产环境关掉 debug 级别日志

数据结构

内置了二叉堆、链表、双向链表、栈,都是游戏开发里常会手写的东西,直接拿来用:

import { BinaryHeap } from '@gongxh/bit-core';

// 小顶堆,常用来做技能冷却队列、AI 决策优先级排序
const heap = new BinaryHeap<Task>((a, b) => a.priority - b.priority);
heap.push(task);
heap.pop();

模块基类(Module)

如果你的项目习惯把游戏系统拆成一个个”模块”(背包模块、任务模块……),可以继承 Module 统一生命周期入口,实现 onInit() 就行,不用每个系统都自己定义一套初始化规范。

避坑提醒

  • Screen 的安全区配置要在 CocosEntry 的 Inspector 面板里设,不是代码里传参数,容易漏配导致横屏适配不对。
  • Time.setNetTime() 只是给个基准,之后 Time.now() 是基于这个基准 + 本地流逝时间计算的,不是每次都重新请求服务器,别指望它帮你做防作弊校验,真要防作弊还是得后端兜底。
  • GlobalTimer 是全局单例,场景切换、组件销毁的时候记得手动 stopTimer,不然定时器会一直跑。

项目信息

如果你的项目需要 UI 管理(bit-ui)、条件显示(bit-condition)、小游戏适配(bit-minigame)或热更新(bit-hotupdate),这几个模块都是直接把 bit-core 当 peer 依赖用的,装它们的时候记得把 bit-core 也一起装上。