Amazonで商品を見るセール会場へ

Unityエフェクト素材の設定:UV・頂点色・スクロール・Billboard・連番

Unityでエフェクト素材を組み込む手順を、UV、頂点色、FBXのカーブ、UVスクロール、Billboard、連番Textureに分けて説明します。素材を作る工程と、Particle Systemを表示・制御する工程を分けると、不具合の原因を調べやすくなります。

参照仕様はUnity 6.3 LTSです。元記事のMaya・Photoshop・After Effects画像は旧資料として保存しています。今回これらの制作ソフトやUnityを実行した画像ではありません。掲載C#の修正版もUnityでのコンパイル・描画確認は未実施です。

目次

目的別に必要な設定を選ぶ

項目・症状設定・確認先
同じ模様を繰り返すUVとTextureのWrap Modeを確認。重ねたUVでは各領域へ独立した絵を描けない。
部分ごとに色を変えるMeshの頂点色と、それを読むShaderを用意。色データがあるだけで全Materialが反映するわけではない。
薄い板をCameraへ向けるParticle SystemのRenderer設定、またはMesh用Billboardを選ぶ。向きとCameraを固定して確認。
雲や光の模様を流すTexture Offsetを動かす。共有Materialの値を直接変更しない。
連番素材を再生する画像の格子とTexture Sheet AnimationのTilesを合わせる。Alpha、寿命、開始Frameも確認。

加算、両面、CutoutなどShaderの選び方はアニメーション用Shaderの記事、色変換はLinear/Gammaの記事で確認できます。Materialを共通化しただけで必ず描画回数が減る、という判断はしません。

UVを重ねる:素材を共有できる形に限定する

次の旧画像は、似た模様を使う面のUVを重ねる例です。4領域を1領域へまとめても、元の独立した絵をすべて維持できるとは限りません。対称・反復を利用できる形で検討し、必要な部分へ同じ模様が出るか確認します。

UVを4つ折りに重ねて配置し、解像度を保ったままテクスチャサイズを抑える設定例。
  1. UVを表示し、各面に固有の絵が必要か、同じ絵を繰り返せるかを決めます。
  2. チェック模様を割り当て、向き、継ぎ目、伸び、重なりを確認します。
  3. Textureを縮小する場合は、対象Cameraの距離と端末で輪郭やにじみを比較します。UVを重ねたことだけで解像感が維持されるとは判断しません。

Draw call batchingとSRP Batcherは別の仕組みです。Mesh/Particle、透明描画の順序、Shader、Passなど条件があるため、Texture AtlasやMaterial共有の効果は実際の描画とProfilerで確認します。ここでは性能を測定していません。

Texture SheetのFrame設定を単独で確認する

旧画面のFrame over Timeは、現在のすべての版で「0、1、2、3をそのままセル番号として入力する」欄とは扱いません。使うモード、Tiles、Start Frame、曲線を分けて確認します。

Tilesの分割数やFrame Over Timeのカーブを設定し、フレーム番号を指定する様子。
  1. まず2×2の各セルに異なる模様を入れた画像を用意します。
  2. Texture Sheet AnimationをGrid、Tilesを2×2、AnimationをWhole Sheet、Time ModeをLifetimeとして確認します。
  3. Frame over Timeを一定にし、Start Frameなど開始条件を変えて、どのセルが見えるかを記録します。
  4. 静止状態でセルと向きが分かってから、寿命に沿うFrameの曲線を付けます。ランダム設定は基本の確認後に追加します。

設定項目は公式のTexture Sheet Animationを参照します。旧画像の値を現行Editorへそのまま入力して同じ結果になることは、今回確認していません。

Meshの頂点色と変形をShaderへ渡す

MayaのLocatorやMeshを使った旧資料です。メッシュ変形のアニメーションと、頂点色による着色は別のデータとして確認してください。

Mayaでメッシュ変形アニメーションを用意し、変形に追従させるロケーターを配置する手順。
  1. まず頂点色が異なるMeshを用意し、Unityへ読み込んだデータを確認します。
  2. 使うShaderがMeshの頂点色を読んで最終色へ反映するか確認します。白一色になる場合、データの有無とShaderの対応を分けて調べます。
  3. Particleの頂点色を使うShaderでは、ParticleのStart ColorやColor over Lifetime、RendererのVertex Streamsも確認します。通常のMeshとParticleの受け渡しを同じものと決めつけません。

「MayaのViewport 2.0では表示できないため旧Viewportが必須」という説明は現在の一般的な手順として残しません。使用するMayaの版と表示設定を確認する必要があります。Particle用の現在の候補はURP Particles Unlitの公式説明を参照してください。

FBXのカーブを使う:Import値とMaterial値を分ける

