FPSゲームやアドベンチャーゲーム等で主人公がダメージを受けた時に画面全体に血が表示される事があります。
今回はその血の画像をGIMP2.10を使って作成してみたいと思います。
さらに作成した血の画像をUnityで実際に使うサンプルも作成してみます。
この記事を参照して頂くと、以下のようなものが出来上がります。
自作のタイピングゲームで使用する為に作りましたが、一般的なゲームでも使える内容かなと思い記事にしました。
GIMPのダウンロード
GIMPは無料の画像エディターです。
まずはGIMPをダウンロードします。
以下のサイトに移動し、『Downloadバージョン番号』のボタンを押して移動したページでDownloadバージョン番号Directoryを押しダウンロードします(2019/12/19時点でのバージョンは2.10.14)。
ダウンロードが完了したらインストールします。
途中で言語選択がありますが、そのままEnglishが選択されている状態でInstallボタンを押します。
これでGIMPがインストールされました。
言語選択でEnglishを選択しましたが、GIMPを起動すると日本語になっています(なぜかはわかりません・・・)。
血の画像の作成
GIMPを起動したらメニューのファイルから新しい画像の生成を選択します。
新しいウインドウが開くのでテンプレートから画像サイズを選ぶか、自分で画像のサイズを指定します。
わたくしの場合はUnityのゲーム画面の基本サイズを1024×768としているので、血の画像のサイズもゲーム画面サイズと合わせてみました。
メニュー下のエアブラシで描画を選択します。
また塗る色を赤色に変更します。
色は現在選択中の色が表示されている部分を押して、新しく出てきたウインドウで左の色の部分を一番右上までドラッグするか、横の縦のメーター上の一番上を押して選択します。
直接色のHTMLカラーコードを入力してもいいです。
次にデフォルトで右上にあるブラシのタイプからSplats 02を選択します。
左下のブラシの設定で以下のように設定します。
ブラシのサイズを500、硬さと強さを100、流量を100にします。
後はブラシで適当に血を描いていきます。
エアブラシで一回描くだけで一定の範囲内に血が飛び散ったように描くことが出来るので、何回か画像内でマウスの左ボタンを押すだけです。
ここまでで血の画像が出来ましたが、下地が白色で塗られています。
新しい画像を生成した時に設定で下地を透明にしておけばいいんですが、忘れたので血の部分以外を透明にしていきます。
メニューのファイルからレイヤー→透明部分→アルファチャンネルの追加を選択します。
次にメニューのレイヤー→透明部分→色を透明度にを選択します。
新しく出てきたウインドウでColorに背景色である白色が設定されているのを確認したらOKボタンを押します。
これで血の部分以外の背景であった白色部分が透明色になります。
これで血の画像が出来たのでメニューのファイルからExport Asを選択し画像ファイルを出力します。
ゲームなどで2段階の血の表現をさせる為に血の画像を二つ作成しておきます。
とりあえずわたくしはpng形式のbloodtest1とbloodtest2ファイルを作成しました。
Unityで血の画像を表示する
血の画像が出来たのでUnityのAssetsフォルダ内で右クリックからImport New Assetを選択し、二つの画像を選択し取り込むか、Assetsフォルダ内に画像をドラッグ&ドロップして取り込みます。
画像の設定
血の画像はあらかじめUIのRawImageに設定しておきます。
ヒエラルキー上で右クリックからUI→Canvasを選択し、キャンバスを作成します。
Canvasを選択した状態で右クリックからUI→RawImageを選択し、名前をBloodRawImage1とします。
同じようにもう一つRawImageを作成し、名前をBloodRawImage2とします。
BloodRawImage1を選択し、インスペクタでAnchor Presetsからstretch stretchを選び、画面全体に表示されるようにします。
RawImageのTextureにはbloodtest1を設定します。
同じようにBloodRawImage2も設定し、RawImageのTextureにはbloodtest2を設定します。
これで二つの血の画像がゲーム画面全体に表示されました。
スクリプトから血の画像を操作する
この記事の目的である血の画像の作成とそれをUnityに取り込んで使うというところは既に出来ていますが、使用する時のサンプルを作ってみます。
血の画像が二つあるので、主人公が3つのライフを持っているとして1回目のダメージを受けたら最初の画像の表示、2回目のダメージを付けたら次の画像の表示と画面内に表示する画像を増やしたり、
連続するダメージを表現する為に、最初のダメージの時は最初の画像を表示して段々と画像のアルファ値を下げて透明にし、次のダメージの時は次の画像を表示し段々と画像のアルファ値を下げるというような色々な使い方が出来ます。
今回は画像を重ねて表示するサンプルと画像が表示されたら段々と透明になって消えていくサンプルの二つを作ってみます。
画像を重ねて表示するサンプル
まずはダメージの累積を表現する為に画像を重ねて表示するサンプルを作成してみます。
Canvasに新しくBloodScript1スクリプトを作成し取り付けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class BloodScript1 : MonoBehaviour { private RawImage[] bloodRawImages; private int damageCount; // Start is called before the first frame update void Start() { bloodRawImages = GetComponentsInChildren<RawImage>(); foreach (var bloodRawImage in bloodRawImages) { bloodRawImage.color = new Color(bloodRawImage.color.r, bloodRawImage.color.g, bloodRawImage.color.b, 0f); } } // Update is called once per frame void Update() { if(damageCount >= bloodRawImages.Length) { return; } // マウスの左ボタンを押したらダメージ if (Input.GetButtonDown("Fire1")) { TakeDamage(); } } public void TakeDamage() { bloodRawImages[damageCount].color = new Color(bloodRawImages[damageCount].color.r, bloodRawImages[damageCount].color.g, bloodRawImages[damageCount].color.b, 1f); damageCount++; } } |
重ねる画像を配列に保持して利用する為、bloodRawImageListフィールドを作成します。
StartメソッドでGetComponentsInChildrenで子要素のRawImageコンポーネント全てを取得します。
また各RawImageのColorのアルファ値を0にして、透明にしておきます。
Updateメソッドでは表示する画像の数を超えるダメージを受けたらそれ以降の処理を実行しないようにしています。
マウスの左ボタン(InputManagerでFire1の初期設定を変更していない場合)を押したらTakeDamageメソッドを呼びます。
TakeDamageメソッドではアルファ値を1にして現在のダメージ画像を見えるようにします。
damageCountを1つ増やします。
これで累積ダメージを表現する事が出来ます。
このサンプルではマウスの左ボタンを押した時にTakeDamageメソッドを呼んで血の画像を表示させていますが、敵のアニメーションの攻撃と合わせて血を表示したい場合はアニメーションイベントを使用するとアニメーションのタイミングに合わせてTakeDamageメソッドを呼ぶようにするといいかもしれません。
こちらを試したのが記事の最初の動画になります。
段々と透明になって消えていくサンプル
次はダメージを受けた時に血の画像を表示して段々と透明になっていくサンプルを作成してみます。
CanvasのBloodScript1スクリプトを無効にし、新しくBloodScript2スクリプトを作成し取り付けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class BloodScript2 : MonoBehaviour { private RawImage[] bloodRawImages; // ダメージを受けたかどうか private bool takeDamage; // 血を消す速さ private float deleteSpeed = 2f; // Start is called before the first frame update void Start() { bloodRawImages = GetComponentsInChildren<RawImage>(); foreach (var bloodRawImage in bloodRawImages) { bloodRawImage.color = new Color(bloodRawImage.color.r, bloodRawImage.color.g, bloodRawImage.color.b, 0f); } } // Update is called once per frame void Update() { if(takeDamage) { foreach (var bloodRawImage in bloodRawImages) { bloodRawImage.color = Color.Lerp(bloodRawImage.color, new Color(bloodRawImage.color.r, bloodRawImage.color.g, bloodRawImage.color.b, 0f), deleteSpeed * Time.deltaTime); } } // マウスの左ボタンを押したらダメージ if (Input.GetButtonDown("Fire1")) { if (takeDamage) { takeDamage = false; } StartCoroutine(TakeDamage()); } } public IEnumerator TakeDamage() { // ひとつの血の画像毎に遅延して消していく場合 takeDamage = true; foreach (var bloodRawImage in bloodRawImages) { bloodRawImage.color = new Color(bloodRawImage.color.r, bloodRawImage.color.g, bloodRawImage.color.b, 1f); yield return new WaitForSeconds(0.5f); } // 全部の血をまとめて消す場合 //takeDamage = true; } } |
takeDamageはダメージを受けたかどうかで、deleteSpeedは血が消えていくスピードです。
Startメソッドは最初のサンプルと同じです。
UpdateメソッドではtakeDamageがtrue、つまりダメージを受けている時に全てのbloodRawImagesのアルファ値をColor.Lerpを使って徐々に透明にしていきます。
マウスの左ボタンを押した時にtakeDamageがtrueだったらfalseにしています、これは連続でマウスの左ボタンが押された時に一旦ダメージを無効化する為です。
コルーチンを使ってTakeDamageメソッドを呼び出します。
TakeDamageメソッドではtakeDamageをtrueにし、bloodRawImageListの全てのRawImageのColorのアルファ値を1にして画像表示しますが、画像と画像の間に0.5秒間の待ち時間を入れています。
takeDamageをtrueにするタイミングはforeachの前と後のどちらに記述するかで処理が変わりますが、最初に記述した場合は画像が表示されたら他の画像にかかわらず透明になっていきます(個々の画像で透明になるタイミングが変わる)。
foreachの後に記述すると全部の血の画像が表示されてから画像が透明になっていきます。
このサンプルではコルーチンを使って一回のダメージで全ての血の画像を表示していますが、アニメーションイベントを使ってBloodScript1のように血の画像を順番に表示させるようにするといいかもしれません。
こちらのサンプルを実行すると以下のようになります。
終わりに
血の画像を作らなきゃなぁと思っていたんですが、GIMPを使ったらなんともまぁ簡単に作れますね!
芸術性がまったくないわたくしにとって非常にありがたいです。(´Д`)