ユニティちゃんのRPGを作ってみよう27ー戦闘中のダメージや回復ポイントのアニメーションを作るー | Unityを使った3Dゲームの作り方(かめくめ)

ユニティちゃんのRPGを作ってみよう27ー戦闘中のダメージや回復ポイントのアニメーションを作るー

今回は戦闘中のダメージや回復ポイントをキャラクターの近くにTextMeshProを使って表示し、テキストがアニメーションをするようにします。

前回は戦闘中に選択されたキャラクターの上にアイコンを表示する機能を作成しました。

ユニティちゃんRPGの戦闘中に攻撃やアイテム等を使用する対象者を選ぶ時にそのキャラクターの上にアイコンを表示する機能を作成します。

ユニティちゃんのRPGを作ってみようの他の記事は

から見ることが出来ます。

戦闘中に攻撃や回復アイテム等を使った時に相手のCharacterBattleScriptのHPを操作する機能は作りました。

今回はその攻撃をした時に与えたダメージや回復魔法やアイテムを使って回復したHPの量を見てすぐわかるようにキャラクターの近くに表示します。

テキストは今まで使っていたTextではなくTextMeshProを使って表示し、テキストにアニメーションをさせるようにします。

スポンサーリンク

TextMeshProを使う

今回の記事では今まで使っていたTextではなくTextMeshProを使用したいと思います。

TextMeshProはテキストをメッシュとして取り扱う事が出来、今まで使ってきたTextと違いカメラが接写しても文字がにじみにくいです。

ユニティちゃんRPGで使うTextMeshProと今までのTextの違い

その他TextMeshProでは設定を変更する事で簡単に綺麗なタイトルロゴの作成等が出来ます。

今までのTextだとCanvasの子要素に配置してCanvas上の位置を設定するかCanvasのRender ModeをWorld Spaceにして通常のゲームオブジェクトと同じ扱いをすることが出来ました。

TextMeshProを使ってもCanvasの子要素に配置したり(InputFieldやButton、DropdownのテキストもTextMeshProに出来ます)、通常のゲームオブジェクトとしてテキストを作ることも出来ます。

新しめのUnityのバージョンであればTextMeshProは既にエディターに入っているので、使用する時に必要な他のファイルをインポートして使うだけです。

UnityメニューのWindowからTextMeshPro→Import TMP Essential ResourcesとImport TMP Examples and Extrasを選択しそれぞれインポートします。

TMP Essential Resourcesはフォント等のデータ、TMP Examples and ExtrasはTextMeshProを使ったサンプルが入っています。

ダメージと回復ポイント用のTextMeshProの作成

TextMeshProが使えるようになったのでダメージと回復用のTextMeshProを作成していきます。

Font Assetの作成

TextMeshProで使用するFont Assetを作成します。

Font Assetを作成するには元となるフォントファイルが必要になります。

今回は日本語は使わないのでTMP Essential Resourcesをインポートしてついてきたフォントを元にFont Assetファイルを作成します。

Assets/TextMesh Pro/Fonts/LiberationSans.ttfを選択した状態で右クリックからCreate→TextMeshPro→Font Assetを選択し、名前をDamageSDFとします。

DamageSDFを選択しインスペクタのGeneration SettingsのSource Font FileにLiberationSans.ttfを設定します。

DamageSDFをAssets/TextMesh Pro/Resources/Fonts & Materialsに移動させます。

DamageSDFを選択した状態でCtrl+Dキーをおして複製し、名前をHealingSDFとします。

Font Assetのマテリアルの設定

Font Assetが出来たのでそのFont Assetのマテリアルを設定します。

DamageSDFの子要素のLiberationSansSDFMaterialを選択します。

ユニティちゃんRPGで使用しているDamageSDFのマテリアルを選択

DamageSDFの子要素のLiberationSansSDFMateriarlのインスペクタのShaderがTextMeshPro/Distance FieldとなっていなければTextMeshPro/Distance Fieldに変更します。

