Unityのゲームにスキルツリーのシステムを搭載する

今回はUnityでRPGやアクションゲーム等のスキルツリーのシステムを作ってみたいと思います。

スキルツリーシステムと言っても管理するスクリプトはアイテム管理と同じような感じで作る事が出来るので、UIのデザインの部分が重要になってきます。

が、わたくしにデザインの才能はないのでUIはとりあえず、といった感じになります。(^_^;)

スポンサーリンク

スキルツリーのUIを作成

Canvasの作成

まずはスキルツリーを表示するキャンバスを作成します。

ヒエラルキー上で右クリック→UI→Canvasで作成し、名前をSkillUIとします。

インスペクタでCanvas ScaleのUI Scale ModeをScale With Screen Sizeを選択し、Screen Match ModeをExpandにします。

SkillTreeのCanvas

これはゲームの画面サイズを変更した時にある程度UIがスクリーンサイズに合わせて縮小するようにする為です。

この辺りは

UnityのUIの要素を細かく見てみる
UnityのUIの要素を細かく見ていきます。具体的にButton、Toggle、Slider、Scrollbar、Scroll Rect、Dropdown、Input Field、Scroll View、Canvasを使った簡単なサンプルを作成していきます。

の記事のキャンバス(Canvas)項目を参照してください。

この後、作成したSkillUIの子要素に3つのPanelを作成し『スキルポイント表示部』『スキルツリー部』『説明表示部』の3つの空間を作成していきます。

スキルポイント表示部

まずはスキルポイント表示部を作成していきます。

SkillUIを選択した状態で右クリック→UI→Panelを選択し名前をSkillPointとします。

SkillPointパネルのサイズをSkillUIの上から10%のサイズに変更します。

スキルポイント部のサイズ調整

↑のSkillPointの四隅にある三角形のアイコン(今回は左下のもの)をドラッグしSkillPointの上から10%部分まで移動させます。

SkillPointのインスペクタは

スキルポイント部のインスペクタ

↑のようになります。

次にSkillPointを選択した状態で右クリック→UI→Textを選択し、SkillPointの子要素にTextを作成します。

TextのAnchorを選択します。

Anchorの選択方法

↑のようにアイコンをクリックしShiftキーとAltキーを押しながら右下の縦と横をStretch(親の要素に合わせる)を選択します。

ShiftとAltを押しながら選択する事ですぐに親に合わせて自身(Text)が調整されます。

スキルポイントを表示するテキストUI

Textは↑のようになりました。

テキストに使用するフォントの変更、フォントサイズ、テキストの表示位置(中央に表示されるように)を変更しておきます。

これでスキルポイント表示部が出来ました。

説明表示部の作成

『スキルツリー部』は一番大変なので最後に回して先に『説明表示部』を作成していきます。

SkillUIを選択した状態で右クリック→UI→Panelを選択し名前をSkillInformationとします。

その子要素にUI→Textを作成します。

Textの表示位置は左上となるようにTextインスペクタのParagraphのAlignmentを変更します。

SkillInformation部

↑のようにSkillPointと同じですね。

説明表示部のサイズ調整

SkillInformationのサイズを変更し↑のように上から80%の部分までドラッグし下の方に表示されるようにしておきます。

これで説明表示部が出来ました。

スキルツリー部

最後にスキルツリー部を作成していきます。

SkillUIを選択した状態で右クリック→UI→Panelを選択し名前をSkillPanelとします。

スキルツリー部のサイズをスキルポイント部の下と説明表示部の上にピッタリ合うように調整します。

スキルツリー部のサイズ変更

↑のように真ん中にスキルツリー部がある形になります。

スキルひとつひとつを表現するのにUIのボタンを使用します。

スキル毎のボタンを押して条件が整えばスキルを覚える事が出来るようにします。

スキルツリーなので『スキル毎のボタン』と『スキルを繋げる遷移』が必要になりますが、わかりやすくなるように『ボタンパネル』『遷移』のUIを分けます。

特に分ける必要はないのですが見た目上わかりやすく管理する為です。

でも、一緒にした方がちょっとした移動をさせる時便利かもしれないなぁ・・・・(-_-)

ボタンパネルの作成

SkillPanelを選択した状態で右クリック→UI→Panelを選択し名前をButtonPanelとします。

ButtonPanelのインスペクタでAnchorsを調整し縦横がStretchになるようにします。

これでButtonPanelはSkillPanelと同じ大きさの領域になります。

ButtonPanelを選択した状態で右クリック→UI→Buttonを選択します。

Buttonの子要素にUIのImageを1つ作成し名前をそのまま(もちろん変更してもOK)、Textを2つ作成し名前をTitleとInformationにします。

スキルボタンを形成するもの

階層は↑のようになります。

Titleのインスペクタを表示しParagraphのAlignmentでテキストを上付きで表示するようにします。

