ターン制RPGの作り方#1|プロジェクトの準備とバトル画面のレイアウト

夜の図書館の書庫で、左にスライムちゃん・フェアリー・キョンシーが右を向いて斜めに並び、その場で弾んでいる。右にこぼれたインク、上に「こぼれたインクが あらわれた!」のウインド、左下と右下に空のウインド

「いつかRPGを作ってみたい!」と思ったことがある人は多いのではないでしょうか?ただ、フィールドや町やイベントまで全部作ろうとすると、とんでもない量になってしまいます・・・。そこでこのシリーズでは、フィールドを歩く部分は作らずに、RPGの一番の楽しさであるコマンドバトルと育成に集中して、遊べるRPGを最初から最後まで作っていきます。今回は1回目として、プロジェクトを作って、4人の仲間が待つバトル画面のレイアウトを作ってみたいと思います!

目次

今回作るもの

  • Universal 2Dでプロジェクトを作り、フォルダとシーンを用意する
  • キャラクター・敵・背景の絵と、日本語のフォントを取り込む
  • Canvasを「カメラに映す」設定にして、画面を場所ごとに分ける
    • Stage:味方と敵が並ぶ場所(横から見た「サイドビュー」)
    • MessageWindow:上のメッセージ
    • CommandWindow:左下のコマンド
    • StatusWindow:右下の味方のHP・MP
  • 3人の仲間を並べて、その場でぷるぷる弾ませる

作るスクリプトは1つです。

スクリプト役割付ける場所
IdleBounce待機のコマを切り替えて、その場で弾ませる3人の仲間
スライム

今回の主人公はスライムちゃんと、フェアリー・キョンシー・メドゥーサの4人です!バトルには3人で出て、残りの1人とは図書館のロビーで入れ替えられるようにする予定です

プロジェクトを作ろう

  • Unity Hubで新しいプロジェクトを作る
    • エディターバージョン:Unity 6.3 LTS(記事作成時点では6000.3.22f1で確認しています)
    • テンプレート:Universal 2D
    • プロジェクト名:TurnBasedRpg(好きな名前でOK)

テンプレートの違いは1-2 プロジェクトを作る時のテンプレート選択で紹介しています。

プロジェクトが開いたら、先にフォルダとシーンを整えておきます。

  • ProjectウインドのAssetsで右クリック>Create>Folderで「TurnBasedRpg」を作る
    • 自分で作ったものは全部この中に入れるので、テンプレートに最初から入っているものと混ざりません
  • その中に、Scripts・Sprites・Prefabs・Data・Effects・Audio・Fonts・Scenes の8つのフォルダを作る
  • Assets>Scenes>SampleSceneをBattleにリネームして、TurnBasedRpg>Scenesに移動する
Assets>TurnBasedRpgの中にAudio・Data・Effects・Fonts・Prefabs・Scenes・Scripts・Spritesが並び、ScenesにBattleがある

最後に、Gameビューの画面サイズを決めます。このシリーズはPCで遊ぶ横画面のゲームとして作ります。

  • Gameビューの左上の解像度のドロップダウンを開き、一番下の+を押す
    • Label:Full HD、Type:Fixed Resolution、Width & Height:1920・1080
  • 作ったFull HD (1920×1080)を選ぶ

素材を取り込もう

シリーズで使う素材は、下のリンクからダウンロードしてください。全27回で使う素材(仲間4人・敵・背景・アイコン・音など)が、すべて入っています。

取り込み方は2つあります。

  • かんたん:zipの中のTurnBasedRpgAssets.unitypackageをダブルクリック(またはAssets>Import Package>Custom Package…)
    • 取り込みの設定が入った状態で入るので、次の「絵の設定」は読むだけでOKです
  • 自分で入れる:zipの中のTurnBasedRpgフォルダを、UnityのAssetsにドラッグ&ドロップ
    • この場合は、次の設定を自分で合わせてください

素材は自由に使ってOKです(クレジット不要。作ったゲームの公開・販売にも使えます)。素材そのものの再配布はご遠慮ください。

入っている絵

フォルダ中身
Sprites/Charactersスライムちゃん・フェアリー・キョンシー・メドゥーサ(右向きのポーズと、正面のポーズ。200×200)
Sprites/Enemies地下1階の敵(こぼれたインク・紙ひこうき・本の虫)
Sprites/Backgrounds地下1階の書庫
Sprites/UIウインドの枠、白い四角