FaceのColorを赤色にし、Dilateを1、OutlineのThicknessを0.3、Lightingにチェックを入れBevelのAmountを0.15にします。

Local LightingのDifuse Shadowを0にします。

ユニティちゃんRPGで使用するDamageSDFの子要素のマテリアルの設定

HealingSDFの子要素のLiberationSansSDFMaterialのインスペクタも同じように設定し、FaceのColorだけ青色にします。

これでFont Assetのマテリアルの設定が終わりました。

TextMeshProの作成

ヒエラルキー上で右クリックから3D Object→Text- TextMeshProを選択し、名前をDamageTextProとします。

DamageTextProのインスペクタのTextMeshProのMain SettingsのFont AssetにDamageSDFを設定します。

MeshRendererのMaterialsのElement0にDamageSDFのマテリアルが設定されていなければDamageSDFのマテリアルを設定します。

RectTransformのWidthを5、Heightを1、TextMeshProのFont Sizeを6、Alignmentを真ん中にします。

ユニティちゃんRPGのDamageTextProの設定

これで以下のようになりました。

ユニティちゃんRPGで使用するDamageTextProの実際の画像

ヒエラルキー上のDamageTextProゲームオブジェクトを選択し、Ctrl+Dキーで複製し、名前をHealingTextProとします。

HealingTextProのFont AssetをHealingTextProにし、MaterialsのElement0にHealingSDFの子要素のマテリアルを設定します。

HealingTextProは以下のようになりました。

ユニティちゃんRPGのHealingTextProの実際の画像

ここまで出来たらヒエラルキー上のDamageTextProとHealingTextProをAssets/RPG/Prefabs/UI/BattleCommandフォルダにドラッグ&ドロップしてプレハブにします。

テキストのアニメーションを作成する

ダメージや回復ポイント用のテキストプレハブが出来たので後はダメージを与えた時や回復した時に対応するテキストプレハブに値を設定してインスタンス化するだけです。

ですがテキストがそのまま表示されるだけだと印象に残らないので、テキスト一文字ずつアニメーションを付ける事にします。

アニメーションはスクリプトから一文字の作成に使われているvertex(頂点)を移動して行う事にします。

アニメーションをさせるスクリプトはImport TMP Examples and ExtrasでインポートしたファイルにあったAssets/TextMesh Pro/Examples and Extras/Scripts/VertexJitterスクリプトを元に作ります。

VertexJitterスクリプトではコルーチンを使ってアニメーションをさせていましたが、Updateメソッドを使ってアニメーションさせるように変更しました。

Assets/RPG/Scripts/Battleフォルダに新しくRaiseAndLowerTextAnimationScriptを作成します。

今回作成するアニメーションは大きい桁の数字から上に上がって一定の高さになったら下に戻り、下に戻ったら次の文字が上がって下がるというアニメーションをさせます。

スクリプトが長いので分割して説明します。

クラス定義、フィールド、初期化などのメソッド

まずはクラス定義やフィールド、初期化などを行っているメソッドを見ていきます。

destinationYValueはテキストが上にどれだけ上がるかの距離を設定します。

charSpeedは文字が移動する速さを設定します。

m_TextComponentはTMP_Textを入れます。

hasTextChangedは元々のスクリプトで使っていたもので、よくわかりませんが、trueの時にTMP_Meshinfoのコピーを生成するようです。

vertexAnimsは個々の頂点の構造体データを入れます。

textInfoは個々の文字のテキスト情報を入れます。

characterAnimsは個々の文字の構造体データを入れます。

VertexAnim構造体は個々の頂点のYの位置を入れる事が出来るようにします。

CharacterAnim構造体はisAnimationStartはアニメーションが開始しているか?、isAnimationEndはアニメーションが終了したか?、isFlapは上に行ききって反転したかを入れます。

