チュートリアル: 弾のツクり方とスプライトアニメについて学ぼう!

このチュートリアルについて

このチュートリアルでは、バウンドしながら飛んでいく炎の弾をツクることを通して、
アクツクの「弾」システム
スプライトアニメーションの作り方
を解説をしていきます。

「ジャンプアクションチュートリアル」で作成したプロジェクトを使って解説をします。
アクツクの弾システムは、

  1. 弾用のオブジェクトを作成
  2. 発射元のオブジェクトに弾設定で設定
  3. 発射元のオブジェクトのビジュアルスクリプトの「弾を発射」アクションで発射
    という手順で設定することができます。

Part1: 弾用のオブジェクトをツクってみよう!

まずは、弾用のオブジェクトをつくっていきます、今回は、テンプレート形式ではない画像でのアニメの作り方と、判定アニメ機能の使い方を説明します。

Part1-1: テンプレートを使わないスプライトアニメの作り方

スプライトアニメとは、いわゆるパラパラ漫画のようなもので、画像を順番に表示することでアニメーションをさせる機能です。前回はテンプレート形式で一気に読み込みましたが、今回は1コマ1コマを選択して作る方法を学びましょう。

  1. 弾用の画像を用意します。「素材管理」ビューで「公式素材をインポート」します。
  2. 「武器」にあるP_002_fire.pngを選択して「インポート」しましょう。
  3. 「オブジェクト」ビューの左辺、オブジェクト一覧で「+新規作成」します。
  4. オブジェクト名: 炎弾
    オブジェクトグループ: Player_Bullet
    コリジョンの役割:プレイヤーの弾
    と設定し、下欄で「弾(基本)」を選択して「作成」します。
  5. スプライトアニメタブに切り替え、「スプライトアニメを使う」ボタンを押します。
  6. 右上の「シートから追加」ボタンを押します。
  7. アニメーションの追加ウィンドウで、「追加」を押します。
  8. 移動と名付けて「OK」を押しましょう。
  9. シートからフレームを追加というウィンドウが開くので、「画像一覧から…」ボタンを押します。
  10. 先ほど追加した、「P_002_fire.png」を選んで「決定」します。
  11. 画像が追加されますが、少し小さいので拡大しましょう、「表示倍率」のプルダウンで800%に変更します。
  12. 続いて、この画像は4コマの画像ですが、1コマになってしまっているので分割しましょう、水平コマ数を「4」にします。画像に縦線が入り4コマになりました。
  13. 続いて、判定のサイズを1コマのサイズに合わせましょう。「初期判定調整」ボタンを押します。
  14. 壁判定、攻撃判定ともに大きすぎるようです。調整していきましょう。
  15. 壁判定のハンドルを動かして調整します、幅8、高さ12くらいに調整しましょう。(プレビューの拡縮はマウスのホイールでできます。)
  16. 攻撃判定に切り替えて調整します、攻撃判定は一回り大きく、幅12、高さ16くらいにしておきましょう。できたら「確定」します。
  17. 最後に、フレームを追加します。クリックした順に読み込まれるようになるので、左のコマから順番に1,2,3,4とクリックしていき、できたら「追加」します。
  18. これでアニメが追加できました、下の「フレーム」欄に先ほどの画像が4つ表示されていれば成功です。
  19. ウィンドウの左上にある[:play_button:]ボタンを押してみましょう、アニメーションがプレビューでき、キラキラと炎弾が輝くアニメが入ったことがわかります。

Part1-2: 判定アニメで画像を回転させよう!

  1. タブを判定アニメに変更します。
  2. 判定アニメは、各コマごとに判定や画像の位置やサイズ、回転状態などを設定することができる機能です。ここで、「オブジェクト画像」を回転させるように設定します。
    まずは「要素(一部非表示)」欄でオブジェクト画像を選択します。
  3. 一番下の移動(4フレーム)欄にある5つのコマから、ENDを選択します。
なんでアニメは4コマしかないのに5コマ目にENDがあるのか?