スキルのタイトル

Anchorsは縦横Stretchです。

Imageはスキルのイメージを表示するものなのでSource Imageにスプライトを設定します。

スキルのイメージ

Imageは中央に表示するのでAnchorsはmiddle centerにします。

Imageのサイズを調整しボタンに合わせます。

InformationのインスペクタのParagraphのAlignmentでテキストを下付きにします。

スキルの情報

設定が終わったらTitleのTextにスキルの名前、InformationのTextにスキルの簡易説明を設定します。

1つのスキルが出来上がった

↑のように1つのスキルが出来上がりました。

ボタンの中にスキル名とスキルの簡易説明を表示していますが、もちろん表示するものは自由に設定してください。

出来上がったスキルをCtrl+Dでコピーし他のスキルを作成します。

スキルをコピーし配置

↑のようにButtonをコピーし他のスキルを作成し配置していきます。

名前を変更していないので全てButtonの派生の名前になってますが・・・・・(^_^;)

スキルを配置した状態

↑がスキルを並べた画像です。

これでスキルボタンの配置が終わったので次はスキルの遷移を作成していきます。

スキル遷移UI

スキルボタンが出来たのでその遷移を表すUIを作成していきましょう。

スキルの遷移を表すアイコンは矢印で作成しますが、矢印アイコンをそのまま使うと

矢印の先が長くなってしまう

↑のように矢印の先が長く伸びてしまうので矢の本体部分と先でわけて画像を作成します。

矢印用の画像を作成

矢印の本体用Image

↑が矢印の本体用のImage画像。

矢印の先用Image

↑が矢印の先用のImage画像になります。

上の2つの画像はダウンロードしてお使いください。

画像をダウンロードしたらUnityのAssetsエリア内で右クリック→Import New Asset…で画像を選択しUnityに取り込みます。

矢印本体のSenのImport Settingsを変更します。

矢印本体SenのImportSetting

↑のようにTexture TypeをTexture、Wrap ModeをClampにします。

矢印の先のyaのImport Settingsを変更します。

矢印の先YaのImportSetting

↑のようにTexture TypeをTexture、Wrap ModeをClampにします。

Wrap ModeをClampにしたのはRepeatだとサイズが足りない時に画像の繰り返しが行われて表示されてしまう為です。

これで矢印用の画像の取り込みが終了しました。

スキル遷移画像を設定

矢印用画像の取り込みが終了したのでスキルの遷移を作成していきます。

SkillPanelを選択した状態で右クリック→UI→Panelを選択し名前をRootPanelとします。

遷移の元のPanel

RootPanelのインスペクタは↑のようになりSkillPanelと同じ大きさにします。

次にRootPanelの子要素にUI→RawImageを作りその子要素にRawImageを作成します。

ひとつの遷移の作成

↑のような階層になります。

このRawImage以下が遷移の矢印の画像を形成します。

親のRawImageのTextureには矢印本体のSenを設定します。

遷移矢印の本体Image

子のRawImageのTextureには矢印の先のyaを設定します。

遷移矢印の先Image

矢印の向きをスキルツリーの向きと逆に作ってしまった為RotationのZ軸を回転し向きを合わせています。

矢印本体と先の画像の色が黒で統一されているので問題ではありませんが、本体と矢の先の色が違う場合はそれぞれの位置を丁度に合わせないと重なってしまいます。

出来上がったら『攻撃UP1』から『攻撃UP2』への遷移の矢印を作成する為に親のRawImageを移動させます。

攻撃UP1から攻撃UP2までの遷移

↑のような感じに遷移の矢印を移動させました。

他のスキルの遷移も同じように作成します。

矢印を斜めにする必要がある場所もあります。

矢印を斜めにする

↑のような感じですね。

UIは2DなのでRotationはZ軸部分だけ変更して回転させるようにします。

回転については他のゲームオブジェクトの回転と同じように出来ます。

2DなのでZ軸だけ回転させる

↑のようにZ軸だけ回転させます。

全てのスキルの遷移を作成すると

スキルツリー部の完成画像

のようになります。

矢印を斜めにするとギザギザが少し目立ちますね・・・・(-_-)

元の画像を引き延ばしているので仕方ないと言えば仕方ないですが・・・。

斜めに遷移させないで直角に遷移させるとギザギザを気にする必要はなくなりますね。

スキル管理スクリプト

SkillUIにスキルを管理するスクリプトSkillSystemを新しく作り設定します。

それぞれのスキルを識別する為に列挙型を使って判別出来るようにします。

skillPointはスキルを覚える時に使うポイント、skillsはそのスキルを覚えているかどうかを入れておくbool型の配列、skillParamsはスキルそれぞれに設定するSkillParamスクリプトを設定します。

skillTextはスキルポイントを表示するテキストUIを設定します。

