Cocos Creator 3.8.8 自定义启动加载页(分3种方案,从简单替换LOGO到完整动画Loading场景)

先分清两个概念:

  1. 引擎闪屏Splash(构建后黑屏前那张Cocos图):Web/小程序/原生打包前的静态图片,项目设置一键替换;
  2. 游戏内Loading加载场景(资源加载进度条、动画、动态LOGO):引擎初始化完成后,加载贴图/预制体/关卡时的自定义页面,支持骨骼动画、液体/软体特效、渐变过渡(你做肉块液体项目优先用这个)

方案一:最简替换默认Splash闪屏(只换LOGO,无动画,5分钟搞定)

1. 编辑器内置配置(全平台通用:Web/微信小游戏/Android/iOS)

  1. 顶部菜单 项目 → 项目设置 → Splash Setting(插屏设置)
  1. 参数说明:
  2. 预览框点击加号,上传你的Logo图片(png/jpg,5M以内);
  3. TotalTime:最小显示毫秒,建议2000(至少显示2秒,不能太短);
  4. Image Size Multiplier:图片缩放比例,100%=原图,200%放大;
  5. 取消勾选可直接关闭引擎默认闪屏。
  6. 构建项目,打包后自动替换Cocos默认Logo。

2. Web端深度自定义(改背景、隐藏进度条、全屏图)

每次构建会覆盖build文件夹,必须用构建模板build-templates永久保存修改:

  1. 项目根目录新建文件夹:build-templates/web-mobile
  2. 先构建一次Web,复制build/web-mobile/index.htmlstyle-mobile.css到上面文件夹;
  3. 修改css,替换背景图、全屏、隐藏进度条:

    #splash {
     position: absolute;
     width: 100%;
     height: 100%;
     background: #000 url(./myLogo.png) no-repeat center;
     background-size: 80%; /* logo占屏幕80% */
    }
    /* 隐藏默认进度条 */
    .progress-bar {
     display: none !important;
    }
  4. 把你的logo图片放进build-templates/web-mobile/,下次构建自动生效。

方案二:完整游戏内Loading加载场景(推荐你的肉块液体项目,最强自定义)

优势

  • 支持骨骼动画、粒子液体、软体肉块、渐变淡入淡出;
  • 实时读取资源加载进度,自定义进度条、文字;
  • 不受引擎Splash限制,所有平台通用,微信小游戏/安卓/iOS都能用;
  • 可以复用前面写的全局数据单例控制加载参数。

完整实现步骤

步骤1:新建Loading场景

  1. 新建场景 Scene_Loading,设为启动场景(项目设置 → 项目数据 → 默认启动场景选Scene_Loading);
  2. 节点结构:

    Canvas
    ├─ Sprite_Bg 背景图
    ├─ Sprite_Logo 你的品牌logo(可加缓动缩放动画)
    ├─ ProgressBar 进度条组件(ProgressTimer)
    └─ Label_Progress 文字:0%

步骤2:加载脚本 LoadingManager.ts

核心逻辑:异步预加载所有游戏资源、实时更新进度、加载完成跳转主场景

import { _decorator, Component, ProgressTimer, Label, director, resources, Vec3, tween } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('LoadingManager')
export class LoadingManager extends Component {
    @property(ProgressTimer) progressBar!: ProgressTimer;
    @property(Label) progressText!: Label;

    onLoad() {
        // Logo入场缩放动画
        const logo = this.node.getChildByName("Sprite_Logo");
        tween(logo)
            .set({ scale: new Vec3(0,0,0) })
            .to(0.6, { scale: new Vec3(1,1,1) })
            .start();

        // 开始预加载资源
        this.loadGameAssets();
    }

    // 批量预加载所有游戏资源(肉块预制体、液体贴图、场景)
    async loadGameAssets() {
        const bundleList = ["textures", "prefabs", "scenes"];
        let total = bundleList.length;
        let loaded = 0;

        for(const bundleName of bundleList) {
            await new Promise(res => {
                resources.loadBundle(bundleName, (finish, totalAll) => {
                    // 更新实时加载进度
                    const curPercent = (loaded + finish / totalAll) / total;
                    this.updateProgress(curPercent);
                }, ()=>{
                    loaded++;
                    res(null);
                })
            })
        }

        // 全部加载完成,跳转主游戏场景
        director.loadScene("Scene_Game");
    }