シンプルアニメ機能は、「それぞれのコマの再生開始時点」の位置にキー(状態)を設定する機能です。4コマのままでは、4コマ目の最後の状態=ループ終了時の状態を設定できないため、ENDコマが判定アニメのみ自動で追加されるようになっています。

  1. 右側のインスペクターの、Node2D>トランスフォームにある、「回転」の値を360としましょう。これで、アニメの再生終わり時点の「回転」の値(これをキーといいます)が設定されました。1コマ目のキーは作成時の状態=0度が自動設定されており、間のコマのキーは自動で補間されるので設定はこれだけで完了です。
  2. ウィンドウの左上にある再生ボタンをクリックしてみてください、くるくると画像が回転するはずです。うまくいかないときは、きちんとENDのコマを360度にしているかチェックしてください、切り替え忘れで1コマ目を360度にしていたりするかもしれません。
再生が終わるとENDのコマの回転が359.9になっているのはなぜか?

表示上のみの問題です。ループ再生が有効な場合、再生を行うと360度の状態=本当のENDの状態では0秒地点に自動で戻ってしまいます、なので戻る直前の状態で表示されますが、ENDには正しく360の値が設定されているので問題はありません。

Part1-3: 移動速度と重力の設定を変えよう!

さて、次は弾として正しい動きにかえましょう、移動速度をプレイヤーより早く、そしてバウンドなので重力の影響を受けるようにする必要があります。(普通の弾は重力の影響を受けないので、テンプレートでは重力を無効にしています。)

  1. プレビュータブに切り替えて、要素一覧で「移動とジャンプ」を選択します。

  2. 右側のインスペクターの、移動速度を設定で
    左右の移動量:500
    上下の移動量:500としましょう。

  3. その少し下、ジャンプの設定にある重力の値が0になっていますので、
    重力5.0
    にしましょう。重力の既定値は1.0なので、通常の5倍の重力をこの弾に掛けます。通常の重力ではふわっとした動きになるので、あえて強い重力をかけることでキビキビした動きになるようにします。

  4. これでオブジェクトの設定は完了です、念の為「保存」しておきましょう。

Part2: 弾のヴィジュアルスクリプトを設定しよう!

続いて、弾にヴィジュアルスクリプトを設定します。

  1. ヴィジュアルスクリプトを編集を押します。
  2. ヴィジュアルスクリプトを作成ボタンを押します。
  3. ステート001を以下のように変更します。
    割り当てるアニメーション>アニメーションカテゴリ名:移動
    タイトル:移動
  4. 「移動」ステートに「+実行アクションの追加」をします。
    左枠では移動>テンプレート移動の設定
    右枠ではテンプレート移動タイプをバウンド、重力の落下でも跳ね返るのチェックをオン
    と設定しましょう。バウンドは衝突可能なものにあたった際にバウンドするという移動で、これで地面にあたったときに跳ねるようになります。
テンプレート移動アクションについて

「テンプレート移動」は一度実行すると、別のテンプレート移動で「停止」を命じられるまで指定の移動を続けるアクションです。つまり、複数のステートをまたいでも同じ動きを続けるため、単純な移動しか行わないオブジェクトでは便利な機能です。「エネミー」の左右移動もこれでつくられています。

  1. 続いて、敵にあたったときに消える設定をつくります。新しいステートを近くにつくり、名前を消滅に変えて「+実行アクションの追加」をしましょう。
  2. 消滅/復活の「自身を消滅させる」を追加します。
  3. 最後にリンクを設定します、「移動」ステートから「消滅」ステートにリンクをつなぎ、「+その他条件の追加」をします。
  4. 左枠ではオブジェクト操作>オブジェクトの当たり判定と接触
    右枠では、オブジェクトからみた接触方向を全方向有効化し、対象となるオブジェクトの種類をグループ、対象となるオブジェクトグループを「Enemy」として追加しましょう。
  5. これで敵にあたれば消えるようになりましたが、このままでは敵に当たらない限り弾が消えません。壁判定に横からぶつかったら消えるようにしましょう。もう一度「+その他条件の追加」をします。
  6. 左枠では「衝突可能なものと接触」右枠では、
    このオブジェクトからみた接触方向:左、上、右(!!下以外です、下もいれると地面でバウンドせず消えてしまいます。!!)
    前の条件との論理条件:「OR」
    ここは間違えやすいので注意して見てから追加してください。
  7. 衝突可能なものと接触を見て、アイコンが正しく「OR」になっていればOKです。これで弾側の設定が完了しました。

