(この記事の使用環境: Unity5.6.1f1 Personal、Windows10


今回は教材レビューです。やってみたのはこの本。
普通の紙の本もKindle版もあります。自分はKindle版を買いました。



■ 内容紹介(Amazon.co.jpより抜粋)
Unity 2Dを徹底的に極めるノウハウ満載!

プロのプランナー・プログラマが知っている、本格2Dゲーム制作のテクニックを詳細に解説。Unity 2Dのツールとしての使い方から、キャラ管理やカメラ設定、エフェクト、レベルデザイン調整など、すべてのノウハウを満載。

●目次
Chapter1 Unityの準備
Chapter2 Unity 2D入門
Chapter3 Unity 2Dを利用した3種類のプログラミングスタイル
Chapter4 Unity 2Dでゲームを作るための企画・設計をする
Chapter5 MecanimとPyhsics 2Dでプレイヤーキャラを作る
Chapter6 トリガー処理とアニメーションイベントで攻撃アクションを作る
Chapter7 MecanimとPhysics 2Dで敵キャラを作る
Chapter8 スクリプトで敵キャラの管理システムを作る
Chapter9 複数のカメラを利用してカメラとHUDを作る
Chapter10 エフェクトを作る
Chapter11 Sceneビューを活用してレベルデザインする
Chapter12 バーチャルパッドを作ろう
Chapter13 BGMとSEをつける
Chapter14 ゲームを完成させる

■ 感想
2Dのスラッシュアクションゲームを作るのに必要となる技術要素と、それらをうまく扱うノウハウについて、かなりの量を学ぶことができます。紙の本の厚さで688ページ!

キャラクター操作だけでなく、カメラやパーティクルを使った演出まで、本当に幅広く学べます。配置されたオブジェクトに影をつけることで奥行を表現したり、プレイヤーの動きを追従する残像を付けたり、面白い演出が学べました。

スクリプトの書き方も勉強になります。処理負荷軽減と難易度調整のためカメラ外やプレイヤーから一定距離外の敵キャラを動かさないようにしたり同時に行動可能な敵の数を制限したりする処理や、敵にやられたり穴に落ちてしまって中間ポイントからリスタートするときの処理など、大変参考になりました。

著者によるエディタ拡張スクリプトやTweenスクリプトなど、応用レベル(?)の内容も紹介されています。それらを使うことでHierarchyビューで選択していないオブジェクトのコライダーもSceneビューに表示できたり(位置合わせなどの際に重宝)、オブジェクトを簡単にアニメーションさせることができたりします。

なお、ボリュームの多さは著者のサービス精神の現れだと思うのですが、その一方で、最初から最後まで通して消化しようとするとかなりのエネルギーを必要とするように思います。自分はスプライトをシーンに配置してステージを作っていく作業の繰り返しで心を折られてしまいました。紙面の制約もあったと思うのですが、設定値などの説明が省略されている箇所も多いため、自力ですべて消化するのは多くの人にとって困難かと思います。完成プロジェクトをダウンロードできるので、適宜そちらを参考にするとよいでしょう。また、2014年に出版された書籍なので、さすがに現行バージョンのUnityでは、そのままでは動かない箇所等があります。そのため、この本をUnityを学ぶ1冊目の教材とするのはおすすめしません。Unity入門者であれば、まずはもっと新しい教本で学ぶことをおすすめします。少し自信がついてからこの本に着手するのはアリかと思います。

この本に着手される方は、以下に記す留意点や誤記情報を参考にしてください。途中までしか消化できていないのですが・・・そこまでは自分なりに丁寧に進めたつもりです。教材を進めるうえでの助けになると思います。


■ 留意点
  • 対象としているUnityのバージョンが古い(ver4.5?)ため、設定項目名が異なっていたり、スクリプトの書き方を変える必要のある個所がある。そのため、この本を1冊目の教材とするのは苦労しそう。Unityの入門者であれば、まずはもっと新しい教本で学びましょう。そのあとで戻ってきてもよいので。
  • 変数名などが微妙に省略名称になっているなど、なんのために使用するものなのか分かりにくい。かなり多くの変数やメソッドを作成し使用するので、適宜自分でXMLドキュメントコメントを追記して、VisualStudio等から説明を参照できるようにしておくとよいと思います。
  • (特に後半で扱うオブジェクトの種類が増えてきたとき)Kindle版のみの問題かもしれないが、図を参考に設定しようとしても小さくてとても読み取りにくいことがある。かなり拡大しても、解像度もあるので限界がある。少々推測しながら進める場面がある。
  • 具体的な設定値等が記載されていないところがある(また、単純な誤記もある)。特に後半になると目立つかも。とても複雑な設定もあり、自力で設定するのは非常に苦労するところもある。そのような場合は、完成プロジェクト「NinjaSlayerX」>「Assets」フォルダから必要に応じて完成しているアニメーションやプレハブをコピーして使うと良い。

    ■ 教本を進めるのにあたって、自分で工夫してみた点
    • Chapter5以降で作成する忍者ゲームで、ジャンプして着地したときにプレイヤーキャラが地面のコライダーにめり込んで身動き取れなくなる現象が(ごくたまに)発生した。PlayerオブジェクトにアタッチされているRigidbody2DのCollisionDetectionを「Descrete」から「Continuous」にすることで解決した。
    • プレイヤーキャラの(地上での)攻撃アクション時に少しずつ前進するよう、「Player_ATK_A」および「Player_ATK_B」のアニメーションクリップの編集で、開始フレームに「AddForceAnimatorVx(float)」イベントを追加してみた。これによりその場攻撃では少し前進、走り攻撃では大きく前進するようになる。これにあわせて、走り攻撃時は「Player_ATK_B」から開始するようにしてみた(抜刀する見栄えがよいため)。
    • 「9.2 HUDを作る」で紹介されているGUI表示方法はuGUI登場がする前の時代の手法のようなので、自分は画面イメージとスクリプトを参考にしつつ、uGUIで実装してみた。

    ■ 誤記、バージョン違い、その他気を付ける必要のある箇所等
    • 正誤情報はまず出版社の情報を見ましょう。http://www.sbcr.jp/support/12227.html
    • (全体) 現行バージョンのAnimatorの遷移条件には「Atomic」という設定項目はない。「Atomic : オン」を「Has Exit Time : オフ, Transition Duration = 0」と読み替えて対応した。(以降同様)
    • P.30 背景のゲームオブジェクトに設定するのは「Sprite_back」ではなく「Stage_back」。
    • P.38 Tank.csで、現在のUnityバージョンでは変数 rigidbody2Dを初期化なしに使用することはできない。ここでは「rigidbody2D」の箇所を「GetComponent<Rigidbody2D>()」と書き換えればよい。(以降同様)
    • P.93- 「3.4」で作成するサンプルで、「3.3」から継続して設定を行う場合、「Player」オブジェクトのRigidbody2DのGravityScaleが「0」のままになっているため、ジャンプしたら上昇し続けて画面外に消えてしまう。GravityScaleを「1」などの値に設定する必要がある。
    • P.143 記載されているとおり「さらに小さな円のコライダーを足元に作成」したが、地面のコライダーの継ぎ目にひっかかる現象は改善されなかった。(上記P.94での対応と同様の対応により解決した。小さいほうの円コライダーは無効にした)
    • P.94 (不明点) 「ステージのアタリ判定の設定」で、複数ある「StageA_Road_A」オブジェクト1つにつき1つずつコライダーを設定すると、オブジェクト間の境界でプレイヤーキャラがひっかかることがあった。(回避策の一例として)複数のコライダーを並べて設置するのではなく、1つの「StageA_Road_A」オブジェクトにステージ全体にわたる大きなコライダーを設置すればよい。
    • P.106 (バージョン差異) 現バージョンのRigidbody2Dのインスペクターには「Fixed Angle」という項目はない。代わりに「Constraints」>「Freeze Rotation」>「Z」にチェックを入れればよい。(以降同様)
    • P.134 表4.1.4内の説明文、「○○をTranslateで返す」は「○○をTrasnformで返す」が正(すべて) 。
    • P.139 「Sprites」>「Player」内のすべてのスプライトに対して、PivotをBottomに変更してApplyしておく必要あり。(図を見て「Player_Idle1」の設定をするだけでは足りないので注意)
      なお、その後出てくる敵キャラクターのスプライトについても同様で、すべてPivotをBottomに変更してApplyしておく必要がある。
    • P.157- BaseCharacterController.cs のコードで、void Awake() 内に「gravityScale = rigidBody2D.gravityScale;」とあるが、これは左辺と右辺が逆で、「rigidBody2D.gravityScale = gravityScale;」が正しいはず。
    • P.189- 「攻撃アタリ判定のアニメーション」で、説明内容からすると Animationで切り替えるのはコライダーの「IsTrigger」ではなくて「Enabled」が正。
    • P.215 図6.3.8のAnimatorControllerで、「Player_ATK_C」から次の攻撃へのTransitionがない(PlayerController.cs には 「Player_ATK_C」のときに攻撃トリガーをセットするよう記述されている)。打ち上げ攻撃からの遷移なので、空中での打ち下ろしモーションである「Player_ATKJUMP_B」へのTransitionを付けるのが良さそう。遷移条件は「Conditions」に「Attack_A」、HasExitTime:オフ, TransitionDuration=0 にした。
    • P.220 下から2行目、Collider_AttackゲームオブジェクトのTagは「EnemyBody」ではなく「EnemyArm」が正(本文が誤りで、図は正しい)。
    • P.223 図7.1.1「EnemyA_ATK_A」のアニメーション作成で、パラメーター「EnemySprite:SpriteRenderer.Color」が追加されているが、設定する内容についての記載がない(かつ紙面もモノクロなので色の変化は分からない)。→ 最初のキーフレームから次のキーフレームに移る間、Linearで徐々に白から紫色に変化させるよう設定することで、テークバックモーションまでの間、敵が攻撃準備中であることが視認できるようにしてみた。
    • P.225 ここでAnimatorControllerに設定する各種パラメーターはすべてTrigger型とすればよい。(Unity4.x のAnimatorControllerのパラメーター設定画面では、Bool型とTrigger型がともにチェックボックスで表示されるため、説明がないと分からない)
    • P.233 コード内に「// Memo: 空中ダメージではx移動を禁止」というコメントがあるが、その下の if 文では空中ダメージである「ANISTS_DMG_B」だけでなく、通常ダメージの「ANISTS_DMG_A」も条件に含めているため、空中ダメージに限らず敵キャラ被ダメージ時はX移動禁止となる。通常ダメージではX移動を禁止しないのであれば if文中の「ANISTS_DMG_A」の条件を削除すべきでは?
    • P.254 誤記ではないが、AnimationController「EnemyBAnimController」は「EnemyAAnimController」を複製したものをリネームし編集したほうが効率が良い。
    • P.254 説明はないが、EnemyB_Basの下のEnemySpriteについて、位置合わせのために TransformのPosition.Xを -0.5 程度にしておくのがよい。
    • P.264 説明はないが、EnemyC_Basの下のEnemySpriteについて、位置合わせのために TransformのPosition.Xを -0.2 程度にしておくのがよい。
    • P.266 説明はないが、EnemyC_DMG_A、EnemyC_DMG_B、EnemyC_Deadの各アニメーションも作る必要がある。
    • P.273 手裏剣のFireBulletのインスペクターで、「Hit Sprite」に「Effect_Hit2_1」をセットする必要がある。
    • P.277 図7.3.16「手裏剣の設定」で、EnemyC_Bas > EnemyController > FireObjectListにHierarchyビュー上のEnemy_Shuriken_Basオブジェクトを指定しているが、Enemy_Shuriken_BasオブジェクトをPrefab化したものを指定するようにし、Hierarchyビュー上のEnemy_Shuriken_Basオブジェクトは削除したほうが良い。(10ページほど後に説明あり)
    • P.303 (バージョン差異) PlayerController.csのコード内「boxCol2D.center」(BoxCollider2D.center)は旧型式のためエラーとなる。→ 「boxCol2D.offset」に置き換える。
    • P.330 (バージョン差異) 変数「camera」は旧型式のためエラーとなる。→ Camera camera変数を作り、GetComponent<Camera>(); しておく。
    • P.373 (バージョン差異) 現行バージョンのUnityでは、ParticleSystemのインスペクターからSortingLayerの指定ができる(ParticleSystem>Renderer>SortingLayer)。インスペクターで設定を行えば、コード10.3.1「Unity2DSortingLayer.cs」を作成する必要はない。
    • P.383- コード10.4.1「zFoxTween.cs」内で、「zTWEEN_VALUE」に「LOCALPOSITION(_x,y,z)」が指定されたときの処理が記述されていない。また、「zTWEEN_OUT」に「ADD」が指定されたときの処理も記述されていない。エラーにはならないが、何も処理されない。後者は特にTweenItemのデフォルト値でもあるので注意が必要。
    • P.406 コード11.1.2「PlayerBodyCollider.cs」内に「playerCtrl.superMode = true;」という行があるが、本を読み進める中で PlaerController.cs内にsuperModeというパラメーターを追記するよう説明されている箇所がない(はず)。また、superModeが利用される箇所についても説明がない(はず)。完成プロジェクトを参照し、以下の2箇所を追記する必要がある。
      (1)
      PlayerController.csに以下の行を追記(外部パラメーター宣言部)
        [NonSerialized] public bool superMode = false;
      (2)
      EnemyController.csに以下の行を追記( 追記する場所は 「if (SetHP(hp - damage,hpMax)) {」 の前の行)
              damage *= (playerCtrl.superMode ? 5 : 1);
    • P.427 「背景を作る」で、「StageA_MainCamera」の「Orthographic Enabled」をオフにするよう指示があるが、それにあわせて、カメラ視点の変更用に作成したトリガーオブジェクト「CameraTriggerH」および「CameraTriggerV」の「Orthographic Enabled」がオンになっている場合はオフにしておく必要がある(Prefabで設定変更すればよい)。また、そこまでの工程でシーン上に配置したオブジェクトのZ座標がバラバラだと、「Orthographic Enabled」をオフにした途端画面表示が崩れるので注意。Hierarchyビューで配置済みのオブジェクトをチェックし、適宜Z座標を0に修正すればよい。
    • P431 図11.1.73「背景カラーの作成」で「StageA_BackColor」オブジェクトにアタッチするLineRendererだが、マテリアルを1つ指定しないと描画されなかった。マテリアルを作成し、シェーダーに「GUI/TextShader」をしたものをLineRendererのマテリアルに指定することで描画できた。(※ 該当ページの図ではインスペクターのMaterialsの欄が折りたたまれているが、サンプルプログラムを参照したところ、マテリアルが指定してあった・・・)
    • P.432 コード11.1.6「StageA_TimeEffect.cs」内に「float t = player.transform.position.x / 380.0f;」とあるが、この「380.0f」はこのステージのゴールのX座標を示している。自分で教本に沿ってステージ作成した場合、この値とはゴール座標が異なると考えられるので、たとえば「public Transform goalPos;」というように変数を定義してインスペクターからゴール位置にあるオブジェクトを指定するようにし、該当コード箇所では「poalPos.position.x」というように指定するのが良さそう。
    • P.444 表11.2.3「地形スプライトのタグ・レイヤー・ソーティングレイヤー・オーダーインレイヤー」の一番下の行にある「StageB_RoadUnder_R」というスプライト(およびゲームオブジェクト)は存在しない(無視してよい)。
    • P.446 表11.2.4「地形スプライトのタグ・レイヤー・ソーティングレイヤー・オーダーインレイヤー」にある、「StageB_BackWall_B」は存在しない。代わりに?「StageB_BackWall_R」・「Stage_BackWall_RT」というファイルがあるので、それらのLayerを「StageBack」にしておく。また、「Stage_BackWall_Roof」も存在しないが、「StageB_Roof」に読み替えて設定を行う。
    • P.446 (バージョン差異含む) 下から2つ目の段落のテクスチャーインポーターの設定で、「TextureTypeを『Advanced 』に、WrapModeを『Repeat 』にして」とあるが、現行バージョンのUnityではTextureTypeを変更する必要はない(「Sprite(2D and UI)」のままでよい。その状態でインスペクターに「Advanced」の欄が表示されているため)。「WarpMode」も素材インポート時点で「Repeat」に設定されていたため変更の必要はなかった。
      また、次ページに続く文で、「このとき、Tilingのxとyが1にリセットされますが」とあるが、現行バージョンのUnityではxとyは3のまま保持されていた(Unityバージョンアップによるバグ解消?)。
    • P.451 (バージョン差異) コード11.2.1「StageTrigger_Link.cs」で、「Application.loadedLevelName」および「Application.LoadLevel」を使う箇所があるが、VisualStudioに旧型式である旨のメッセージが表示される。エラーにはならない。
      → 気になる場合は、スクリプトのアタマで「using UnityEngine.SceneManagement;」を追記した上で、「Application.loadedLevelName」は「SceneManager.GetActiveScene().name」に、「Application.LoadLevel」は「SceneManager.LoadScene」に置き換えればよい。
    • P.452 コード11.2.2「StageTrigger_CheckPoint.cs」も同上。
    • P.453 コード11.2.4「PlayerController.cs」の(太字になっていないほうの)「// パラメータ初期化」の箇所には「 SetHP ( initHpMax, initHpMax );」という行があったが、これは削除しておく必要がある。(p.454のif文の中に移動しているということだろうが、分かりにくいので注意)
    • P.455 作成するプレハブ「StageLinkJumpV」および「StageLinkJumpH」にはタグ「EventTrigger」を設定しておく必要がある。P.456で作成する「StageLinkMark」も同様。
    • P.455 シーン間を移動するためには、UnityEditorのメニューから「File」>「BuildSettings...」を選択し、「Scenes In Build」の欄に「StageA」と「StageB」のシーンを追加しておく必要がある(追加しておかないとエラーになる)。
    • P.457 本文中には説明がないが、「StageB_ExitA」オブジェクトについては図11.2.30のとおりタグを「EventTrigger」に設定し、BoxCollider2Dを追加しておく必要がある(Is Triggerにチェックしておく)。Layerも「StageBack」にしておくとよい。
    • P.459 図.11.2.32「壊れない箱の作成」で、使用するスプライトの名称は「StageA_Block_C*」ではなく、「Stage_Block_C*」が正しい。また、使用するスプライト(5個)のSortingLayerおよびOrderInLayerは作成済みの他のブロックのプレハブ(BlockA または BlockB)を参考にして同じように設定しておく。
    • P.461 シーン「StageB_Puzzle_A2」において、そのままでは左右の箱(BlockA)とあわせて3つのブロックオブジェクトを一緒に押せてしまうため、期待するパズルゲームにならない。それぞれのブロックオブジェクトのコライダーにPhysicsMaterial2D(Frictionを1000以上の適当な値にする)をセットすることで、期待どおり左右のブロックを壊さない限りブロックを押せないようにできる。
    • P.480 図11.3.15「最初の物理パズルステージ(StageB_Puzzle_B1)の作成」で、右側の「StageB_ExitA」オブジェクトの「JumpSceneName」に設定する値は「StageB_Puzzle_A2」ではなく「StageB_Puzzle_C1」が正しい(サンプルプロジェクトにて確認した)。

    今回は以上です。

    (管理情報: プロジェクト MyProjects\TEXTBOOK\Unity2DTetteiGuide)