見出し画像

『あんさんぶるスターズ!!Music』足の動きに合わせてパーティクルを出す機能

はじめに

『あんさんぶるスターズ!!Music』(以下、あんスタ!!Music)でゲームエンジニアをしている M.M. です。

入社してちょうど4年、色々とあって1年半ほど前からあんスタ!!Musicのチームにジョインしました。
ジョインしてからも色々とあって現在は新規開発・運用のマネジメントをしつつ、実作業ベースでは3DライブMVの開発(主に初期のセットアップ)を担当しております。

あんスタ!!Musicでの推しキャラは「青葉 つむぎ」ですが、
眼鏡の一彩くんを見た瞬間気づいたら全てのダイヤが溶けていました。。

さて、この記事ではあんスタ!!Musicで開発した機能を紹介したいと思います。

「夏鳥の詩 -サマーバード-」の水面

「夏鳥の詩 -サマーバード-」ではキャラクターが湖の上でダンスするパートがあり、
キャラクターの足と水面が常に接触していて波紋や水しぶきのパーティクルの設定に課題がありました。
手付けで設定するには物量が多く、またキャラクターを入れ替えることで足の位置も変わってきます。
今回はキャラクター足の動きに合わせてパーティクルを自動発生させる機能を作成して対応しました。

接触判定〜パーティクル発生まで

自作のタイムラインスクリプトで以下のような順序で処理を行います。

  • キャラクターの足と床が接触しているかを判定

  • 「接触開始時」「接触終了時」「接触しながら足を動かした時」にイベントを発火

  • バースト設定からパーティクルを発生

まず、キャラクターの足と床の接触については足の指先(toes)と足首(foot)の位置を基準に床と接触しているかを判定します。
また足の位置は一定フレーム数記録しておいて速度の計算に使用します。

C#

// clip 変数は後述の ParticleSystemBursterClip
var detectHeight = floorHeight + clip.ContactPositionOffset;
GetCharacterTransforms(out var foot, out var toes);
var toesPosition = toes.position - new Vector3(0f, ToesContactSize, 0f);
var footPosition = foot.position - new Vector3(0f, FootContactSize, 0f);
if (toesPosition.y < detectHeight)
{
    if (footPosition.y < detectHeight)
    {
        var averagePosition = 0.5f * (toesPosition + footPosition);
        _contactPosition = new Vector3(averagePosition.x, floorHeight, averagePosition.z);
    }
    else
    {
        _contactPosition = new Vector3(toesPosition.x, floorHeight, toesPosition.z);
    }
    _contacting = true;
}
else if (footPosition.y < detectHeight)
{
    _contactPosition = new Vector3(footPosition.x, floorHeight, footPosition.z);
    _contacting = true;
}
else
{
    _contacting = false;
}
// この中で足の位置を記録
_footRecordedPosition.Record(playableTime, footPosition);
_toesRecordedPosition.Record(playableTime, toesPosition);

次に前回の接触判定を考慮しつつ「接触開始時」「接触終了時」「接触しながら足を動かした時」にイベントを発火します。

C#

if (_contacting)
{
    if (contactingBefore)
    {
        Burst(playableTime, GetDragSpeed(), clip.BurstOnDrag);
    }
    else
    {
        Burst(playableTime, GetTouchOnOffSpeed(), clip.BurstOnTouchOn);
    }
}
else
{
    if (contactingBefore)
    {
        Burst(playableTime, GetTouchOnOffSpeed(), clip.BurstOnTouchOff);
    }
}

最後に実際にバーストさせる部分では設定されたパラメーターを考慮しつつ Burst データを作成して、
ParticleSystem.emission.SetBursts() でパーティクルを発生させます。

Timeline のクリップによる制御

例えば波紋の設定をしているクリップは以下のようなパラメーターで制御しています。

ParticleSystem はキャラクターの片足ごとに作成する想定で、
今回の MV では 3人 * 2(両足) * パーティクル3種(波紋、波紋ノーマルマップ、水しぶき) で作成しています。

ParticleSystemBursterClip

BurstData

BurstDataModifier

BurstDataModifier

おわりに

いかがでしたでしょうか。
簡単にですが今回作成した機能について紹介させていただきました。

足元のパーティクルなのでなかなか気づきにくいですが、こうした細部にもこだわってあんスタ!!Musicの MV は作成されています。
来年も新しい楽曲がどんどん公開されると思うので、キャラクター以外の演出部分にも注目していただけると幸いです。

おまけ

ちなみに今回作成した機能は「FIST OF SOUL」の砂煙でも使用されています!
(かなり注意して見ないと気づかないかも……?!)


Happy Elements株式会社 カカリアスタジオでは
いっしょに「熱狂的に愛されるコンテンツ」をつくっていただけるメンバーを大募集中です!
もし弊社にご興味持っていただけましたら、是非一度
下記採用サイトをご覧ください!