4人の絵は、同じポーズが同じ番号になっているので、ファイル名の頭にキャラクターの名前を付けてあります(slime_walk_61.png、fairy_walk_61.pngなど)。名前が同じだと、Inspectorで絵を選ぶときにどれがだれだか分からなくなるためです。

Sprites>Characters>Slimeの中に、slime_attack_61・slime_book_01・slime_walk_61などの絵が並んでいる

絵の設定

  • Spritesフォルダの中の画像を全部選ぶ(各フォルダで1枚目をクリック → 最後をShift+クリック)
  • Inspectorで次のように設定して、Apply
    • Texture Type:Sprite (2D and UI)
    • Sprite Mode:Single

Universal 2Dのプロジェクトでは、取り込んだ画像のSprite Modeが最初からMultipleになっていることがあります。Multipleのままだと「slime_walk_61_0」のように名前が変わり、UIのImageに入れるときに分かりにくくなるので、Singleにしておきましょう。

ウインドの枠(UI/ui_window)だけは、もう1つ設定があります。四角い枠を、角をつぶさずに好きな大きさに伸ばせるようにします。

  • ui_windowを選んで、InspectorのSprite Editorを押す
  • 右下のBorderの L・T・R・B を、すべて24にして、上のApply
    • 緑の線で、絵が9つに区切られる(角の4つは伸ばさず、辺と真ん中だけを伸ばす)

日本語のフォント

メッセージやコマンドに日本語を出したいのですが、TextMeshProに最初から入っているフォントには日本語がありません。zipに入っているNoto Sans JPからフォントアセットを作ります。

  • TurnBasedRpg/FontsのNotoSansJP.ttfを右クリック>Create>TextMeshPro>Font Asset>SDF
    • 「NotoSansJP SDF」が出来る(Atlas Population ModeはDynamicのまま。使った文字だけをその場で用意してくれます)
  • 出来たNotoSansJP SDFを選び、InspectorのGeneration SettingsにあるMulti Atlas Textures にチェックを入れる
    • RPGはメッセージの文字の種類が多いので、文字を書きこむ画像(アトラス)が1枚でいっぱいになったときに2枚目を作ってくれるようにしておきます
  • Edit>Project Settings>TextMesh Pro>Settings のDefault Font Assetに、NotoSansJP SDFを入れる
    • 新しく作るテキストが、最初から日本語で表示されるようになる
  • 初めてTextMeshProを使うと「TMP Importer」のウインドが出るので、Import TMP Essentialsを押す
左はNotoSansJP SDFのInspectorのGeneration Settings(Atlas Population ModeがDynamic)。右はProject SettingsのTextMesh Pro>Settingsで、Default Font AssetにNotoSansJP SDFが入っている

フォントアセットの作り方は、9-3 TextMeshProで美しいテキストを表示しようで詳しく紹介しています。

Canvasを用意しよう

画面の部品は、キャラクターも含めてUIで作ります(Canvasの基本は9-1 UnityのUI(Canvas)システムを知ろう)。

  • Hierarchyで右クリック>UI (Canvas)>Canvas(EventSystemも一緒に出来ます)
  • Canvasを選んで、Inspectorで次のように設定
    • Render Mode:Screen Space – Camera
    • Render Camera:Main Cameraをドラッグ
  • Canvas Scalerを次のように設定
    • UI Scale Mode:Scale With Screen Size
    • Reference Resolution:X 1920、Y 1080
    • Match:0.5
CanvasのRender ModeがScreen Space - Camera、Render CameraがMain Camera。Canvas ScalerはScale With Screen Size、1920×1080、Match 0.5
  • Screen Space – Camera
    • UIを、カメラの前に置いた板のように映す設定
    • 最初のScreen Space – Overlayは「カメラと関係なく画面の一番手前に描く」ので、パーティクル(火花やまほうのキラキラ)をUIの手前に出せない
    • このシリーズでは#8の攻撃や#13のまほうでエフェクトを出すので、最初からカメラに映す設定にしておきます
  • Match:0.5
    • 画面の縦横比が1920×1080と違うとき、幅と高さのどちらに合わせるか。0.5は「両方の間」で、PCのいろいろなウインドの大きさでもはみ出しにくい

