- 2020/06/30 【Unity】【C#】Windows で mp3 をランタイムで再生する
- 2020/05/31 【Unity】【C#】TGAをランタイムでロードする
- 2020/05/08 【Unity】UniRx 7.x にアップグレードすると UniTask 系のエラーが出る
- 2020/04/27 【Unity】【エディタ拡張】インスペクタの UnityEvent を並べ替え可能にする
- 2020/04/10 【Unity】【エディタ拡張】インスペクタの配列やリストを並べ替え可能にする
« prev next »
【Unity】【C#】Windows で mp3 をランタイムで再生する 
2020/06/30 Tue [edit]
なぜか Windows ではランタイムでの mp3 再生(ストリーミング)に対応してない。Unity のバージョン上がったらいつか対応するのかと思ってたけど、いっこうに対応しない(エラーとなる)。Android や Mac, iOS などは普通に再生できるのにね。
VRM Live Viewer でも、音楽素材は wav/ogg でしか使えず、少し不便だな~といつも感じていた。
なのでちょっと調べてみたが、実装が面倒なのが多い。色々見てみたが結局、NAudio というプラグインライブラリで「mp3 → wav に変換して再生する」のが一番簡単なようだ。
あまり日本語での記事が見つからなかったので、せっかくなので実装例を載せておこう。VRM Live Viewer ではこれが実装されている(※実際には変換作業を非同期化[UniTask]にしている)。ここではわかりやすいように、中核となる部分を簡略化したコードを掲載しておこう。
・NAudio
・Microsoft Public License (Ms-PL)
(※) Unity 2019.2.21f1 / Windows10(x64) で確認
■NAudio (dll) の導入
まずはプラグイン本体の dll をダウンロードしよう。Release ページに移動すると、掲載時点では v1.10.0 が出ていたが、「▼Assets (2)」を開くとソースコードしか無かったので、自分でコンパイルしないのなら、そのすぐ下バージョンの v1.8.4 の「▼Assets (4)」を開いて、「NAudio-Release.zip」をダウンロードしよう(※要するに zip で落とせる最新版をダウンロードする)。
・(NAudio) Release ページ
zip を解凍したら、「NAudio.dll」と「NAudio.xml」とドキュメント(txt)が入っているので、「Plugins」フォルダを作って(Windows だけで良いのなら「Plugins/x86」を作る)プロジェクトにドラッグドロップしてインポートしよう(dll と xml だけでも良い)。ちなみに「Plugins」は全てのプラットフォーム or Fallback で、以下に「Android」「iOS」「x86_64」を作れば、それぞれのプラットフォームごとになると考えて良い。ここでは Windows でだけしか使わないので、以下のように配置している。

・Unityの特殊フォルダと各々の役割(追記版)
あとは dll をクリックして、Import Settings を設定しておこう。「x86_64」にチェックを入れておけば 64bit でも使えるようになる。CPU の種類もとりあえず全てにしておこう。

●CPU