    // 更新进度条+文字
    updateProgress(percent: number) {
        this.progressBar.progress = percent;
        this.progressText.string = `${Math.floor(percent * 100)}%`;
    }
}

进阶扩展(适配你的软体/液体项目)

  1. 加载页放液体粒子、晃动肉块软体
    在Loading场景直接挂载之前写的液体发射器、弹簧质点肉块,加载资源时同步播放动态效果;
  2. 全局数据联动
    读取GlobalData里的液体粘度、肉块软度参数,在加载页预览默认效果;
  3. 过渡动画
    加载完成加淡出Tween,黑屏后再进入游戏场景,丝滑切换。

方案三:原生平台Android/iOS替换启动图(解决APP打开黑屏)

Android

  1. 构建安卓项目后打开proj.android/app/src/main/res/mipmap-xxx
  2. 替换所有ic_launcher、splash图片;
  3. 修改values/styles.xml设置全屏启动页背景色。

iOS

  1. Xcode打开工程,修改LaunchScreen.storyboard
  2. 替换启动图资源,移除Cocos默认占位图。

三种方案对比,按需选择

方案效果适用场景开发成本
方案一:替换引擎Splash静态图片,无动画,仅开机一瞬间只需要换个Logo,无动态效果需求极低
方案二:Loading加载场景骨骼动画、液体/软体、动态进度、转场动画你的肉块液体游戏、需要炫酷加载页中等(推荐)
方案三:原生启动图APP安装包冷启动黑屏阶段画面安卓iOS打包,解决黑屏

避坑关键点

  1. 不要混淆Splash和Loading场景
    引擎Splash是引擎初始化前,只能静态图;Loading场景是引擎跑起来之后,能做任意游戏动画;
  2. Web端直接修改build文件夹图片会失效
    必须用build-templates模板目录保存自定义html/css,否则每次构建覆盖;
  3. 加载场景资源尽量轻量化
    Loading场景只用1-2张小图,不要放大量贴图/物理预制体,避免加载页本身卡顿;
  4. 多场景数据共享
    Loading场景和游戏主场景共用之前写的GlobalData全局单例,加载进度、配置互通。

最简推荐流程(你的项目直接照做)

  1. 项目设置Splash替换自家Logo(解决开机Cocos标);
  2. 新建Scene_Loading作为启动场景,写上面LoadingManager脚本;
  3. 在Loading场景添加液体粒子、弹簧肉块软体做动态视觉;
  4. 预加载所有肉块、液体、关卡资源,进度条实时展示,加载完进入游戏。

Cocos Creator 3.8.8 多场景共享数据全套方案(分轻量/全局/持久化,适配你的软体、液体物理项目)

核心场景需求

  1. 切换场景(关卡A→关卡B)保留:液体粒子数量、肉块软体参数、玩家设置、物理配置、道具数据
  2. 场景并行叠加(additive叠加场景)互相读写数据
  3. 重启游戏数据不丢失(持久存储)
  4. 区分:临时运行时共享 / 本地永久保存

方案1:全局单例类(最推荐,运行时全局共享,所有场景通用)

原理

创建静态单例管理类,脚本挂载在「常驻根节点」(不会随场景销毁),所有场景直接导入调用,存液体、肉块、玩家、物理全局配置。

步骤1:创建全局数据管理器 GlobalData.ts

// assets/Script/GlobalData.ts
import { _decorator } from 'cc';
const { ccclass } = _decorator;

// 全局数据结构,统一管理所有跨场景数据
export type GameData = {
    // 你的软体肉块配置
    meatSoftConfig: {
        springFreq: number,
        damping: number
    },
    // 液体物理参数
    liquidConfig: {
        viscosity: number,
        dropCount: number
    },
    // 玩家通用数据
    playerScore: number,
    unlockLevel: number
}

