スプライトエディター
Cluster Rendering

スプライト パッカー

Suggest a change

Success!

Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable.

Close

Sumbission failed

For some reason your suggested change could not be submitted. Please try again in a few minutes. And thank you for taking the time to help us improve the quality of Unity Documentation.

Close

Cancel

スプライト画像をデザインする際,各キャラクター毎のテクスチャファイルとして作業すると便利でです。しかし,スプライトテクスチャの大部分は,多くの場合,グラフィック要素が空の領域に取り込まれ,この空間は実行時に無駄なビデオメモリを消費します。最適なパフォーマンスのために,いくつかのスプライトテクスチャ画像を一緒にまとめてアトラスとして知られている単一のテクスチャにパックするのが最善です。Unityは,個々のスプライトテクスチャからアトラスを生成するプロセスを自動化するユーティリティ Sprite Packerを提供します。

Unityがスプライトアトラステクスチャの生成と処理を行い,ユーザーは手動で割り当てを行う必要はありません。アトラスは必要に応じて再生モードへの移行やビルド時にパックすることができ,スプライトオブジェクトの画像がアトラスから生成されて取得できます。

ユーザーはそのテクスチャのスプライトのパッキングを有効にするテクスチャインポータでパッキングタグを指定する必要があります。

スプライトパッカーの使い方

スプライトパッカーは,デフォルトでは無効になっていますが,エディタの設定からそれを設定することができます。メニューから Edit -> Project Settings -> Editor)スプライトパッキングモードは Disabled から Enabled for Builds (すなわち,パッキングはビルドで有効,プレイモードでは無効),または Always Enabled (すなわち,パッキングはプレイモードとビルドの両方に有効)に変更できます。

Sprite Packer windowを開き(menu: Window -> Sprite Packer) ,左上の隅のPack ボタンをクリックし,アトラス内にパックされたテクスチャの配置を参照してください。

プロジェクトパネルでスプライトを選択した場合は,アトラスでの位置を示すために強調表示されます。輪郭は実際のメッシュの輪郭を描画し,それはまた,結合したパッキングの領域を定義する。

スプライトパッカーウィンドウ上のツールバーには,パッキングとビューイングのためのコントロールを数持っています。Packボタンは,パッキング処理を初期化しますが,アトラスは最後にパッキングされてから,変更がなければ自動更新することはしません(下記のCustomizing the Sprite Packerで説明しているとおり,カスタムパッキングポリシーを実装する際にRepackボタンが表示されます)。View AtlasPage # のメニューでは,どのアトラスか,どのページかを選択することを決めることができます(最大テクスチャサイズで全てのスプライトのため十分なスペースがない場合は,一つのアトラスを複数の「ページ」に分割することができます)。ページ番号の横のメニューでアトラスのために使用される“パッキング ポリシー” を選択できます(下記参照)。ツールバーの右にある2つのコントロールでビューをズームするとアトラスのためのカラーとアルファー表示を切り替えることができます。

Packing Policy