キャラクターをSpriteRendererではなくUIのImageで並べるのは、ウインドやメッセージと同じ「Canvasの座標」で位置を決められるからです。コマンドで選んだキャラクターに印を付けたり、ダメージの数字を頭の上に出したりするときに、座標の変換をしなくて済みます。

画面を場所ごとに分けよう

いよいよレイアウトです。最終的なHierarchyは次の形になります。

  • Canvas
    • Background(書庫の背景)
    • Stage(味方と敵が並ぶ場所)
      • PartyArea
        • Fairy
        • Slime
        • Jiangshi
      • EnemyArea
        • SpilledInk
    • MessageWindow
      • MessageText
    • CommandWindow
    • StatusWindow
Canvasの下にBackground・Stage(PartyArea>Fairy・Slime・Jiangshi、EnemyArea>SpilledInk)・MessageWindow(MessageText)・CommandWindow・StatusWindowが並ぶHierarchy

Hierarchyで下にあるものほど、画面では手前に描かれます。背景を一番上、ウインドを一番下にしておくと、キャラクターが動いてもメッセージやコマンドが隠れません。

背景とStage

Canvasの子に、次のものを作ります。アンカーは、Rect Transformの左上の四角いボタンで選び、そのあと位置と大きさの数字を入れます。

  • Background(UI (Canvas)>Image)
    • アンカー:stretch-stretch、Left・Top・Right・Bottom:0(画面いっぱいに広がる)
    • Source Image:bg_library_b1
  • Stage(Create Empty)
    • アンカー:stretch-stretch、Left・Top・Right・Bottom:0
    • 中身が無い入れ物ですが、#8で攻撃が当たったときにStageごと揺らして、画面が揺れたように見せるために分けておきます
  • Stageの子にPartyArea(Create Empty)
    • アンカー:middle-left、Pos X:440、Pos Y:60、Width:600、Height:560
  • Stageの子にEnemyArea(Create Empty)
    • アンカー:middle-right、Pos X:-560、Pos Y:60、Width:900、Height:560

アンカーを「左」「右」にしておくと、画面の横幅が変わっても、味方は左、敵は右にくっついたままになります。

3つのウインド

ウインドは、ui_windowをSlicedで伸ばして作ります。3つとも、Canvasの子にUI (Canvas)>Imageで作り、Source Imageにui_window、Image TypeをSlicedにします。

名前アンカーPos XPos YWidthHeight
MessageWindowtop-stretch(Left・Right:60)--100-120
CommandWindowbottom-left250150420260
StatusWindowbottom-stretch(Left:480、Right:60)-150-260
  • MessageWindowの子にText – TextMeshProで「MessageText」を作る
    • アンカー:stretch-stretch、Left・Right:40、Top・Bottom:0
    • テキスト:「こぼれたインクが あらわれた!」、Font Size:44、Alignment:左寄せ・上下中央、Color:白
MessageWindowのRect Transformはtop-stretch、Left・Right 60、Pos Y -100、Height 120。ImageのSource Imageがui_window、Image TypeがSliced

Image TypeがSimpleのままだと、四角い枠がまるごと引き伸ばされて、白いふちが太くなったり、角がつぶれたりします。枠の絵を伸ばすときは、Sprite EditorのBorderとImage Type:Slicedをセットで使いましょう。

仲間と敵を並べよう

PartyAreaの子に、3人をUI (Canvas)>Imageで作ります。横から見たRPGらしく、奥の人ほど左上にずらして斜めに並べます。

名前Pos XPos YSource Image
Fairy-190140fairy_walk_61
Slime00slime_walk_61
Jiangshi190-140jiangshi_walk_61
  • 3人とも アンカー:middle-center、Width・Height:340、Preserve Aspectにチェック(絵の縦横比を保つ)
  • Hierarchyでは、奥のFairyを上、手前のJiangshiを下にする(手前の人が上に重なるように)

EnemyAreaの子に、敵を1体置きます。

  • SpilledInk(UI (Canvas)>Image)
    • アンカー:middle-center、Pos X・Pos Y:0、Width・Height:380
    • Source Image:enemy_spilled_ink、Preserve Aspectにチェック
書庫の背景の左に3人が斜めに並び、右にこぼれたインク、上にメッセージのウインド、左下と右下に空のウインドがある

その場で弾ませよう

このままだと止まった絵のままなので、待機のコマを切り替えて、その場で弾むようにします。

  • TurnBasedRpg/Scriptsに「IdleBounce」スクリプトを作る