構造体はクラスと同じように使えますが、構造体の変数やフィールドには実体が入ります。

クラスの場合は変数やフィールドには実体の場所を指し示す参照値が入っています。

なので構造体をメソッド等の引数に渡す時は受け取り側の構造体の引数にも実態が渡される為メモリを使うようです。

Awake、OnEnable、OnDisableは元々のスクリプトにあったもので何をしているのかはよくわかりません。

StartメソッドとON_TEXT_CHANGEDメソッド

次にStartメソッドとON_TEXT_CHANGEDメソッドを見ていきます。

m_TextComponent.ForceMeshUpdate()で一旦強制でメッシュのアップデートを行わないとその後のTextMeshProからデータを取る時にエラーが出る為呼び出します。

テキストの一文字は4つの頂点から作られているのでtextInfo.characterCountで文字数を取得しそれに4をかけた数字分の頂点データが必要になります。

その分のVertexAnimを作成しvertexAnimに入れています。

characterAnimは文字毎のデータなので文字数分のデータを確保します。

characterAnim[0]で最初の文字の構造体データを取得しisAnimationStartをtrueにして最初の文字のアニメーションをスタートさせます。

cachedMeshInfo = textInfo.CopyMeshInfoVertexData()は元々のスクリプトにあったものでMesh情報の頂点データを複製していると思われます。

ON_TEXT_CHANGEDメソッドも元々のスクリプトにあったものです。

Updateメソッド

Updateメソッドを作成します。

m_TextComponent.ForceMeshUpdate()で最初にテキストのメッシュをアップデートします。

characterCountが0、つまりテキストに一文字もなければreturnでその後の処理をしません。

で文字数分のcharOffsetのVector3の配列を作成します。

その後for文で文字数分の繰り返しを行います。

その文字のisAnimationStartがfalseの時(その文字のアニメーションがスタートしていない時)、isAnimationEndがtrueの時(その文字のアニメーションが終了している時)はcontinueで次の文字に回します。

!charInfo.isVisibleでその文字が見えない(空白文字等)時はその文字の構造体データのisAnimationStartをfalseにし、isAnimationEndをtrueにし次の文字のアニメーションに移ります。

最後の文字まで進んでいなければ次の文字のisAnimationStartをtrueにします。

最後の文字であればこのスクリプトが設定されているゲームオブジェクトを1秒後に削除します。

の部分は元々のスクリプトにあったものでマテリアルのインデックス、頂点のインデックスの取得をして、頂点から文字の真ん中の位置を取得しています。

その文字を作っている4つの頂点に元のデータにオフセット値を加えたものを入れています。

その文字の構造体データのisFlapがfalseの時(文字が上に移動している時)はMathf.MoveTowardsメソッドを使って現在のYの位置からdestinationYValueの値にcharSpeed * Time.deltaTimeのスピードで移動させます。

求めた値はその頂点の構造体データのyValueに入れて置き次にここに来た時に使用します。

目的地を超えたらその文字の構造体データのisFlapをtrueにして下向きに移動させるようにします。

下向きの場合は現在のYの値から0にcharSpeed * Time.deltaTimeのスピードで移動させます。

目的地を超えたらこの文字は終了し、次の文字のアニメーションへ移行させます。

Matrix4×4.TRSメソッドは位置、回転、スケールから行列を求められます。

vertexIndexはその文字の最初の頂点の番号でそれに0~3を足すことでこの文字を形成している4つの頂点を表すことが出来ます。

matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 0])で作成した変換行列(matrix)を使って引数で与えた頂点の位置を変換します。

最後に頂点を更新しています。

これも元々のスクリプトにあったものなのでよくわかりません。

Updateメソッド内でfor文を使って全部の文字を繰り返ししてisAnimationStartがtrueの文字だけをアニメーションさせています。

ですが結局アニメーションさせる文字は最初の文字から一文字ずつをアニメーションさせるのでfor文を使わずにcharNum等の文字のインデックスを使って処理をすることも出来ます。