@ccclass('GlobalData')
export class GlobalData {
    // 单例静态实例
    private static _instance: GlobalData;
    public static get instance() {
        if (!GlobalData._instance) {
            GlobalData._instance = new GlobalData();
        }
        return GlobalData._instance;
    }

    // 全局存储仓库
    public data: GameData = {
        meatSoftConfig: { springFreq: 3.5, damping: 0.5 },
        liquidConfig: { viscosity: 0.3, dropCount: 0 },
        playerScore: 0,
        unlockLevel: 1
    }

    // 快捷修改数据方法
    setMeatSoft(freq: number, damp: number) {
        this.data.meatSoftConfig.springFreq = freq;
        this.data.meatSoftConfig.damping = damp;
    }

    addLiquidDrop(num: number) {
        this.data.liquidConfig.dropCount += num;
    }

    // 清空临时运行数据(切换关卡重置用)
    clearTempData() {
        this.data.liquidConfig.dropCount = 0;
    }
}

步骤2:保证脚本常驻,任意场景读写

任意场景脚本读取/修改数据示例

import { GlobalData } from './GlobalData';

// 读取肉块软体参数
const softCfg = GlobalData.instance.data.meatSoftConfig;
console.log('当前软度', softCfg.springFreq);

// 修改液体粘度,切换下一个场景依然保留
GlobalData.instance.data.liquidConfig.viscosity = 0.8;

// 切换场景API(场景加载后数据不变)
director.loadScene("Level2");

关键:为什么不会被场景销毁?

这个类是纯TS逻辑类,不绑定任何节点,不依附场景,只要游戏进程不关闭,数据永久存在。
适合:关卡切换、多场景共用物理配置、软体/液体全局参数。

方案2:常驻节点(PersistRoot,带组件逻辑共享)

如果你不仅要存数据,还要全局持续运行脚本(全局液体发射器、全局物理检测、全局计时器),用常驻节点。

  1. 初始启动场景创建空节点 GameRoot
  2. 挂载代码:director.addPersistRootNode(this.node)

    import { _decorator, Component, director } from 'cc';
    const { ccclass } = _decorator;
    
    @ccclass('GameRoot')
    export class GameRoot extends Component {
     // 这里可以放全局数据 + 全局持续逻辑(液体全局生成、物理全局控制)
     public liquidTotal = 0;
    
     onLoad() {
         // 设置节点跨场景常驻,切换场景不会销毁
         director.addPersistRootNode(this.node);
     }
    }
  3. 任意场景获取常驻节点:

    const root = director.getScene().getChildByName("GameRoot")!.getComponent(GameRoot);
    root.liquidTotal += 10;

    适用场景:需要全局持续运行的物理、特效管理器。

方案3:附加式场景(Additive 叠加场景,互相直接访问节点数据)

如果你不是销毁切换场景,而是多层场景同时显示(UI场景 + 物理关卡场景并行):

// 加载叠加场景,两个场景同时存在,节点互通
director.loadScene("UIScene", { additive: true });

特点:

  1. 两个场景节点树共存,可以直接 find() 另一个场景的节点、组件读取数据;
  2. 缺点:场景多了层级混乱,不适合频繁切换关卡。

方案4:本地持久化存储(游戏关闭再打开依然保留数据)

上面两种只保内存,游戏关闭数据清空;需要永久存档用 sys.localStorage,搭配全局单例封装。

扩展全局单例,增加存档/读档

// 写入本地存档
saveToLocal() {
    const str = JSON.stringify(this.data);
    sys.localStorage.setItem("game_save", str);
}

// 启动读取存档
loadFromLocal() {
    const str = sys.localStorage.getItem("game_save");
    if(str) {
        this.data = JSON.parse(str);
    }
}

使用时机:关卡完成调用 saveToLocal();游戏启动第一帧调用 loadFromLocal()

四、四种方案对比,按需选择