■mp3 → wav に変換して再生する
NAudio のプラグインを導入できたら、次にサンプルコードを作成しよう。
先に簡単にコードの内容を解説しておくと、インスペクタで設定した mp3 のファイルパスを NAudio で一時フォルダに wav として書き出し、ストリーミング再生するサンプルになっている。
ちにみに、音声ファイルをストリーミング再生する方法は以前に紹介した方法と基本的には同じだ。
・動的にオーディオファイルの読み込みと再生をする
●mp3 → wav に変換して再生するサンプルコード
using System.Collections;
using System.IO;
using UnityEngine;
using NAudio.Wave; //← 見つからないとエラーが出たときは Import Settings を見直す
public class Mp3Play : MonoBehaviour //クラス名は任意
{
public AudioSource audioSource; //再生用 AudioSource をアタッチしておく
public string mp3Path; //再生する mp3 のパス
// Use this for initialization
private void Start()
{
if (File.Exists(mp3Path))
{
//wav 変換した一時ファイルを保存するパス
var wavPath = Application.temporaryCachePath + "/converted.wav";
ConvertMp3ToWav(mp3Path, wavPath);
StartCoroutine(PlayWav(wavPath));
}
else
{
Debug.Log($"File not found : {mp3Path}");
}
}
//mp3 → wav 変換して、保存したパスを返す
public void ConvertMp3ToWav(string mp3Path, string wavPath)
{
//ファイルを byte 配列で読み込み
var bytes = File.ReadAllBytes(mp3Path);
//wav を一時ファイルとして保存
using (var stream = new MemoryStream())
{
stream.Write(bytes, 0, bytes.Length);
stream.Position = 0;
using (var reader = new Mp3FileReader(stream))
{
WaveFileWriter.CreateWaveFile(wavPath, reader); //wav で書き出し
Debug.Log($"Convert to wav successfully : {wavPath}");
}
}
}
//ストリーミング再生する
IEnumerator PlayWav(string path)
{
using (var www = new WWW("file://" + path))
{
while (!www.isDone)
yield return null;
if (string.IsNullOrEmpty(www.error))
{
var clip = www.GetAudioClip(false, true);
audioSource.clip = clip;
audioSource.Play();
Debug.Log($"Play wav : {path}");
}
else
{
Debug.Log(www.error);
}
}
}
}
再生するには GameOjbect にこのスクリプトと AudioSource をアタッチし、その AudioSource をインスペクタでセットしておく必要がある。
プレイして、設定したパス(mp3)の音声が鳴ったなら成功だ。