ただこの場合は文字を切り替えた後に一旦次のUpdateメソッドが呼ばれるまで次の文字がアニメーションをしません。

なので文字の切り替わりが断絶されたような感じでスムーズなアニメーションにならないのでfor文を使って処理をしています。

これでスクリプトが出来たのでDamageTextProプレハブとHealingTextProプレハブに取り付けます。

攻撃や回復をした時にDamageTextProやHealingTextProのインスタンス化をして表示する

ダメージ用のテキストDamageTextProと回復用のテキストHealingTextProが出来たのでそれらを攻撃や回復した時にインスタンス化して表示するようにします。

ポイント表示用スクリプトの作成

ダメージや回復ポイントを表示させるスクリプトを作成します。

Assets/RPG/Scripts/Battleフォルダに新しくEffectNumericalDisplayScriptスクリプトを作成し、BattleManagerゲームオブジェクトに取り付けます。

NumberTypeはダメージ用なのか?回復用なのかでインスタンス化するプレハブを変える時に使う列挙型です。

damagePointTextはダメージ用のプレハブ、healingPointTextは回復用のプレハブをインスペクタで設定します。

offsetはテキストを表示する位置のオフセット位置を設定します。

InstantiatePointTextメソッドは第1引数で受け取ったNumberTypeでインスタンス化するテキストプレハブを変化させます。

第2引数で攻撃等の対象者のゲームオブジェクト、第3引数でテキストに表示するダメージ数等を受け取ります。

Instantiateメソッドでインスタンス化していますが、第3引数でCamera.main.transform.rotationを指定して、カメラの向きに合わせてテキストの角度を合わせます。

Destroyで3秒後にインスタンス化したゲームオブジェクトを消していますが、正しく動作していればRaiseAndLowerTextAnimationScriptスクリプトで全部の文字のアニメーションが終了したら自動で削除されているので、この処理はいりません。

おまけとして残してありますけど・・・・( 一一)

BattleManagerのEffectNumericalDisplayScriptのインスペクタは以下のように設定します。

ユニティちゃんRPGのEffectNumericalDisplayScriptのインスペクタの設定

テキストをインスタンス化するメソッドの呼び出し

EffectNumericalDisplayScriptのInstantiatePointTextメソッドは攻撃や回復した時に呼び出して使用するので該当する場所で呼び出し処理を追加します。

CharacterBattleScriptスクリプトに処理を追加します。

フィールドを追加します。

StartメソッドでEffectNumericalDisplayScriptを取得します。

まずはDirectAttackメソッドの最後に追加します。

次はMagicAttackの最後です。

UseMagicメソッドの回復をした時に処理を追加します。

UseItemメソッドのHPとMPの回復処理の所にメソッド呼び出しを追加します。

これでメソッドの呼び出し処理の追加が終わりました。

実際に戦闘をしてテキストが表示されアニメーションするかどうか確認してみましょう。

上のようになりました。

終わりに

与えたダメージ等をテキストを使ってキャラクターの近くに表示する事でより視覚的にわかりやすくなりましたね。

今回はスクリプトを使って一文字ずつアニメーションをさせているので少し難しい感じになっていますね。

TextやTextMeshProをAnimationウインドウでそれらを上下に移動させるアニメーションを作ってプレハブにし、

ダメージ数が1000だとしたら桁ごとにそのテキストのプレハブをインスタンス化して並べればスクリプトでアニメーションをさせない方法でも同じように出来ます。

Unityでダメージを与えた時のポイント表示でただテキストを表示するのではなく一文字毎にアニメーションをさせて表示させる機能を作成します。
ユニティちゃんライセンス

この作品はユニティちゃんライセンス条項の元に提供されています

スポンサーリンク

記事をシェアして頂ける方はこちら

フォローして頂くとやる気が出ます