Part3: プレイヤー側で弾の発射を設定しよう!

続いて、プレイヤー側で弾の設定を行います。
手順は「弾」設定で弾データに「炎弾」を登録。「弾を発射」アクションを追加、の2段階です。

Part3-1: 「弾」設定をしよう!

  1. オブジェクトビューに戻り、オブジェクトを「プレイヤー」に切り替えます。
  2. 左上にある「+設定を追加」しましょう。
  3. 設定を追加ウィンドウで、オブジェクト利用にある「弾」を追加します。
  4. 右側のインスペクターを見て、弾の一覧にある「Array[BulletData]」をクリックして展開し、続けて出てくる「BulletData」をクリックして展開します。
  5. 基本設定を展開します、まずは弾の名前を炎弾として、弾オブジェクトを指定の「一覧」ボタンから「炎弾」を追加します。
  6. 続けて、基本設定の「制限無し」をオンにしましょう(ここがオフだと、シーン内に炎弾があると発射できなくなります)、基本設定が画像のようになっていればOKです。
  7. 次は「弾の飛び方(初期動作)」を展開し、「発射元オブジェクトの表示方向」と設定しましょう。
  8. これで弾データ側の設定はOKです、「炎弾」を、「発射元オブジェクトの表示方向」に、「シーン内にいくつ炎弾があっても」発射する。というデータをつくることができました。

Part3-2:「弾を発射」アクションを設定しよう!

  1. 「ヴィジュアルスクリプトを編集」に入り、「移動」ステートの近くに新しいステートを作り、アニメーションカテゴリ名には「shoot」を設定し、「地上発射」と名付けましょう。

  2. 「+実行アクションの追加」をしましょう。左枠は「攻撃/弾」の「弾を発射」、右枠は弾データ「炎弾」を選んで「追加」します。もし炎弾がないときは正しくプレイヤーの「弾」設定に炎弾が設定されているかチェックしてください。

  3. アクション側は設定完了なのでリンクを作ります。「移動」ステートから「地上発射」にリンクを追加し、「以下の入力がなされた」にチェックを入れ、「+入力を追加」します。

  4. 左枠を入力に使う操作キー、右枠を入力キー: B、入力の条件: 押された瞬間として「追加」しましょう。

  5. このままでは移動中しか炎弾しか打てないので、待機からもつなぎます。内容は全く一緒なので、「移動」→「地上発射」リンクをコピーして待機にペーストし、地上発射につなぎましょう。

  6. 最後に「地上発射」から「待機」に戻るリンクを作り、ステートを切り替える条件を「アニメーションが終了した」にしましょう、これで「shoot」アニメがおわると「待機に戻るようになります。」

  7. これで設定できましたが、線がゴチャゴチャしていると感じるかもしれません、ステートはドラッグで移動できるので、この機会に少し動かして整理をしておくとよいでしょう。(以下画像では、全体的にステートの位置を下げて地上発射を上にうごかしました。)

  8. さて、それではテストプレイをしてみましょう。うまく設定できていれば、プレイヤーの向いている方向に炎弾が出て、跳ねながら前に進むはずです。なお、「この時点では正しく設定していても、弾は消えますが敵を倒せません」。弾が出せるか、跳ねながら進むかだけをチェックしてください。

うまくいかないときのチェックリスト