方案优点缺点适用场景
纯TS单例GlobalData最轻量、无节点依赖、读写极快不能挂载持续运行的组件90%项目,跨场景共享配置、数值(肉块/液体参数首选)
常驻Persist节点可运行全局脚本、全局物理/特效管理器多常驻节点容易混乱需要全局持续逻辑(全局液体生成器、全局碰撞检测)
Additive叠加场景直接访问跨场景节点内存占用高,场景销毁麻烦UI与游戏场景分层、双场景同时显示
localStorage持久化永久保存,重启游戏不丢失只能存简单JSON,不能存对象/节点存档、玩家设置、解锁内容

五、实战避坑重点(踩坑总结)

  1. 不要把场景内节点、RigidBody、粒子放进全局数据
    切换场景后原场景节点会被销毁,保存引用会报错、内存泄漏;只存数值、配置参数,不存场景实体。
    正确:存液体粘度数字、弹簧刚度数值
    错误:存肉块质点Node、水滴预制体实例
  2. 多场景同时修改同一全局数据,数据冲突处理
    复杂项目加事件分发EventTarget,数据修改发送事件,所有场景监听自动刷新:

    import { EventTarget } from 'cc';
    export const gameEvent = new EventTarget();
    
    // 修改数据后派发事件
    GlobalData.instance.setMeatSoft(4,0.6);
    gameEvent.emit("meatConfigChange");
    
    // 其他场景监听数据更新
    gameEvent.on("meatConfigChange", ()=>{
     // 重新更新肉块软体弹簧参数
    })
  3. 切换场景清空临时数据
    每进新关卡执行 GlobalData.instance.clearTempData(),清除本关卡临时液体粒子计数,保留全局解锁、设置。
  4. 物理资源跨场景复用
    预制体(水滴、肉块)不要每个场景重复加载,在启动场景一次性加载存入全局单例,所有场景复用,减少卡顿。

六、你的软体/液体项目推荐组合(最优解)

  1. 基础:纯TS全局单例 GlobalData 存储所有软体、液体物理参数、玩家数据
  2. 全局特效:创建一个 Persist 常驻节点,挂载全局液体粒子管理器,全程生成水滴不中断
  3. 存档功能:单例封装 localStorage 实现配置永久保存
  4. 数据同步:搭配 EventTarget 事件,修改参数后自动刷新场景内所有肉块、液体物理效果

Cocos Creator 3.8.8 液体物理完整方案(适配你的肉块软体场景)

分三类方案,从低成本流体视觉 → 粒子流体 → 真实物理液体,按需选择,包含滴落、滩涂、沿斜坡流动、和肉块软体交互效果。
环境前提:3.8.8 内置 Ammo 3D物理 / Box2D 2D物理,无原生流体组件,全部靠扩展实现。

一、粒子模拟流体(90%小游戏首选,性能好、能沿斜面流动)

核心原理

大量带物理刚体的小球粒子模拟水滴/液体,重力下落、碰撞凹凸地面后受摩擦力沿坡面滑动、互相碰撞堆叠成水滩;可和之前弹簧质点肉块发生碰撞交互。

1、2D液体实现(Box2D)

  1. 粒子预制体

    • Node:水滴
    • RigidBody2D Dynamic,质量极小0.05
    • CircleCollider2D
    • 物理材质:摩擦力0.3、弹力0.05(低回弹,水不会乱弹)
  2. 发射器脚本:定时生成水滴粒子,设置初始速度
  3. 液体聚合效果

    • 粒子碰撞后叠加局部阻尼,落地后速度快速降低,堆积形成水洼
    • ChainCollider2D 凹凸斜坡自动引导粒子顺着边缘流动
  4. 销毁规则:停留地面超过5秒自动销毁,避免粒子爆炸卡顿

    2、3D液体实现(Ammo)

    水滴小球SphereCollider刚体,MeshCollider凹凸地形自动导流;
    增加粒子颜色叠加、透明度,大量粒子重叠模拟半透明水体。

    优缺点

    开发快、性能友好、支持和软体肉块碰撞、自动沿斜坡流动
    无流体压力、不会扩散摊开成薄水膜,仅点状水滴

简易生成水滴TS代码(3D)

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

@ccclass('LiquidDropEmitter')
export class LiquidDropEmitter extends Component {
    @property(Node) dropPrefab!: Node;
    @property dropSpeed = 3;
    private timer = 0;