スプライトパッカーは,アトラスにスプライトをどう割り当てるか方法を決めるためにpacking policyを使用しています。あなた自身の独自のパッキングポリシーを作成することは可能ですが(下記参照),Default Packer PolicyTight Packer Policy オプションが常に用意されており,使用できます。これらのポリシーでは Texture ImporterPacking Tag プロパティはアトラスの名前で選択してスプライトはパックされます。したがって同じパッキングタグを持つすべてのスプライトを同じアトラスにパックされます。アトラスはさらにテクスチャのインポート設定により,ソーステクスチャにセットした内容と合致するようにソートされます。

  • “[TIGHT]”Packing Tagで指定されていない限り,DefaultPackerPolicyは,デフォルトでは矩形のパッキングを使用します(つまり,”[TIGHT]Character"とパッキングタグを設定すれば密接にパッキングします)。
  • TightPackerPolicyは,スプライトがタイトメッシュを持っている場合,デフォルトではタイトパッキングを使用します。“[RECT]”が Packing Tagで指定されている場合は,矩形パッキングが行われます(つまり,あなたのパッキングタグは”[RECT] UI_Elements”に設定し,矩形パッキングになります)。

スプライトパッカーのカスタマイズ

DefaultPackerPolicyオプションはほとんどの目的には十分ですが,あなた自身が必要とする場合,独自のカスタム·パッキングポリシーを実装することができます。これを行うには,エディタ·スクリプトでクラスのUnityEditor.Sprites.IPackerPolicyインタフェース を実装する必要があります。このインタフェースには次のメソッドが必要です。

  • GetVersion - パッキング ポリシーのバージョン値を返します。ポリシースクリプトに変更がある場合にバージョンが一つあがり,バージョン管理にこのポリシーが保存されます。
  • OnGroupAtlases - ここにパッキングロジックを実装します。 PackerJobのアトラスを定義し,与えられたTextureImportersからスプライトを割り当てます。

DefaultPackerPolicyはデフォルトではタイトなパッキング(SpritePackingModeを参照)を使用しています。カスタムポリシーは,これを上書きし,代わりに矩形パッキングを使用することができます。texture-spaceエフェクトの使用やスプライトをレンダリングするための別のメッシュを使用したい場合に便利です。

  • Repack ボタンはカスタムポリシーが選択された場合のみ有効になります。
    • OnGroupAtlases will not be called unless TextureImporter metadata or the selected PackerPolicy version values change.
    • Use Repack button when working on your custom policy.
  • スプライトは回転したパッキングはできません。
    • SpritePackingRotation is a reserved type for future Unity versions.

その他

  • アトラスは Project\Library\AtlasCache. にキャッシュされてます。
    • Deleting this folder and then launching Unity will force atlases to be repacked. Unity must be closed when doing so.
  • アトラスキャッシュは起動時にロードしません。
    • All textures must be checked when packing for the first time after Unity is restarted. This operation might take some time depending on the total number of textures in the project.
    • Only the required atlases are loaded.
  • デフォルトの最大アトラス サイズは 2048x2048 です。
  • PackingTagが設定されている場合,テクスチャは圧縮されないため,SpritePackerは元のピクセル値を取得後,アトラスで圧縮を行います。

DefaultPackerPolicy

using System;
using System.Linq;
using UnityEngine;
using UnityEditor;
using UnityEditor.Sprites;
using System.Collections.Generic;

// DefaultPackerPolicy will pack rectangles no matter what Sprite mesh type is unless their packing tag contains "[TIGHT]".
class DefaultPackerPolicySample : UnityEditor.Sprites.IPackerPolicy
{
    protected class Entry
    {
        public Sprite            sprite;
        public AtlasSettings     settings;
        public string            atlasName;
        public SpritePackingMode packingMode;
        public int               anisoLevel;
    }

    private const uint kDefaultPaddingPower = 2; // Good for base and two mip levels.

    public virtual int GetVersion() { return 1; }

    protected virtual string TagPrefix { get { return "[TIGHT]"; } }
    protected virtual bool AllowTightWhenTagged { get { return true; } }

    public void OnGroupAtlases(BuildTarget target, PackerJob job, int[] textureImporterInstanceIDs)
    {
        List<Entry> entries = new List<Entry>();

        foreach (int instanceID in textureImporterInstanceIDs)
        {
            TextureImporter ti = EditorUtility.InstanceIDToObject(instanceID) as TextureImporter;

            TextureImportInstructions ins = new TextureImportInstructions();
            ti.ReadTextureImportInstructions(ins, target);

            TextureImporterSettings tis = new TextureImporterSettings();
            ti.ReadTextureSettings(tis);

            Sprite[] sprites = AssetDatabase.LoadAllAssetRepresentationsAtPath(ti.assetPath).Select(x => x as Sprite).Where(x => x != null).ToArray();
            foreach (Sprite sprite in sprites)
            {
                Entry entry = new Entry();
                entry.sprite = sprite;
                entry.settings.format = ins.desiredFormat;
                entry.settings.usageMode = ins.usageMode;
                entry.settings.colorSpace = ins.colorSpace;
                entry.settings.compressionQuality = ins.compressionQuality;
                entry.settings.filterMode = Enum.IsDefined(typeof(FilterMode), ti.filterMode) ? ti.filterMode : FilterMode.Bilinear;
                entry.settings.maxWidth = 2048;
                entry.settings.maxHeight = 2048;
                entry.settings.generateMipMaps = ti.mipmapEnabled;
                if (ti.mipmapEnabled)
                    entry.settings.paddingPower = kDefaultPaddingPower;
                entry.atlasName = ParseAtlasName(ti.spritePackingTag);
                entry.packingMode = GetPackingMode(ti.spritePackingTag, tis.spriteMeshType);
                entry.anisoLevel = ti.anisoLevel;

                entries.Add(entry);
            }

            Resources.UnloadAsset(ti);
        }
        
        // First split sprites into groups based on atlas name
        var atlasGroups =
            from e in entries
            group e by e.atlasName;
        foreach (var atlasGroup in atlasGroups)
        {
            int page = 0;
            // Then split those groups into smaller groups based on texture settings
            var settingsGroups =
                from t in atlasGroup
                group t by t.settings;
            foreach (var settingsGroup in settingsGroups)
            {
                string atlasName = atlasGroup.Key;
                if (settingsGroups.Count() > 1)
                    atlasName += string.Format(" (Group {0})", page);
                
                AtlasSettings settings = settingsGroup.Key;
                settings.anisoLevel = 1;
                // Use the highest aniso level from all entries in this atlas
                if (settings.generateMipMaps)
                    foreach (Entry entry in settingsGroup)
                        if (entry.anisoLevel > settings.anisoLevel)
                            settings.anisoLevel = entry.anisoLevel;

                job.AddAtlas(atlasName, settings);
                foreach (Entry entry in settingsGroup)
                {
                    job.AssignToAtlas(atlasName, entry.sprite, entry.packingMode, SpritePackingRotation.None);
                }
                
                ++page;
            }
        }
    }

    protected bool IsTagPrefixed(string packingTag)
    {
        packingTag = packingTag.Trim();
        if (packingTag.Length < TagPrefix.Length)
            return false;
        return (packingTag.Substring(0, TagPrefix.Length) == TagPrefix);
    }

    private string ParseAtlasName(string packingTag)
    {
        string name = packingTag.Trim();
        if (IsTagPrefixed(name))
            name = name.Substring(TagPrefix.Length).Trim();
        return (name.Length == 0) ? "(unnamed)" : name;
    }

    private SpritePackingMode GetPackingMode(string packingTag, SpriteMeshType meshType)
    {
        if (meshType == SpriteMeshType.Tight)
            if (IsTagPrefixed(packingTag) == AllowTightWhenTagged)
                return SpritePackingMode.Tight;
        return SpritePackingMode.Rectangle;
    }
}


TightPackerPolicy

using System;
using System.Linq;
using UnityEngine;
using UnityEditor;
using UnityEditor.Sprites;
using System.Collections.Generic;

// TightPackerPolicy will tightly pack non-rectangle Sprites unless their packing tag contains "[RECT]".
class TightPackerPolicySample : DefaultPackerPolicySample
{
    protected override string TagPrefix { get { return "[RECT]"; } }
    protected override bool AllowTightWhenTagged { get { return false; } }
}


スプライトエディター
Cluster Rendering