・弾がでない。
「弾を発射」アクションで正しく弾データが指定されているかチェックしてください。
・弾は出るが、その後動けなくなる。
待機へ戻るリンクの設定が正しいか、地上発射ステートにshootアニメが正しく設定されているかチェックしてください。
・弾は出るが、2回目以後でない。
弾データで基本設定で「制限なし」が正しくオンになっているかチェックしてください。
・弾は出るが、バウンドしない。
移動ステートで正しくテンプレート移動:バウンドが設定されているか。
「衝突可能なものとの接触」で誤って下方向を有効にしていないか
をチェックしてください。

Part3-3: 弾でエネミーを倒せるようにしよう。

さて、この時点で正しく設定をしていても弾は敵にあたり、消えます、そして実際にダメージも入ってHPが0になっていますが、敵はダメージ動作を行いません。
これはなぜかというと、「ダメージ」ステートへの遷移条件が「player」グループとの接触だけになっており、プレイヤーの弾が属する「player_bullet」との接触が設定されていないためです。早速設定を直してみましょう。

  1. オブジェクトビューに戻り、「エネミー」を開き、「ヴィジュアルスクリプトを編集」します。ダメージステートをコピーしてペーストしましょう。

  2. ダメージ(1)というステートができるので、「炎弾ダメージ」とタイトルを変更し、設定されている「オブジェクトの速度を設定」を削除します。(速度を設定はプレイヤーを跳ね上げるアクションですので、弾で跳ね上げがおきないようにします。)

  3. walk→ダメージのリンクをコピーして、walk→炎弾ダメージのリンクとして貼り付けます。

  4. インスペクターの「オブジェクトの攻撃判定に゙接触」を開き、対象となるオブジェクトグループを「Player_Bullet」に変更しましょう。

  5. 続いて、ダメージ→Deadの条件を同じくコピーし、炎弾ダメージ→Deadのリンクとして貼り付けます。

  6. これで準備は完了です。プレイヤーの弾にあたると炎弾ダメージにリンクするようになり、hpが0になるとDeadまでつながるはずなので。テストプレイで試してみましょう。

うまくいかない時のチェックリスト

・弾が敵で止まらない
炎弾オブジェクトの「敵の当たり判定と接触」条件をチェックしてみましょう。
・弾は消えるが敵が消えない。
エネミーのwalk→炎弾ダメージのリンクと炎弾ダメージ→Deadのリンクの条件をチェックしてみましょう。

次のチュートリアルへは目次から

発展課題

さて、これで弾の出し方やアニメーションの設定方法が理解できたはずなので、チュートリアルとしてはここまで・・・ですが、ゲームとして見ると気になる点がいくつかあるはずです、その解決方法だけ記載しておくので、興味がある方はチャレンジしてみてください。

空中で弾が出せない。

地上発射のコピーでよいので、「空中発射」のステートを作り、「ジャンプ」ステートと「落下」ステートからリンクをつなぎましょう。
「空中発射」ステートからは「落下」ステートにだけリンクをつなぎましょう。
全ての設定は地上発射と同じで問題ありません。

・なぜ「ジャンプ」に戻さないのか?
ジャンプに戻すと、再びジャンプしてしまうからです。

・なぜ「地上発射」と「空中発射」にわけるのか?
戻り先をわけるためです。空中発射から「待機」に戻してしまうと、空中発射後に空中でジャンプできるようになってしまいます。

敵のHPを増やすと敵の動作がおかしくなる。

今の作りはダメージを受けた後、walkステートに戻ることができません。(HPが1しかないことが前提の作りになっているからです)
「ダメージ」、「炎弾ダメージ」からwalkに戻るリンクを用意しましょう。
そのリンクでは、その他条件として「変数・スイッチが変わった」HP>0としておけばHPが0より大きければwalkに戻り、HPが0であればdeadに移る、という設定にできます。

なお、せっかくステートをわけているので、新しい公式パーティクル(例えばexplode)を読み込み、炎弾ダメージのステートで「パーティクルを表示」すれば、炎弾を受けたときだけ違うパーティクルを出すことができます。