    update(dt: number) {
        this.timer += dt;
        if(this.timer > 0.1) {
            this.timer = 0;
            const drop = instantiate(this.dropPrefab);
            drop.setParent(this.node.parent);
            drop.setWorldPosition(this.node.worldPosition);
            // 随机横向偏移,模拟液体散开
            drop.getComponent(RigidBody)!.setLinearVelocity(new Vec3(
                (Math.random()-0.5)*this.dropSpeed,
                -this.dropSpeed,
                0
            ))
        }
    }
}

二、网格流体(2D 流体变形,滩涂、液体摊开,适合桌面积水)

实现方案: metaball 元球流体(视觉流体)

  1. 底层逻辑:多个水滴粒子作为元球,Shader叠加融合,视觉连成一整片液体;
  2. 物理层还是上面的刚体水滴,渲染层用后处理元球Shader融合,实现连续水面;
  3. 斜坡流动:刚体粒子沿凹凸地面滑动,元球跟随粒子位置实时更新,液体顺着台面边缘流淌;
  4. 和肉块交互:液体粒子碰到软体质点刚体产生碰撞,水被肉块挤开。

    局限

    仅视觉融合,无真实流体压强,无法模拟水压冲击、波浪。

三、SPH 光滑粒子流体动力学(真实物理液体,专业流体)

核心特性(真实水物理)

  • 具备密度、压力、粘度;液体挤压会向四周摊开,高处流向低处,斜坡自然流淌;
  • 撞击物体产生水花、飞溅;液体能包裹、推开软体肉块;
  • 粘度可调:低粘度清水、高粘度蜂蜜/粘稠酱汁(贴合你肉块软体需求)

    Cocos 3.8.8 两种接入方式

  • 开源JS SPH库 + Ammo物理联动(Web端)
    手写SPH计算循环,每一帧遍历所有液体粒子,计算压力、粘性力,更新粒子速度,再同步给Ammo刚体做碰撞;
  • 外部烘焙方案(性能优化)
    Blender烘焙流体动画,VAT顶点动画导入,仅播放固定水流动画,无法实时交互,不能和肉块动态碰撞

    缺点

    SPH每帧计算量大,粒子超过300移动端严重掉帧,仅适合少量液体特效。

四、Ammo 软体模拟粘稠液体(蜂蜜、酱料,软质流体)

承接你之前的肉块弹簧质点方案:
把大量微小质点用极软弹簧约束连接(Frequency=1.5,阻尼0.2),整体表现粘稠流体;

  • 低刚度弹簧:质点极易拉伸、摊开,像液体流动
  • 高阻尼:流动缓慢,粘稠不飞溅
  • 掉落在凹凸表面会顺着轮廓缓慢铺开,可和肉块软体互相挤压形变

五、关键细分需求调参指南

1. 清水(流动快、易散开)

粒子质量0.03,摩擦力0.2,弹力0.05,弹簧刚度极低(SPH粘度0.1)

2. 酱汁/粘稠液体(慢流、挂壁、贴合物体)

粒子质量0.08,摩擦力0.5,SPH粘度0.8;弹簧软体方案阻尼0.7

3. 沿凹凸桌面滑动核心设置

地面必须使用 ChainCollider2D(2D) / MeshCollider(3D)
禁用多个分离方块碰撞体,否则液体容易卡缝隙;刚体开启CCD连续碰撞防止穿模。

4. 液体与肉块软体交互

液体粒子刚体 和 肉块质点刚体 开启互相碰撞;
粘稠液体撞击肉块时,给肉块增加额外冲击力,实现肉块被水冲得晃动。

六、选型快速推荐

  1. 只需要滴水、水花、沿桌子流淌、和肉块简单碰撞 → 粒子刚体流体(方案一)(首选,低成本)
  2. 需要一整片积水、液体融合成水面视觉 → 粒子+元球Shader(方案二)
  3. 追求真实水压、波浪、粘稠酱汁摊开效果 → SPH流体(方案三,性能消耗高)
  4. 模拟果冻、粘液这类半固半液软物质 → 弹簧质点软体(承接你之前肉块方案)