Awakeメソッドでスキルの数分のskillsの領域を確保します。

bool型の変数(今回の場合配列)は初期値を指定しないとデフォルトでfalseが設定されるので個別に初期値を設定する事はしていません。

その後SetTextメソッドを呼び出しスキルポイントをテキストUIに表示しています。

SetSkillメソッドはスキルタイプと消費するスキルポイントを受け取りスキルを覚えさせます。

SkillType型の変数を(int)でキャストするとSkillTypeの順番に並べた数値を取得する事が出来ます。

SetSkillPointメソッドでスキルポイントを更新し、SetTextでテキストUIに新しいスキルポイントを表示しています。

SetSkillPointメソッドに処理を分離したのはスキルポイントを消費する機能だけでなくプラスにする処理を作る場合にSetSkillPointの処理を変更すれば楽に出来ると思ったのでそうしました。

今回の場合は消費する事しか念頭に置いていない為、skillPointから受け取ったポイント分を減らしているだけです。

CheckOnOffメソッドはスキルを覚えた時に他のスキルを覚えられる状態にする処理を実行します。

実際に実行するのはSkillParamスクリプトのCheckOnOffメソッドになります。

foreach文を使いskillParamsに格納されている全てのCheckOnOffメソッドを呼び出しています。

IsSkillは受け取ったスキルを覚えているかどうかを調べ、GetSkillPointはスキルポイントを返します。

Checkメソッドはそのスキルを覚えられるかどうか?のbool値を返すメソッドで、spendPoint引数が渡ってこなかった場合オプション引数を使ってspendPointを初期化しています。

オプション引数に関しては

C#のクラス、フィールド、メソッド、コンストラクタ、プロパティの作成
C#のクラスの作成やフィールド、メソッド、コンストラクタ、プロパティについて記述しました。

を参照してください。

Checkメソッドで行っている事は覚える為に消費するスキルポイントがなければfalseをまず返します。

その後そのスキルを覚える為の条件をクリアしているかどうかを判断しbool値をreturnしています。

例えば『攻撃UP2』は『攻撃UP1』を覚えていないと覚えられないので『攻撃UP1』を覚えていなければfalseを返しています。

return skills [(int)SkillType.attack1];

と一気に記述しているのでわかり辛い人もいるかもしれませんが、skillsはbool型の配列でskills[(int)skillType.attack1]でbool値が得られるのでそれをreturnしているだけです。

スキルパラメータスクリプト

スキル管理スクリプトでも出てきましたが個別のスキルに設定するスキルパラメータスクリプトSkillParamを作成していきます。

skillSystemは先ほど作成したSkillSystemスクリプトを設定します。
typeはこのスキルのタイプを設定します。
spendPointはこのスキルを覚える為に必要なスキルポイント。
skillTitleはスキルテキストUI情報に表示するスキルタイトル。
skillInformationはスキルテキストUI情報に表示するスキルの説明。
textはスキル情報を載せるテキストUI。

になります。

StartメソッドでCheckOnOffメソッドを呼び出します。

CheckOnOffメソッドはスキルをまだ覚えていない状態、覚えている状態等でボタンの色を変更する処理です。

実際に変更しているのはChangeButtonColorメソッドで受け取った色にボタンのNormalColorとPressdColorを変更しています。

NormalColorやPressdColorは直接変更出来ないので一時的にColorBlock変数を作成し、そのNormalColorやPressdColorを変更したのちにbutton.colorsに代入して変更します。

今回の処理はボタンの状態によって色合いを変える為ButtonのTransitionがColor Tintである必要があります。

その他のTransitionを設定している場合はそれぞれの対応が必要になってきます。

OnClickメソッドはスキルボタンが押された時に実行させるメソッドです。

自身のスキルを覚えていたらreturnですぐ処理をやめます。

それ以外の時でCheckメソッドでスキルを覚えられるか調べスキルを覚えさせスキルテキストUIにスキルを覚えた事を表示します。

スキルが覚えられない時はスキルを覚えられないと表示します。

SetTextメソッドはスキルボタンがアクティブ(マウスが上に来た時やフォーカスが移動してきた時)になった時にスキル情報をスキルテキストUIに表示するメソッドです。

ResetTextメソッドはスキルテキストUIを空にするだけです。

SetTextやResetTextメソッドを呼び出す為にはマウスがスキルボタンの上に来たや移動キーやゲームパッドでフォーカスがスキルボタンに来たというイベントを受け取り、
そのイベントを受け取ったらSetTextやResetTextメソッドを実行する必要があります。

それは後で作成します。

SkillSystemとSkillParamのインスペクタの設定

とりあえずSkillSystemスクリプトとSkillParamスクリプトが出来たので、SkillSystemをSkillUIゲームオブジェクトに、

