CrossRoad

XRを中心とした技術ブログ。 Check also "English" category.

ソードアートオンラインのオブジェクトが消えるエフェクトを作ってみました

今さらかもしれませんが、最近ソードアートオンライン (Sword Art Online : SAO) のアニメにはまっています。
今はガンゲイルオンライン編を見てます。

はまったついでに、SAOで共通して使われる物体が消える (ゲーム内のアイテム消費とか) エフェクトをBabylon.jsで再現してみました。

1. ソードアートオンラインとは

WikiPediaでの解説によると、ライトノベルから始まった小説です。その後アニメ、ゲーム、映画化されていったようです。

ソードアート・オンライン - Wikipedia

ストーリーは、2022年に人類が完全な仮想空間を実現したというところから始まります。身体的な感覚を全て仮想世界での体験に使えるデバイスを使って、ファンタジー世界の中に入って楽しむバーチャルMMO (Massively Multiplayer Online) ゲームの名称が「ソードアートオンライン」です。ストーリーの中のゲーム名でもあり、タイトルでもあるということですね。

あるとき製作者がゲームを中止する「ログアウト」機能を無効にし、ゲーム内で体力がゼロになると現実でも反映されてしまう (現実で使っているVRヘッドセットから高周波の電流?が流れる) 、現実に戻るには最上階まで行ってゲームをクリアするしかないと伝えます。主なストーリーはここから始まります。

INTRODUCTION | Aincrad | TVアニメ「ソードアート・オンライン」オフィシャルサイト

ソードアートオンラインの世界では、オブジェクトが消えるとき三角ポリゴンが散るようなエフェクトがかかります。

2. オブジェクトが消えるエフェクト

abema.tv

この動画の4:20付近の表現です。基本的な操作練習をしてモンスター退治をする場面で出てきます。

まず、対象物が青いグリッド状になり、その後で小さな破片となって散り、数秒で消えています。

今回はこれをBabylon.jsで表現しました。

Fragment object as SAO

Babylon.jsの処理をソースコード付きで確認できるPlaygroundに書いたので、こちらを見ていただければ詳細確認可能です。
https://playground.babylonjs.com/#XU5JER#12

以降では、Playgroundに書いた処理を少し解説します。

3. ベースにしたサンプルコードと変更内容

Solid Particle System (SPS) を使いました。まだあまり調べられていませんが、SPSは多数の物体を効率的に表示させる仕組みです。digestという機能のサンプルコードがあり、これを元にして変更しました。

Digest feature of SPS sample on Babylon.js

元のコードはこちらです。

https://www.babylonjs-playground.com/#BF4A8E

主な変更箇所です。

■破片が地面に転がるのではなく、空に浮く感じにする

sps.updateParticle = function(p) {
//途中省略
//p.velocity.y += gravity;
p.velocity.y -= gravity; 
//途中省略

■破片を光らせる、grid表示にする

//glow layer
    var gl = new BABYLON.GlowLayer("glow", scene, {
    blurKernelSize: 32
});

//途中省略
    var mat_grid = new BABYLON.GridMaterial("knotMaterial", scene);
//途中省略
    mat_grid.emissiveColor = BABYLON.Color3.Blue();

■メッシュがクリックされたら、元のメッシュを削除して破片が散る感じにする

scene.onPointerDown = function(evt, pickResult) {
       // if (digested) {
            
            var pickResult = scene.pick(scene.pointerX, scene.pointerY);
            if (pickResult.hit) {
                if(pickResult.pickedMesh.name =="s"){
                    digested=true;
                    model.dispose();//元のメッシュを削除
                    var s = sps.buildMesh();
                    s.material = mat_grid; //破片表示されるメッシュにgrid マテリアルを当てる
//途中省略

4. おわりに

Solid Particle Systemのおかげで、思ったよりは簡単に表現できました。ただ、今の書き方ではここで表示したTorusKnot以外では失敗するので、任意の3DCGモデルでできるようにもう少し調べてみます。