Materialの半透明は、まず使うShaderをTransparentの設定にして確認します。下の旧Material画像は当時の例で、URP/HDRPの欄名や対応を保証するものではありません。

半透明対応シェーダーを設定し、アニメーションカーブでカラーやアルファを変化させる設定例。

MaterialのAlphaを0〜1で動かす場合と、画像編集画面の0〜255表示は区別します。MayaのTransparencyとUnity側のAlphaでは向きや意味が異なる場合もあります。元記事の255を使うLocatorカーブは旧資料です。

Graph Editorでキーの値をスケーリングし、FBX形式でエクスポートする手順。
  1. まずUnityのMaterialを手動で操作し、Alpha 0・0.5・1で期待した透明度になるか確認します。
  2. FBXを選び、AnimationのImportを確認します。公式のAnimationタブではAnimated Custom Propertiesなども説明されており、FBXはTransformだけを取り込むものではありません。
  3. カーブを転用する場合は、読み込まれたプロパティ、値の範囲、フレーム、補間、単位変換を確認します。旧LocatorのY値をMaterialへコピーするだけで正しいAlphaになるとは扱いません。
  4. 必要な値が得られないときは、Unity内で専用Animation ClipにMaterialのキーを付け、手動で確認した0〜1の範囲から切り分けます。
Unityでの作業に関する手順を示す図。

FBX内のClipを編集用に分ける旧例です。元データを再Importして変更が失われないよう、編集用ClipとImport由来のClipを区別します。Materialアニメーションの基本はCutoutのAnimation手順も参照できますが、ThresholdとAlphaは別の値です。

Unityでの作業において出力したFBXをインポートし、アニメーションクリップを複製して編集可能にする手順。

Alpha付きTextureを書き出す

次のPhotoshop画面は元記事のAlpha編集資料です。RGBの白黒画像、追加Alphaチャンネル、PNGとして保存された透明度を同じものと考えないようにします。

コピーしたアニメーションカーブキーを、マテリアルのアルファチャンネルにペーストする手順。
  1. 色と透明度を分けて編集し、必要なAlphaを持つファイルとして書き出します。
  2. 書き出した画像を再び開いてAlphaを確認します。
  3. UnityのImportプレビューでもAlphaを確認します。Shaderがどのチャンネルを読むか、MaterialのTintのAlpha、圧縮や境界を調べます。

UVスクロール:対象だけのMaterialを動かす

旧例ではsharedMaterialのOffsetを直接変更していました。同じMaterialを使う他のRendererへも影響するため、次の修正版は専用Materialコピーを作り、無効化・破棄時に解放します。SetTextureOffsetのプロパティ名はShaderに合わせます。

  1. ファイル名UVScroll.csで保存し、MeshRendererなどRendererを持つ対象へ追加します。
  2. URPの標準例はTexture Propertyを_BaseMap、旧Built-inの標準例は_MainTexとして確認します。独自ShaderはそのTextureプロパティ名を使います。HasPropertyで存在を確認しても、正しいTexture型やOffset対応まで保証するわけではありません。
  3. 継ぎ目なく流すTextureならWrap ModeをRepeatにし、ShaderがTextureのOffsetを使うことを確認します。まずSpeedを小さくし、他のRendererが同時に動かないか比較します。
  4. コンポーネントを無効化して元のMaterialへ戻るか確認します。他の処理が途中でMaterialを変えた場合、その新しい割り当てを上書きして戻さないようにしています。
using UnityEngine;

public class UVScroll : MonoBehaviour
{
    [SerializeField] private string textureProperty = "_BaseMap";
    [SerializeField] private Vector2 speed = new Vector2(0.1f, 0.1f);
    private Renderer targetRenderer;
    private Material originalMaterial;
    private Material ownedMaterial;
    private Vector2 initialOffset;
    private Vector2 movement;

    private void OnEnable()
    {
        targetRenderer = GetComponent<Renderer>();
        if (targetRenderer == null || targetRenderer.sharedMaterial == null)
        {
            Debug.LogWarning("RendererとMaterialを設定してください。", this);
            enabled = false;
            return;
        }
        originalMaterial = targetRenderer.sharedMaterial;
        ownedMaterial = new Material(originalMaterial);
        if (string.IsNullOrEmpty(textureProperty) || !ownedMaterial.HasProperty(textureProperty))
        {
            Debug.LogWarning("ShaderのTextureプロパティ名を確認してください。", this);
            Destroy(ownedMaterial);
            ownedMaterial = null;
            enabled = false;
            return;
        }
        initialOffset = ownedMaterial.GetTextureOffset(textureProperty);
        movement = Vector2.zero;
        targetRenderer.sharedMaterial = ownedMaterial;
    }