エラーチェックは最低限しかしてないので、必要なら try-catch などを追加しておいた方が良いだろう。
また wav ファイルはサイズが大きいので、アプリ終了時(OnApplicationQuit)などで一時ファイルを削除しておいた方が良いかも知れない。その辺りは好きにやって欲しい。
ちなみに、上記の例で Mp3FileReader にパスを与えるオーバーロードもあるので、ConvertMp3ToWav() の中身を以下のように書くこともできる。
●Mp3FileReader(パス) のオーバーロードを使う
//mp3 → wav 変換して、保存したパスを返す
public void ConvertMp3ToWav(string mp3Path, string wavPath)
{
using (var reader = new Mp3FileReader(mp3Path))
{
WaveFileWriter.CreateWaveFile(wavPath, reader); //wav で書き出し
Debug.Log($"Convert to wav successfully : {wavPath}");
}
}
ただコードは短くて良いのだが、私が実行速度を計測してみた所、前述のコードからすると約 100~200ms ほど遅いようだ(※2~3分の曲の場合)。また Mp3FileReader → AudioFileReader に置き換えてみたら、更に 300~400ms 遅い。
なので、実行速度を気にしない場合であれば、こちらを使っても良いだろう。
また、再生には WaveOut を使う方法があるが(本来は WaveOut が正しい使い方だと思うが、Unity では AudioClip として扱いたかったため、変換だけ利用している)、興味があったら、以下の資料を覗いてみると良い。
(参考)
・C# プログラミング解説 NAudio
(関連記事)
【Unity】【C#】動的にオーディオファイルの読み込みと再生をする
【Unity】【C#】オーディオ再生でのエラー:An invalid seek position was passed to this function の対処法
【Unity】【C#】BMP をランタイムで読み込む
【Unity】【C#】TGAをランタイムでロードする
【Unity】【C#】ランタイム時にファイルをドラッグ&ドロップして取得する(Windows のみ)
- 関連記事
-
-
【Unity】GearVR アプリをビルドする
-
【Unity】アイコン画像のフォーマット警告:Compressed texture XXX is used as icon. This might compromise visual quality of~ を消す
-
【Unity】【C#】Addressable Assets でキー(アドレス)の存在(登録)を調べる
-
【Unity】activeInHierarchy, activeSelf, isActiveAndEnabled の結果の違い
-
【Unity】Unity2020 でプラットフォーム切り替えをすると、Run In Background が勝手にオフになってしまう
-
category: Unity
thread: ゲーム開発
janre: コンピュータ
tag: Unityオープンソースライブラリ Unityプラグイン オーディオファイル【Unity】【C#】TGAをランタイムでロードする 
2020/05/31 Sun [edit]
BMPLoader に続き、これも試験的(Experimental)に VRM Live Viewer に導入しているのだが、オリジナルソースに少し手を加えた方が使い易いと思うので、ほんのちょっと改造版を載せておこう。
今回紹介する方法は、オープンソースの TGALoader を使う方法だ。ただ、少し注意点は、「フルカラー・無圧縮」のみ対応という点だ。
それを踏まえた改造版になる。簡単に説明すれば、「ヘッダ部分から画像データ形式を拾って、フルカラーでなければエラーを出す」というものを付け加えたものだ。あと、github にあったコメントなどの修正もついでに入れてある。
・TGALoader.cs (mikezila)
・TGA Loader for Unity3D (aaro4130)
(※) Unity 2019.2.21f1 / Windows10(x64) で確認
●TGALoader.cs(フルカラー・無圧縮のみ) [github のほんのちょっと改造版]
// https://gist.github.com/mikezila/10557162
// This was made by aaro4130 on the Unity forums. Thanks boss!
// https://forum.unity.com/threads/tga-loader-for-unity3d.172291/
// It's been optimized and slimmed down for the purpose of loading Quake 3 TGA textures from memory streams.
using System;
using System.IO;
using UnityEngine;
public static class TGALoader
{
public static Texture2D LoadTGA(string fileName)
{
using (var imageFile = File.OpenRead(fileName))
{
return LoadTGA(imageFile);
}
}
public static Texture2D LoadTGA(Stream TGAStream)
{
using (BinaryReader r = new BinaryReader(TGAStream))
{
r.BaseStream.Seek(2, SeekOrigin.Begin);
int type = r.ReadByte(); //(offset 2) 画像形式 (1バイト)
//フルカラー以外は非対応とする(=RLE圧縮は展開コードが必要のため)
if (type != 2)
{
throw new Exception("Only Full-color Uncompressed is supported.");
}
// Skip some header info we don't care about.
// Even if we did care, we have to move the stream seek point to the beginning,
// as the previous method in the workflow left it at the end.
r.BaseStream.Seek(9, SeekOrigin.Current); //offset 3 から +9 → 12
short width = r.ReadInt16(); //(offset 12) 画像の横幅 (2バイト)
short height = r.ReadInt16(); //(offset 14) 画像の縦幅 (2バイト)
int bitDepth = r.ReadByte(); //(offset 16) 色深度 (1バイト)
// Skip a byte of header information we don't care about.
r.BaseStream.Seek(1, SeekOrigin.Current);
Texture2D tex = new Texture2D(width, height);
Color32[] pulledColors = new Color32[width * height];
if (bitDepth == 32) //アルファあり
{
for (int i = 0; i < width * height; i++)
{
byte red = r.ReadByte();
byte green = r.ReadByte();
byte blue = r.ReadByte();
byte alpha = r.ReadByte();
pulledColors [i] = new Color32(blue, green, red, alpha);
}
} else if (bitDepth == 24) //アルファなし
{
for (int i = 0; i < width * height; i++)
{
byte red = r.ReadByte();
byte green = r.ReadByte();
byte blue = r.ReadByte();
/* (github のコメントから)
https://gist.github.com/mikezila/10557162#gistcomment-2995969
pulledColors [i] = new Color32(blue, green, red, 1); //float で 1.0 と間違えた?
1 need to be replaced by 255, in another case, texture become transparent
*/
pulledColors [i] = new Color32(blue, green, red, 255);
}
} else
{
throw new Exception("TGA texture had non 32/24 bit depth.");
}
tex.SetPixels32(pulledColors);
tex.Apply();
return tex;
}
}
}
ファイルフォーマットに関しては以下を参考にさせて貰った。 このコードではRLE圧縮には対応してない。RLE圧縮に関しては以下の記事にも載っているので、参考にするのも良いだろう。
(参考)
・TGA ファイルフォーマット (GAME PROGRAMMING UNIT)
・TGA ファイルフォーマット (PROJECT ASURA)
今回利用するヘッダ部分と画像のデータ形式だけ抜粋させて頂くと以下のような表になる。
ヘッダー (18 byte)
offset | byte | 内容 |
---|---|---|
0 | 1 | ヘッダーの後に続く、IDの長さ (ID field length) |
1 | 1 | カラーマップの有無 (Color map type) |
2 | 1 | データ形式 (Image type) |
3 | 2 | カラーマップの位置 (Color map index) |
5 | 2 | カラーマップの長さ (Color map length) |
7 | 1 | カラーマップエントリーのビット数 (Color map size) |
8 | 2 | X (Image origin X) |
10 | 2 | Y (Image origin Y) |
12 | 2 | 幅 (Image width) |
14 | 2 | 高さ (Image height) |
16 | 1 | ピクセルのビット数 (Bit per pixel) |
17 | 1 | 属性 (Discripter) |
(offset 2) データ形式 (1 byte)
値(整数) | 内容 |
---|---|
0 | イメージなし |
1 | インデックスカラー(256色) |
2 | フルカラー |
3 | 白黒 |
9 | インデックスカラー。RLE圧縮 |
10 | フルカラー。RLE圧縮 |
11 | 白黒。RLE圧縮 |
まぁ、ここでは「フルカラー・無圧縮」に限定してしまっているが、データ形式にあるように「フルカラー/インデックスカラー/白黒」と「圧縮/無圧縮」と「格納方向:縦/横」(offset 17 の属性)を組み合わせるとコードが長くなるのは容易に想像できるだろう。以下に複数の形式で TGA → BMP に変換するサンプルコードはあったので、興味があったら覗いてみるのも良いかも知れない(そしてRLE展開も作ったら公開して欲しい(笑))。
・TGALoader.cs (openmetaversefoundation/libopenmetaverse)
簡単なテストをするには以下ようなのコードで十分だろう。UI に RawImage を適当に置いて、インスペクタにセットし、読み込む画像のパスを設定してプレイすれば良い。画像が表示できたら成功だ。
●簡単な確認コード
using System;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
public class TGALoaderTest : MonoBehaviour
{
public RawImage image; //画像表示用
public string path; //画像パス
// Use this for initialization
private void Start()
{
LoadTGA(path);
}
void LoadTGA(string path)
{
try
{
var tex = TGALoader.LoadTGA(path);
image.texture = tex;
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
}
ちなみにフルカラーのチェックをしないでRLE圧縮形式のTGAを読み込んだ場合は「Unable to read beyond the end of the stream.」というエラーが出る(たぶん圧縮してある場合は、データ長が短くなるので足りなくなり、エラーとなる)。このサンプルコードの場合はフルカラー以外では「Only Full-color Uncompressed is supported.」と出る。必要なら何か処理を入れた方が良いだろう。
また、私が提供しているプラグインを使えば、Android でも TGA を読み込めた。実際にスマホで全天球ビューワを作ることも可能だ(これが VRM Live Viewer で実装されている)。フリーなので、自由に使って欲しい。
(関連記事)
【Unity】【C#】BMP をランタイムで読み込む
【Unity】【C#】ランタイム時にファイルをドラッグ&ドロップして取得する(Windows のみ)
【Unity】スマホで簡易360度(パノラマ, 全天球)ビューワを作る
【Unity】Androidのトーストやダイアログ、通知、音声認識、ハード音量操作など基本的な機能を使えるプラグインを作ってみた
【Unity】AssetStore版 FantomPlugin のセットアップ
【Unity】UniRx 7.x にアップグレードすると UniTask 系のエラーが出る 
2020/05/08 Fri [edit]
どうやら Unity2019.2.x (2.21f1) が2月頃からアップデートが止まっている…これもコロナウィルスのせいなのか…(会社はロスみたいだし)?
だけど、Unity2019.3.x はずっとアップデートされ続けている…。
しかたないので、そろそろ覚悟を決めて (Android では内部実装が変わるので、ネイティブプラグインが死ぬ可能性がある) Unity2019.3.x にアップグレードしなくてはいけないかな?と思ってやってみたら、大量のエラーが出た。
・【Unity】Unity2019.3 で Android / iOS ネイティブの構成が変わるらしい
(※) Unity 2019.3.13f1 / Windows10(x64) / UniRx 7.1.0 / UniTask 1.3.1 で確認
1つは、どうやらカメラに Unity5 時代にデフォルトで付いていた「GUI Layer」が完全に廃止されたっぽい。もしかしたら旧 GUI も完全に使えなくなったのかな…?
It will be removed after you edit this GameObject and save the Scene.
→ これは一度シーンを保存すれば、自動的に消されるらしい
もう1つは UniRx のエラーだった。その1つは「using UnityEngine.Experimental.LowLevel;」の namespace で、どうやら Unity2019.3 では「using UnityEngine.LowLevel;」になったっぽい。
※この修正は後述の UniRx 7.x にアップグレードする場合は書き換える必要はありません。
error CS0246: The type or namespace name 'PlayerLoopSystem' could not be found (are you missing a using directive or an assembly reference?)
そういえば、UniRx (6.x) は長らくアップデートしてないなぁと思ったので、AssetStore から再ダウンロード&インポート(UniRx 7.1.0)。そしたら今度は UniTask 関連のエラーが大量に出た。
・UniRx - Reactive Extensions for Unity (AssetStore)
error CS0246: The type or namespace name 'UniTask' could not be found (are you missing a using directive or an assembly reference?)
「UniRx.Async の namespace が無い」みたいなエラーだったので、しばらく原因がわからなかったのだが(6.x では普通に使えたので)、github で何か issue でも立ってないかと見ていたら、もっと単純に「UniRx.Async is separated to https://github.com/Cysharp/UniTask」([Ver 7.0.0 で] UniRx.Async のパッケージが分離しました) というコメントを見つけた。ああ、これか、と(笑)。
なので、UniRx.Async のパッケージをDLしようかと思ったら、Ver 2.x.x-preview (プレビュー版)となっている。しかし「This version is preview, if you want to use stable version, check 1.3.1.」(安定版が使いたいなら、1.3.1 を見てね)ともあるので、今回はそちらを使うことにした。
・UniRx (github)
・UniTask (github)
インポートしてみると、UniRx.Async は以前のように「Plugins」フォルダ以下ではなくなったみたい。もしかしたら「Plugins」フォルダ以下に移動した方が良いのかもだが(ビルド順が変わるとか何とか)、まぁ、私は動けば良いので、とりあえずこれでよし(笑)。
・特殊フォルダーとスクリプトのコンパイル順 (Unity Manual)


後で試しに「Assets/Plugins/UniRx」以下に「UniRx.Async」を移動してみたが、これも問題ないようだ。まぁ、コンパイル順でエラーが出たことはないが、アップグレードするときにまとめておいた方が便利なので、Plugins 以下に移動しても良いかもね。
(関連記事)
【Unity】【C#】UniRx で「1フレームごと待機して処理」してみる
【Unity】【エディタ拡張】インスペクタの UnityEvent を並べ替え可能にする 
2020/04/27 Mon [edit]
前回「インスペクタの配列やリストを並べ替え」を紹介したが、UnityEvent も並べ替えたいときもよくあるだろう。これもとても導入・利用が簡単なものがあるので、ついでに紹介しておこう。
・EasyEventEditor (MIT License)
また、あまりオープンソースに馴染みの無い人のためにも、導入方法も詳しく書いておく。慣れている人なら自分の方法でも構わない。といっても導入しただけで使えるスグレモノなので、簡単な使い方だけ見ておけば、すぐに使えると思う。
(※) Unity 2019.2.21f1 / Windows10(x64) で確認
■ライブラリのインポート
まずは github でライブラリをダウンロードしよう。「Clone or download」から zip をダウンロードしても良いが、Releases ページにある .unitypackage を使う方が簡単なので、ここではそのやり方で導入してみよう。
・Releases ページ(.unitypackage がダウンロードできる)
.unitypackage をダウンロードしたら、プロジェクトビューにドラッグドロップしよう。ファイルは1つしかないので(※掲載時点:v1.0.1)、そのままインポートすれば良い。これだけで導入は完了だ。


尚、zip の方には asmdef(Assembly Definition Files)やパッケージマネージャーでの導入するための package.json などが入っている。こちらの方法はまた別の方法となるので(あと、Unity のバージョンによるので)、興味があったら参考資料だけ載せておこう。
・【Unity】Assembly Definition Filesという神機能
・プロジェクト管理は進化しています – Unity Package Manager の概要
・UnityのPackage Managerを使って機能をインストールする
■インスペクタで並べ替えてみるためのサンプルコード
ここからは簡単なコードを書いて試してみよう。内容はかなり適当なので、好きなように書き換えて欲しい。
もしあまり UnityEvent を使ったことないから、色々なイベントコールバックをするサンプルコードが以下の記事にまとめてあるので、参照して欲しい。
・【Unity】【C#】UnityEvent, Action, delegate, interface でのコールバック実装方法とインスペクタでの登録
●インスペクタで並べ替えてみるためのサンプルコード(※.NET 4.x)
using UnityEngine;
using UnityEngine.Events;
public class EasyEventEditorTest : MonoBehaviour
{
//これがインスペクタに表示される
public UnityEvent OnCallback;
//UnityEvent のコールバック用1
public void Hoge()
{
Debug.Log("Hoge");
}
//UnityEvent のコールバック用2
public void Fuga()
{
Debug.Log("Fuga");
}
//UnityEvent のコールバック用3
public void Piyo()
{
Debug.Log("Piyo");
}
//UI-Button などの OnClick などに登録する等
public void Click()
{
OnCallback?.Invoke(); //コールバック発火
}
}
このスクリプトをヒエラルキーで何らかの GameObject にアタッチしよう。
後はインスペクタで実際に確認して欲しい(表示が更新されてなかったら、一旦フォーカスを外して、再度スクリプトをアタッチした GameObject を見てみると反映されてたりする ← Unity はコンパイルが走ると表示がデフォに戻ることがある)。

●ドラッグで移動できる

●移動後

Click() を UI の Button に登録して試してみればわかるが(面倒なら Start() から呼んでも良い)、コールバックの発火はインスペクタで登録した上→下の順になる。試してみよう。
●並べ替え前
Fuga
Piyo
●並べ替え後(※並び替えた順)
Hoge
Fuga
また、機能をオフにしたり、表示方法を変更したりする設定は「Edit>Preference」で「Easy Event Editor」タブ(Unity2019以降)にある。自分の見やすい設定にしておくと良いだろう。

(関連記事)
【Unity】【C#】インスペクタの配列やリストを並べ替え可能にする
【Unity】【C#】インスペクタで入力不可(Disable)な属性を作る
【Unity】【C#】インスペクタの値を保持したまま変数をリネームする
【Unity】【C#】インスペクタの表示項目を動的に変更する
【Unity】【C#】インスペクタでの UnityEvent のコールバック登録の有無を調べる
【Unity】【C#】UnityEvent, Action, delegate, interface でのコールバック実装方法とインスペクタでの登録
- 関連記事
-
-
【Unity】【エディタ拡張】インスペクタの UnityEvent を並べ替え可能にする
-
【Unity】【C#】EventSystem を InputSystem 用に置き換えると、スクロールビュー等の移動が速過ぎる
-
【Unity】【C#】非アクティブも含めて、Transform (GameObject) をパス名で取得する
-
【Unity】【C#】スワイプ(フリック)を判定、方向を取得してコールバックする
-
【Unity】【C#】SmoothFollow を C# で書いてみる
-
category: Unity
thread: ゲーム開発
janre: コンピュータ
tag: Unityオープンソースライブラリ Unityプラグイン インスペクタ エディタ拡張【Unity】【エディタ拡張】インスペクタの配列やリストを並べ替え可能にする 
2020/04/10 Fri [edit]
この手のエディタ拡張はググればいくつか出てくるが、今回は特に導入・利用が簡単な「Reorderable Inspector」というオープンソースライブラリを紹介しよう。また、コード上で属性を付けるだけで、既に作ってあるものに後から機能追加できることも、このライブラリの魅力だ。
・Reorderable Inspector(MIT License)
※Unity2020LTS では標準で利用できるようになりました(導入不要)
あまりオープンソースに馴染みの無い人のためにも、導入方法も詳しく書いておく。慣れている人なら自分の方法でも構わない。それではやってみよう。
(※) Unity 2019.2.21f1 / Windows10(x64) で確認
■ライブラリのインポート
まずは github でライブラリをダウンロードしよう。「Clone or download」から zip をダウンロードできるので、落としたら zip を解凍する。
・Reorderable Inspector (MIT License)
解凍したらいくつかファイルが出てくるので、プロジェクトビューで「Scripts」(名前は任意)フォルダを用意し、「ReorderableAttribute.cs」「EditScriptableAttribute.cs」をプロジェクトビューにドラッグ&ドロップしてインポートする。
また「Editor」以下のファイルも必要なので、フォルダごとインポートするか、自分で「Editor」(場所はどこでも構わないが、名前は "Editor" 固定)フォルダを作り、「ReorderableArrayInspector.cs」「SerializedPropExtension.cs」をインポートする。これだけで導入は完了だ。

■インスペクタで並べ替え可能な配列やリストを表示する
ここからは簡単な使用例となる。配列やリストの変数名などは自分の任意で構わない。既に何らかのプロジェクトがあるのなら、それを使っても良い。
●ReorderableInspector の使用例
using System.Collections.Generic;
using UnityEngine;
using SubjectNerd.Utilities;
public class ReorderableInspectorTest : MonoBehaviour
{
//配列の例(public フィールド例)
[Reorderable]
public string[] strArray = { "Apple", "Banana", "Candy" };
//リストの例(private フィールド例)
[SerializeField, Reorderable]
List<string> strList = new List<string>() { "xxx", "yyy", "zzz" };
}
要素の内容は適当だが、このスクリプトをヒエラルキーで何らかの GameObject にアタッチしよう。
コードの要点としては「using SubjectNerd.Utilities;」を入れることと、フィールドに "[Reorderable]" を追加するということだ。逆に元に戻したければ "[Reorderable]" をコメントアウトするか、削除すれば良い。
後はインスペクタで実際に確認して欲しい(表示が更新されてなかったら、一旦フォーカスを外して、再度スクリプトをアタッチした GameObject を見てみると反映されてたりする ← Unity はコンパイルが走ると表示がデフォに戻ることがある)。

●各項目をドラッグして並べ替えられるようになる

もし、並び替え機能を自作したいなら、以下の資料を参考にすると良いだろう。ただ、自作となると Reflection の知識が必要となるので、結構大変だと思う(実は私も独自に作ってたのがあるが、結局このライブラリの方が楽なので、最近はこっちしか使ってない(笑))。興味があったら調べてみるのも良いだろう。
・エディタ拡張で配列の入れ替えが簡単に出来るReorderableListの使い方と全コールバック【Unity】【エディタ拡張】
・.NET のリフレクション
・System.Reflection
(関連記事)
【Unity】【C#】インスペクタの UnityEvent を並べ替え可能にする
【Unity】【C#】インスペクタで入力不可(Disable)な属性を作る
【Unity】【C#】インスペクタの値を保持したまま変数をリネームする
【Unity】【C#】インスペクタの表示項目を動的に変更する
【Unity】【C#】インスペクタでの UnityEvent のコールバック登録の有無を調べる
【Unity】【C#】UnityEvent, Action, delegate, interface でのコールバック実装方法とインスペクタでの登録