七、性能优化

  1. 屏幕外液体粒子直接休眠刚体、停止计算;
  2. 单场景液体粒子上限控制在200以内;
  3. 移动端放弃SPH,只用简单粒子流体;
  4. 积水静态区域,超出5秒未动的粒子合并为静态面片,停止物理计算。

Cocos Creator 3.8.8 肉块软体(软胶左右晃动+落地沿斜坡滑动)完整实现方案

先讲核心前提:Cocos 3.8.8 内置Ammo(Bullet)不直接封装原生SoftBody软体,没有一键网格柔体组件,分3套方案,按需求选:

  1. 简易弹簧质点方案(推荐,2D/3D通用、性能高、满足肉块晃动+斜坡滑动)(你的需求首选)
  2. VAT预烘焙顶点动画(纯视觉晃动,无真实物理碰撞滑动,仅美术动画)
  3. 底层Ammo原生SoftBody(最真实布料/肉块,复杂、多bug、移动端性能差)

需求拆解

你要两个核心效果:
① 肉块本体柔软、左右惯性晃动、挤压形变;
② 自由落体掉落在桌面/凹凸斜坡,沿物体边缘自然滑动、受摩擦力停下。

方案一:弹簧质点网格(最优,实战肉块/果冻通用)

原理

把一张肉块图片/3D模型拆成多个小块质点,每个质点带刚体,用弹簧关节(DistanceJoint) 互相绑定;
中心质点质量大、边缘质点质量小,受力时边缘滞后晃动,模拟软体;
整体外层加一个大碰撞盒处理全局重力、落地、斜坡滑动;凹凸地面用ChainCollider2D/网格碰撞体实现沿边滑动。

分2D、3D两套流程(先讲2D,最常用)

一、2D肉块软体(Box2D物理,适合小游戏2D肉块)

1. 环境开启

项目设置 → 功能裁剪 → 开启 2D物理Box2D,重力设 (0,-9.8)

2. 肉块节点结构(分层质点)

MeatRoot(总根,静态刚体,仅做视觉父节点,不参与物理)
├─ CenterPoint(中心质点,Dynamic刚体,质量5,核心)
│  Sprite:肉块中心贴图
│  RigidBody2D Dynamic
│  CircleCollider2D
├─ Left1 Left2(左侧边缘质点,质量1)
├─ Right1 Right2(右侧边缘质点,质量1)
├─ Top1 Top2(上边质点)
└─ Bottom1 Bottom2(下边质点)

3. 弹簧关节绑定(核心晃动逻辑)

给每个边缘质点添加 DistanceJoint2D(弹簧关节)

  1. ConnectedBody 绑定中心质点刚体
  2. 参数设置(肉块软度关键)

    • Max Length:质点之间初始距离(不拉伸)
    • Frequency:3~6(越小越软,果冻肉块用3,硬肉用6)
    • Damping Ratio:0.4~0.7(阻尼,控制晃动衰减,0无衰减疯狂抖,1立刻停)
    • Collide Connected:勾选,质点之间可以互相碰撞挤压

效果:整体移动/落地撞击时,边缘质点延迟跟随,自然左右来回晃动,完美模拟软肉抖动。

4. 落地+斜坡沿边滑动实现(解决你第二个需求)

地面设置(凹凸不平、桌子、斜坡)

  • 平面桌子:BoxCollider2D Static
  • 不规则凹凸/斜坡:ChainCollider2D(链条碰撞体,贴合曲线边缘,刚体落地会自动沿坡面滑动,不会卡穿)
  • 物理材质统一配置:
    friction=0.6(摩擦力,数值越大滑得越慢)
    restitution=0.1(低弹性,肉块落地轻微回弹不乱飞)

全局移动/下落物理规则

  1. 中心质点RigidBody2D开启UseGravity,自动下落;
  2. 掉落撞击地面后,物理引擎自动计算坡面法线,Dynamic刚体自带沿斜面滑动逻辑;
  3. 若滑动太滑:提高friction至0.8;滑不动降低到0.3。

5. 视觉合并(所有质点贴图拼成完整肉块)