using UnityEngine;
using UnityEngine.UI;

// 待機のコマを 1→2→3→2 の順に切り替えて、その場で弾ませる
public class IdleBounce : MonoBehaviour
{
    [SerializeField] private Image image;
    [SerializeField] private Sprite[] frames;            // walk_61・walk_62・walk_63
    [SerializeField] private float frameSeconds = 0.15f; // 1コマを出しておく時間

    // 3枚を 1→2→3→2 の順に使う(2枚目を折り返しに使うと、なめらかにつながる)
    private static readonly int[] frameOrder = { 0, 1, 2, 1 };

    private float timer;
    private int orderIndex;

    private void Start()
    {
        // 3人が同じタイミングで弾まないように、始めるコマをずらす
        orderIndex = Random.Range(0, frameOrder.Length);
        image.sprite = frames[frameOrder[orderIndex]];
    }

    private void Update()
    {
        timer += Time.deltaTime;
        if (timer < frameSeconds)
        {
            return;
        }

        timer -= frameSeconds;
        orderIndex = (orderIndex + 1) % frameOrder.Length;
        image.sprite = frames[frameOrder[orderIndex]];
    }
}
  • frameOrder
    • 3枚の絵を「何番目の順に使うか」の表。1→2→3→2→1→2→3・・・とくり返す
    • 1→2→3→1だと、3から1にいきなり戻るので動きがカクッとなる。2枚目を折り返しに使うとなめらかになります
  • Start
    • 3人が同じコマから始めると、そろって弾んで、ちょっと不自然に見える。始めるコマをランダムにずらしておく
  • timer
    • 経過時間をためて、frameSeconds(0.15秒)をこえたら次のコマにする
    • timer = 0ではなくtimer -= frameSecondsにしているのは、こえた分を次に持ち越して、コマの長さをそろえるため
  • %(あまり)
    • (orderIndex + 1) % 4は、0→1→2→3→0とくり返す。表の最後まで行ったら最初に戻る

スクリプトを付けて、Inspectorで設定します。3人とも同じ手順です。

  • IdleBounceを、HierarchyのSlimeにドラッグ&ドロップ
  • Image:Slime(自分自身)をドラッグ
  • Frames:ProjectウインドでSlimeフォルダのslime_walk_61〜63を選んで、InspectorのFramesの文字の上にドラッグ&ドロップ
    • 61・62・63の順に並んでいるかを確認
  • FairyとJiangshiにも、それぞれの絵で同じように設定する
SlimeのImageのSource Imageがslime_walk_61でPreserve Aspectにチェック。Idle BounceのImageにSlime、Framesに3枚、Frame Secondsが0.15

ゲームの中身に関わる乱数(ダメージのばらつきや敵の行動)は、#7で作る「GameRandom」に1か所でまとめて、同じ結果を再現できるようにします。今回のコマのずらし方は見た目だけのゆらぎなので、UnityのRandom.RangeのままでOKです。

動かして確認!

再生して、3人がばらばらのタイミングで弾めば成功です!

再生すると、3人がその場でばらばらのタイミングで弾む

続けて、画面の比率を変えてもくずれないか確かめておきましょう。

  • Gameビューの解像度のドロップダウンで、16:10 Aspectに切り替えてみる
左がFull HD(16:9)、右が16:10のGameビュー。どちらも味方が左、敵が右、ウインドが上と下にあり、部品が重なっていない

#1の動作確認

  • 3人が、その場でなめらかに弾んでいる(そろって弾まない)
  • 味方が左、敵が右、メッセージが上、コマンドとステータスのウインドが下にある
  • ウインドの白いふちが、どれも同じ太さで、角が丸いまま
  • 16:10にしても、部品同士が重ならない
  • 「こぼれたインクが あらわれた!」の日本語が表示されている
スライム

ウインドが空っぽなので、まだちょっとさみしいですね・・・

フェアリー

#3でHPとMPのゲージ、#4でコマンドを入れていくよ!もうRPGの画面っぽくなってきたでしょ?

あとがき

今回はプロジェクトを作って、サイドビューのバトル画面のレイアウトを決めました。まだ戦えませんが、書庫の中で3人がぷるぷるしているだけでも、RPGが始まりそうな気がしてきますね。次回は、キャラクターと敵の名前やHP・攻撃力などを入れておく「データ」をScriptableObjectで作りたいと思います!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメント一覧 (1件)

コメントする

目次