    private void Update()
    {
        if (ownedMaterial == null) return;
        movement += speed * Time.deltaTime;
        movement.x = Mathf.Repeat(movement.x, 1f);
        movement.y = Mathf.Repeat(movement.y, 1f);
        ownedMaterial.SetTextureOffset(textureProperty, initialOffset + movement);
    }

    private void OnDisable() { ReleaseMaterial(); }
    private void OnDestroy() { ReleaseMaterial(); }

    private void ReleaseMaterial()
    {
        if (ownedMaterial == null) return;
        if (targetRenderer != null && targetRenderer.sharedMaterial == ownedMaterial)
            targetRenderer.sharedMaterial = originalMaterial;
        Destroy(ownedMaterial);
        ownedMaterial = null;
    }
}

初期Offsetを保ち、Time.deltaTimeに従って動かす例です。Time Scaleが0なら進みません。Materialコピーが増えるため、性能やバッチングが改善するコードではありません。多数の対象へ使う場合は所有・解放と描画負荷を実環境で確認してください。次の素材画像は旧資料です。

メッシュ上のテクスチャを一定方向に流すUVスクロールの事前準備として用意する、切れ目のないシームレステクスチャ。

MeshのBillboard:Cameraと面の向きを決める

Particle System自体のBillboardならRendererのRender Modeを先に確認します。次のコードは通常のMeshなどを向ける例で、CameraをInspectorから指定します。未指定時だけCamera.mainを使い、見つからない間は回転を変えません。

  1. Billboard.csとして保存し、表示用Meshの専用子オブジェクトへ追加します。Animatorなど別の回転制御と同じTransformを奪い合わない構成にします。
  2. Target Cameraを指定します。Camera.mainを使う場合はMainCameraタグも確認します。複数Cameraを自動的に個別対応するコードではありません。
  3. QuadならまずLocal Euler Offsetを0にし、Cameraから見える面を確認します。PlaneやDCC由来のMeshは基準面が違うため、補正回転を合わせます。
  4. 透視CameraではCameraから対象への方向、OrthographicではCameraの前方向を使います。Cameraを移動・回転して、正しい面が見えるか確認します。
using UnityEngine;

public class Billboard : MonoBehaviour
{
    [SerializeField] private Camera targetCamera;
    [SerializeField] private Vector3 localEulerOffset = Vector3.zero;

    private void LateUpdate()
    {
        if (targetCamera == null) targetCamera = Camera.main;
        if (targetCamera == null) return;

        Vector3 direction = targetCamera.orthographic
            ? targetCamera.transform.forward
            : transform.position - targetCamera.transform.position;
        if (direction.sqrMagnitude < 0.000001f) return;

        transform.rotation = Quaternion.LookRotation(direction, targetCamera.transform.up)
            * Quaternion.Euler(localEulerOffset);
    }
}

LateUpdateで回転を更新します。Cameraと対象が同じ位置なら方向を決めず、そのフレームの回転を変更しません。親の回転・非一様Scale・負のScale、別の回転制御がある場合の表示は別途確認が必要です。

連番Texture:画像の格子と粒子の寿命を合わせる

次のAfter Effects画像は旧資料です。作成ツールは一つに限定せず、必要なFrame数、Alpha、セルの寸法を持つ連番シートを用意します。プラグインを購入すれば設定が完成する、という説明ではありません。

連番PNG画像を1枚のスプライトシートに結合して配置した例。
  1. 8Frameを横4×縦2で配置する例なら、1セル128×128の画像全体は512×256です。セルの順序を番号付き素材で先に確認します。
  2. Particle用Materialへ画像を割り当て、Texture Sheet AnimationをGrid、Tiles 4×2、Whole Sheet、Time ModeをLifetimeにします。
  3. 切り分け用にLoopをオフ、DurationとStart Lifetimeを1秒、Start Speedを0、Rate over Timeを0、0秒のBurstを1個にする構成を作ります。
  4. Frame over Timeを寿命全体で0→1、Cyclesを1として、開始・中間・終了で意図したセルへ進むか確認します。境界の補間や開始Frame、Alphaも確認します。
  5. 1粒で確認できてから、Burst数、寿命、ランダム、色、速度などを追加します。画面占有率や重なりの負荷は別途測定します。

上記は確認用に用意する条件と期待する動作で、今回実行した結果ではありません。既存の元記事のコード置き場には原版のコードがあり、本文の修正版と同一とは限りません。ここでは外部リポジトリを更新していません。

表示・サイズ・文字・衝突を組み込む

素材とMaterialを単独で確認した後、UI前面への表示、Particleのサイズ、RenderTextureの文字、衝突時の生成へ進んでください。素材準備と実行中の制御を分けた次の記事で扱います。

次に学ぶ・作業環境を選ぶ

学習を続けたい方や、作業環境を整えたい方は、目的に合うガイドをご覧ください。

Unityのおすすめ書籍

開発PCの選び方

周辺機器の優先度

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次