所有质点使用同一张肉块分割贴图,拼合后视觉是完整一块肉,物理上是弹簧绑定的质点网格。
进阶优化:用MeshSprite2D网格贴图,直接一张图拆分顶点质点,不用多张子图。

简易TS弹簧质点代码(自动生成关节)

import { _decorator, Component, Node, RigidBody2D, DistanceJoint2D, math } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('SoftMeat2D')
export class SoftMeat2D extends Component {
    @property(Node) center!: Node;
    @property([Node]) points: Node[] = [];
    @property springFreq = 3.5; // 软度
    @property damping = 0.5;

    start() {
        const centerRb = this.center.getComponent(RigidBody2D)!;
        this.points.forEach(point => {
            const joint = point.addComponent(DistanceJoint2D);
            joint.connectedBody = centerRb;
            joint.frequency = this.springFreq;
            joint.dampingRatio = this.damping;
            joint.collideConnected = true;
        })
    }
}

二、3D肉块软体(Ammo物理,3D游戏)

关键区别

  1. 物理后端切换:项目设置 → 3D物理 → 选择 Ammo.js
  2. 关节:3D用 PointToPointConstraint(点对点弹簧约束,无内置组件,需要代码创建约束)
  3. 碰撞体:SphereCollider胶囊质点,凹凸地面用MeshCollider静态网格
  4. 滑动逻辑:Dynamic刚体落地后自动贴合Mesh坡面滑动,物理材质friction控制滑行速度

3D质点约束核心代码片段

import { RigidBody, Node, Vec3, physics } from 'cc';

// 获取两个刚体ammo原生body
const bodyA = this.centerRb.body;
const bodyB = pointRb.body;
// 创建弹簧点对点约束
const p2p = new physics.AmmoPoint2PointConstraint(
    bodyA, bodyB,
    new physics.AmmoVector3(0,0,0),
    new physics.AmmoVector3(0,0,0)
);
// 弹簧软硬参数
p2p.setStiffness(3.5);
p2p.setDamping(0.5);
physics.PhysicsManager.instance.world.addConstraint(p2p);

方案二:VAT顶点烘焙动画(仅视觉晃动,无真实物理滑动)

适用场景:不需要落地碰撞滑动,只需要肉块原地左右软晃动展示。

  1. 外部Blender/Houdini做肉块柔体模拟动画,烘焙VAT顶点动画贴图;
  2. 导入Cocos,使用VAT材质播放形变动画;
  3. 缺点:无实时物理,掉落到斜坡不会自动滑动,固定动画循环,无法交互。
    你的需求包含落地沿物体滑动,不推荐此方案

方案三:底层Ammo原生SoftBody(真实网格软体,高成本)

Ammo引擎原生支持btSoftBody完整网格布料/肉块,但Cocos 3.8.8没有封装组件,需要手写大量底层WASM交互代码:

  1. 替换物理世界为SoftRigidDynamicsWorld;
  2. 手动创建软体网格、弹簧约束、与静态地面碰撞检测;
  3. 缺陷:

    • 代码量巨大,调试困难;
    • Web/移动端性能开销极高,多肉块会掉帧;
    • 凹凸坡面滑动需要额外法线投影计算;
      仅适合重度3D物理游戏,普通肉块效果完全没必要,优先方案一。

关键参数调优(肉块软硬、滑动手感)

1. 软度晃动控制(弹簧参数)

  • Frequency 2~4:超软果冻,大幅度左右晃动
  • Frequency 4~7:正常肉块,轻微惯性抖动(推荐)
  • Damping Ratio 0.3:晃动久、回弹多;0.7:快速稳定、轻微抖动

2. 落地滑动手感(物理材质)

  • friction=0.4:光滑桌面,滑很远
  • friction=0.7:粗糙台面,落地很快停下
  • restitution=0~0.1:肉块不弹飞;0.3会弹跳

3. 防止落地穿模

  1. Dynamic刚体开启CCD连续碰撞检测;
  2. 物理迭代次数调高:项目设置物理 → 位置迭代10,速度迭代10;
  3. 凹凸地面必须用ChainCollider2D(2D)/MeshCollider(3D),不要分开多个小方块碰撞体。