SkillParamスクリプトをButtonPanelの子要素のそれぞれのボタンに設定します。

SkillSystemスクリプトではskill Point、スキルボタンに設定されているSkillParamをそれぞれ設定、Skill TextにスキルテキストUIを設定します。

SkillSystemのインスペクタの設定

↑のような感じです。

『攻撃UP1』のスキルボタンに取り付けたSkillParamの設定は

SkillParamのインスペクタの設定

のようになります。

そのスキルのタイプの設定とスキル情報の記述等を設定しています。

それぞれのスキル毎に設定をします。

これでスクリプトの設定が終了しました。

スキルボタンのイベント処理を追加

スクリプトが出来上がったのでスキルボタンの上にマウスが来た時、押した時、移動キーやゲームパッドでフォーカスが当たった時のイベント処理を追加します。

例として『攻撃UP1』のスキルボタンで説明していきます。

スキルボタンゲームオブジェクトのAdd Component→Event→EventTriggerを追加します。

EventTriggerを追加

↑はすでにイベントタイプを追加していますが本来はAdd New Event Typeをクリックしイベントの種類を追加します。

またOn Clickは最初からButtonについているのでそれを使用します。

AddNewEventTypeボタンを押すと新しいイベントタイプを追加出来る

Add New Event Typeをクリックすると↑のようにイベントのタイプを選択出来るので、

Pointer Exit(マウスがボタン外に出た)、Pointer Enter(マウスがボタン内に入ってきた)、Select(フォーカスが当たった)、Deselect(フォーカスが外れた)を追加します。

それぞれのタイミングはカッコ内に記述していますが、今回のスキルツリーの操作はマウス、キーボード、ゲームパッド全てで操作出来るようにする為、色々なイベントを追加しています。

イベントタイプを追加したら

イベントタイプに新しいイベントを追加

↑のように+を押して、それぞれのイベントタイプ毎にイベントを追加します。

Pointer Exitの設定をしてみます。

イベントを追加したらゲームオブジェクトを指定する箇所があるのでそこにSkillParamスクリプトを持つ自分自身のゲームオブジェクトをドラッグ&ドロップします。

スクリプトがあるゲームオブジェクトを指定

ゲームオブジェクトを指定すると実行するメソッドを指定する事が出来るのでそこにSkillParamスクリプトのResetTextメソッドを設定します。

実行するメソッドを指定

このようにPointer Exitイベントが発生した時にResetTextメソッドを実行するように指定する事が出来ます。

Pointer Exit、DeselectはResetTextメソッド、Pointer Enter、SelectはSetTextメソッドを指定します。

ButtonのOn ClickにはOnClickメソッドを指定しておきます。

スキルボタンそれぞれに同じように設定していきますが、イベントに設定するゲームオブジェクトは必ず自分自身を設定します。

これでイベントの追加も終了しました。

スキルツリー画面のオン・オフ

スキルツリーの画面は出来ましたが、通常であれば最初は見えない状態で何らかのキーやボタンを押す事でスキルツリー画面を表示したいところです。

そこでMain CameraにSkillSystemOnOffスクリプトを新しく作り取り付けます。

skillSystemはSkillUIに設定しているSkillSystemスクリプト、firstSelectはスキルボタンで最初にフォーカスする対象を指定します。

今回はfirstSelectには『攻撃UP1』のスキルボタンを設定します。

UpdateメソッドではキーボードのSキーを押した時にSkillUIのオン・オフをします。

本来であればGetButtonDownを使ってキーボードとマウス、ゲームパッドどちらを使っても操作できるようにしておくといいと思います。

EventSystem.current.SetSelectedGameObjectで最初にフォーカスしておくゲームオブジェクトを設定する事が出来ます。

これでSkillUIのオン・オフが可能になったのでSkillUIのインスペクタで名前の横のチェックボックスを外し、最初はオフの状態にしておきます。

これでスキルツリーの機能が完成しました!

スキルツリーUIの全体は

スキルツリーUIのヒエラルキー

↑のようなヒエラルキーになります。

スキルツリー機能を確認する

スキルツリー機能が完成したのでマウスやゲームパッドで操作して確認してみます。

↑のようになりました。

最初マウスで操作して確認し一旦Unityを終了してからゲームパッドで操作しています。

今回の場合はゲームパッドで操作する場合でもSkillUIのオン・オフはキーボードのSキーを押す必要があります。

スキルを覚えたスキルボタン自体のinteractableをfalseにしボタン自体を機能させないようにする事も出来ますが、

ゲームパッドの操作を考えた場合に一度覚えたスキルボタンの上にフォーカスが移動出来なくなってしまう為やめました。

マウス操作のみを使う場合はボタンの色合いを変更するのではなくButtonのinteractableをスクリプトからfalseにする方が楽です。

スポンサーリンク

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

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