最初に成果物を提出。こんな感じになりました。それっぽく見えるとうれしいですが、ROM を解析して厳密にやったわけではないです。
データの詳細は、記事の最後に今回のサンプルデータを公開しているので、そちらをご確認ください。
実装したことの流れ
下記は、私が FF5 の敵を倒す演出を見て思って実装した内容。“らしい”かもしれませんが、実際どうなのかは知らないです。
- 敵を倒す。(エフェクト開始の基点のこと。ボタンの押下)
- 敵の色味を半透明の紫色に変更。
- 指定秒数で、敵の透明度を更に下げる。
- 指定秒数で、敵のピクセルが少しずつ霧のようにとけて消える演出 1 をする。
- 同時に指定秒秒数で、透明度を更にさげて 0x00 にする。
- エフェクトが完了したイベントを通知しておく。
こんな感じがよいのではないかと思いました。
紫色にするポイント
画像処理をする際は、ピクセルデータの配列にアクセスする必要があります。
var color = TargetTexture2D.GetPixels32(); var width = TargetTexture.width; var height = TargetTexture.height;
GetPixels
メソッドを実行する際は、Assets のインポートデータの設定で「Read/Write Enabled」が有効になっている必要があります。(png ファイルなので Format もついでに指定してあげました)
ただし、この設定は注意が必要でインポートデータの使用するメモリー量が2倍になるみたいです。詳細は公式の「テクスチャ - Advanced settings」を参照すると以下のコメントがあります。なので、このサンプルのように比較的小さなサイズの画像を対象にしたほうが推奨のエフェクトといえるかもしれないです。
このボックスをチェックすると、スクリプト関数 (Texture2D.SetPixels、Texture2D.GetPixels、その他の Texture2D 関数など) からテクスチャデータにアクセスが可能になります。ただし、テクスチャデータのコピーが作成され、テクスチャアセットに必要なメモリ量が 2 倍になるため、絶対に必要な場合にのみこのプロパティーを使用してください。この機能は非圧縮テクスチャと DXT 圧縮テクスチャに対してのみ有効です。他のタイプの圧縮テクスチャを読み込むことはできません。このボックスは、デフォルトでは無効になっています。
for (int y = 0; y < _ImageHeight; y++) { for (int x = 0; x < _ImageWidth; x++) { var c = _Pixels[(_ImageWidth * y) + x]; // ピクセルが透明のとき if (c.a == 0x00) continue; // 明度 var v = GetBrightness(c); var vp = v / 255.0F; // 明度の割合 if (v > LineBrightness) // 線と区別するライン { // 紫色を基準に明度の割合を当てる c.r = (byte)(0xEE * vp); c.g = (byte)(0x66 * vp); c.b = (byte)(0xFF * vp); } // すこし薄くする c.a = DefeatedWhiteStart; _Pixels[(_ImageWidth * y) + x] = c; } } private byte GetBrightness(Color32 color) { if (color.r >= color.g && color.r >= color.b) return color.r; if (color.g >= color.r && color.g >= color.b) return color.g; return color.b; }
GetBrightness は System.Drawing - GetBrightness メソッドのコードを参考にしてもよかったかも。
ともかく、黒色の部分以外は紫色 #EE6FF
を基準にして、ピクセルの明度にあわせて色味を落とす設定にしてみたのが、一番しっくりしました。
FF5 は紫色に変えるときに白い部分が目立たなくなるなどの特徴があると思ったので、周囲の色をいくらか評価している気もしました。
敵を霧のように消す演出
この部分は、FF5 のやりかたと異なります。私は、斜線で消しました。
FF5 は、最初になんらかのパターンのあるランダム(っぽい)空白の穴がいくつも出現します。その穴が、次第に上方向と若干左右に広がって消えていきます。
特徴として、最後は二等辺三角形のような山型が残ります。大きな部位も小さな部位も最後まで残って(大きな部位ほどよく消える)、最後の瞬間までなんとなく形状が残っている気がします。(気のせいかも)
「God is in the details」というやつで、パッっと消すだけよりは、なんか“らしい”演出があったほうが幸せですね。
この演出にはコルーチンを利用してみました。こうした演出には向いている気がしました。
その他のポイント
Color は特にコメントがなかったけど、Mesh.colors だと次のように「パフォーマンス上の理由から、colors32 の使用を検討してください」とコメントされています。
For performance reasons, consider using colors32 instead. This will avoid byte-to-float conversions in colors, and use less temporary memory.
特に理由がなければ、Color32 を使ったほうがよいかもしれません。
サンプル
今回のサンプルは GitHub に公開しています。
エフェクトがデフォルトの今、画像処理でエフェクトをかけるのも微妙な気もしたけど、2D だしね。細部ではまだやれることもあるんじゃないかと。
参考
Clean Architecture 達人に学ぶソフトウェアの構造と設計
- 作者:Robert C.Martin
- 発売日: 2018/07/27
- メディア: 単行本
Unityの教科書 Unity2019完全対応版 2D&3Dスマートフォンゲーム入門講座 (Entertainment&IDEA)
- 作者:北村 愛実
- 発売日: 2019/06/28
- メディア: 単行本
FINAL FANTASY V Original Sound Track Remaster Version
- アーティスト:ゲーム・ミュージック
- 発売日: 2013/08/07
- メディア: CD