性能优化要点(多肉块场景)

  1. 质点数量控制:小型肉块4~6个质点足够,不要超过10个;
  2. 不需要实时形变的地方用VAT预烘焙动画替代物理质点;
  3. 屏幕外肉块直接关闭刚体模拟、休眠刚体;
  4. Web平台优先2D Box2D弹簧方案,3D Ammo软体容易卡顿。

最终选型建议

你需求:软肉左右惯性晃动 + 掉落凹凸物体沿边缘滑动
直接用【方案一:弹簧质点网格】2D/3D二选一,开发速度最快、性能稳定,完全满足交互物理需求,不需要啃底层SoftBody复杂代码。

VitePress 完整通俗讲解(结合你之前 MineAdmin 文档场景)

1. 一句话定义

VitePress 是 Vue 官方出品、基于 Vite + Vue3 的静态站点生成工具(SSG),专门用来快速搭建项目文档、技术手册、博客网站,MineAdmin 的全套文档就是用它做的。

简单拆解名字:

  • Vite:新一代前端构建工具,启动、热更新极快;
  • Press:文档/站点生成(前身 VuePress)。

2. 核心原理(MineAdmin 文档就是这套流程)

  1. 你写一堆 .md Markdown 文件(MineAdmin 文档仓库里全是 md);
  2. VitePress 读取 md,自动生成侧边栏、导航、搜索、代码高亮;
  3. 本地运行 yarn dev 开启开发预览,改 md 页面秒刷新;
  4. 打包 yarn build 输出纯静态 HTML/CSS/JS,丢到服务器就能在线访问(doc.mineadmin.com 就是打包后的产物)。

3. 关键特性(为什么几乎所有前端开源项目都用它做文档)

  1. 极致开发速度
    依托 Vite,启动服务器几乎瞬间,修改文档保存 <100ms 页面自动刷新,不用等待打包,写文档体验极好。
  2. Markdown 增强 + 支持 Vue 组件

    • 原生支持代码块高亮、折叠代码、提示框、目录、多语言;
    • md 文件里可以直接写 Vue 组件,文档里能嵌入可交互演示组件(比如 MineAdmin 展示表单、表格组件示例)。
  3. 自带成熟文档主题
    默认模板自带:顶部导航、侧边目录、全局搜索、暗黑模式、版本切换、页内锚点,开箱即用,不用自己写页面布局。
  4. 性能兼顾首屏与跳转

    • 首次打开:预渲染静态 HTML,加载速度快;
    • 页面间切换:自动转成单页应用 SPA,无刷新跳转,丝滑。
  5. 部署零门槛
    build 完只有静态文件,可部署 Nginx、Gitee Pages、GitHub Pages、云存储,不需要后端服务。

4. 和 VuePress 的关系(历史)

  • VuePress 1.x:老一代,Vue2 + Webpack,启动慢、热更新卡顿;
  • VitePress:Vue 团队重做的升级版,Vue3 + Vite,性能全面碾压,现在官方主推,VuePress 基本不再维护。

5. 对应你 MineAdmin 文档的实操逻辑

MineAdmin 文档仓库 mineadmin-doc 就是标准 VitePress 项目:

  1. 目录下全是 Markdown 教程文档;
  2. 配置文件控制导航、侧边栏、版本切换;
  3. yarn dev 本地跑旧版/新版文档;
  4. 打包后上传,对外访问 doc.mineadmin.com。

6. 适用场景

  • 开源项目技术文档(Vue、Vite、MineAdmin、Element Plus 全部在用)
  • 私人技术笔记、知识库、博客
  • 内部系统接口手册、开发规范文档

7. 极简使用流程(看懂即可本地跑 MineAdmin 旧文档)

# 1. 拉取 MineAdmin 文档仓库
git clone https://gitee.com/mineadmin/mineadmin-doc.git
cd mineadmin-doc

# 2. 安装 VitePress 依赖
yarn install

# 3. 本地启动文档站点
yarn dev

# 4. 打包静态文件用于线上部署
yarn build

访问 http://localhost:5173 就能离线查看完整旧版 MineAdmin 前端文档。