Unity初心者が2 d sprite使ってゲームを作ってみた【後半戦】

Preview:

DESCRIPTION

Unity初心者が、Unity4.3から搭載された2D Sprite機能を使って、1本ゲームを作った時の作り方やTips、エラーの対処法などをまとめました! こちらにもUnity情報を載せていますので、合わせてご覧ください! http://i-tai.net/apps/unity/ 今回の制作で使用したソースコードはこちら http://i-tai.net/apps/ningen-tamaire/dev/ ※前半戦はこちらです!! http://www.slideshare.net/toshitakamuraishi/unity2-d-sprite-31701418

Citation preview

Unity初心者が2D Sprite使って カジュアルゲームを作ってみた!

☆後半戦☆

名前:村石 敏享(むらいしとしたか) 職業:フロントエンドエンジニア(主にFlashを触ってます) 前半戦をみていない方は、先に そちらを見てください☆ http://i-tai.net/apps/ningen-tamaire/dev/

自己紹介

・Unityに興味をお持ちになっている方 ・カジュアルゲームを作りたいけど、 どこから手をつけていいかわからない方 ・Unity経験者(仲良くなりたいです☆) ・UNITY-CHANかわいいね

このプレゼンのターゲット

前半戦で作ったもの

注:画面はハメコミ合成です

これ。

やあ。

シーンを保存

File→Save Sceneで、「GameMain」として保存します。

そうすると、Assets Viewにシーンが 保存されてるのが分かります。

シーンもプロジェクトの構成要素の1つです。

プロジェクトとシーン

Unity Project 1

Scene Image Music Script

C# Game

Object Camera

Prefab

シーン間の移動

シーン間の移動も、複数のシーンを混在させることも プログラムなどにより可能です。

Scene_01 Scene_02

Scene_03

Scene_04

Scene_05

今回のシーン構成

Title

Story

GameMain

TitleとStoryも それぞれ作って 保存します。

こんなゲームにしたい

つの○じろうさん を彷彿させる タイトル

「痛……」僕は、焼けるような痛みの中、目をさました。体がとても重い。「ここは?」あたりを見渡す。みた事のない場所だ。何より異質なのは、ここが道路のど真ん中という事だ。おかしい…。僕は昨日はちゃんとベッドに入って寝たはずだ。まさか夢遊病者になってしまったのだろうか?「うう……」所々から、うめき声が聞こえる。どうやら、ここにいるのは僕だけではないらしい。声のす

るほうの様子をみる。まだ倒れている人、よろめきながら起き上がる人。みんな、僕と同じような年齢と背格好だ。「大丈夫ですか?」僕は近くの人の所に駆け寄って、話しかけた。その人は、弱々しくかぶりを振る。着ている学ランから、僕が毎日通っている、聖マリアンヌ学園の生徒だとわかった。よくよくあたりを見渡す、すると、みんな同じ学ランを着ているらしい事が見て取れた。……何故? 何故?考えれば、考えるほど異質なこの状況に、目眩を起こしそうになり、体を小さく抱え込む。「……っ!!」そ

の時気づいた。僕も学ランを着ている事に。ちょっと待て、確か昨日はお風呂に入った後、パジャマに着替えたはずだ。急に、足下から現実がくずれ落ちていくような感覚。今までに襲った事のない恐ろしい感情が駆け巡った。やばいぞ、冷静になれ! 一度、声に出してみる。何回か、頭の中で念じた後、深く深呼吸する。時間の感覚もあやふやだ。起きてから何分、いや、何時間経ったのだろうか?ジャジャジャーンジャジャジャーンジャジャジャジャジャン♪その時、突然音楽が鳴り響いた。運動会でよく聞く、あのメロディーだ。遠くでパン…と、花火の音も聞こえる。何だ、何だとあたりがざわつく。まだ倒れてた人も、喧噪で目を覚ま

したのか、次第に起き上がってきた。「次の回に参加する方は、こちらに集まってください!」スピーカーからアナウンスが響いた。突然、ドン!と後ろから押される。せかされるように、僕も列に加わった。…というより、気づいたらその状態になっていたのだが。周りを見やると、色々な人がいる。目を血走らせている人、何かぶつぶつ呟いている人。満身創痍で歩くのがやっとの人…。ただ、どの人であっても、同じ聖マリアンヌ学園の学ランを着ているという事だけは共通していた。「あ、あの…」分からない状況を、

少しでもなんとかしたいと思い、隣に並んでいる人に声をかけた。しかし、途端に鋭い目でにらまれ、圧倒されてしまう。「ようこそ、諸君!!」野太い声が、拡声器から聞こえる。みると、一回り以上の年齢の男が立っていた。先生だろうか? しかし、学校ではみた事がない。男は、なおもしゃべり続ける。「今から“玉入れ”の競技の説明に入る。初めてじゃない者も沢山いると思うが、よく聞いてくれ」え…、玉入れ…?「この先にある、白いラインがスタートだ。そして、この先にあるゲートがゴールになるもう少ししたら

スタート合図がある、それが鳴ったら全力で走れ、以上だ!」あたりがざわざわとする。当たり前だ。玉入れと聞いているのにもかかわらず、玉や籠の説明もない。これでは、まるで徒競走の説明である。比較的冷静な人もいるが、初めてではないのだろうか?「玉と籠はどこにあるんですか?」「チーム分けはどうするんですか?」口々に質問が飛ぶ。「静粛に!」先生らしき男が、場を制した。「今の質問についてだが、一つずつ説明しようと思う。まず、この競技はチームではなく個人戦となる。そのうち協力して戦えるようにしたいという事みたいだが…そして籠、それは、あれだ!」男が上空を差した、「それ」は、とても大きく、隣の高層

ビルより、さらに上空にそびえ立っていた。とてもじゃないが、オリンピック級の選手を連れてきても玉を投げ込めるような高さではない。「ここに、どうやって玉を投げ込むんですか?」当たり前の質問が飛ぶ。その質問をうけて男が答える。「どうやら勘違いをしている者もいるようなので、ここではっきりさせておく。玉は、お前たちだ!お前たちは、そこの異界の窓に移っている、指をかいくぐり、投げられないようにゴールを目指せ」男の言葉と視線の先を見て、僕は戦慄を覚えた。「何だ…。あれは?」籠と対に

なるように、縦長に広がった異界への窓には、ゲームのストーリーらしい説明文を読む、楽しそうな巨人とその説明文を操作をしている太い指がみえた。それに…。え? 何?…何だって!? 玉は僕たちって言った?あたりが一瞬静まりかえり、大きくざわつく。「なにあれ、怖い…」「はぁ、ナニ言ってんだ?」「ふざけるのも大概にしろよな!」「うちにかえりたいよ〜」口々に動揺と罵詈雑言が飛び交いだした。あたり全部が、その空気に満たされようとしていた瞬間「この糞虫どもがっ…!!」男が放った一言は、今まで違う異質な口調で、この場が時が止まったようにしん…と、静まり返った。シュプレヒコールをあげていた者は、口を開けた

まま硬直している。男は、なおも続けた。「この世とは、不条理なものだ。いまさら、それを並べ立てることに何の意味がある?それを受け入れろ!この世の中は理不尽だらけだ。いいかっ…!君らはゆとり世代と言われて久しいが、この世の中を見渡してみ

ろ! 優劣に基づいた競争社会じゃないか。受験戦争しかり、出世競争しかり、世の中には争いや戦いがあふれている。あらぬ誤解で傷つけ、そして傷つくこともあるだろう。もしかしたら、この長い道のり、途中であきらめそうになってしまうかも知れない、立ち止まってしまうかもしれない。しかし、その時こそ、思い出してほしい!勝利とは、決してあきらめなかった者が掴むものだと!諸君らが、今まで流した汗と涙の量は、嘘をつかない。今こそ、この手で掴むときだ!私は何も難しい事は言っていない、ただ走れとだけ言ったんだ。走ればゴールにつく、だだそれだけだ!」!!!!そうだ…! 僕は間違っていた。思えば僕は今ま

での人生、何も掴もうとしてなかった。走ればゴールにつく、そんな簡単な事を僕は今の今まで見失っていたのだ。話は初めて聞いたので、今まで流した汗は、正直ない。だがしかし、ここでやらなければ、そして、勝たなければ意味がないのだ。「やるぞ!」僕も、一言呟く。体が火照りだす。急に目頭が熱くなった。何度地面に叩き付けられようとも、絶対その度に立ち上がってゴールに目指すんだ!「やるぞ…!! やるぞ!!!」僕は叫んだ。それに呼応するかのように地響きのような、うねりにも似た

叫び声がわき上がる。所々で嗚咽も聞こえる、僕も涙で前が見えなくなっていた。いったい何を言いたいのか分からない叫びとともに。走り続けよう。その道がどんなに辛く、苦しくても。そして、勝ち取ろう、勝利を。栄光に向かって走れ。どこまでも。

無駄に長い ストーリー

こんなゲームにしたい

走ってくる人を、 たくさん籠に投げ入れましょう。

こんなゲームにしたい

指でスワイプしてぐりぐり人を集めます。

こんなゲームにしたい

集めた人をフリックで 上に放り投げましょう。 籠に入ったら得点に なります。

キャラクター部分の制作 プログラムを含めた挙動を実際に作りこんでいきます。

投げられる人の作成

それらしいpng画像を用意して、画面上に表示します。

それに、 ・Rigidbody 2D(物理演算用) ・Circle Collider 2D(衝突判定用) ・Audio Source(音声再生用) をAdd Componentします。

… … … … …それらをスクリプトで制御します。

C#スクリプト「PersonController.cs」をAddします。 考え方ですが、キャラにどのような挙動をするかのステータスをを一つ用意し、プレイヤーの動作によってステータスを変更させていきます。

投げられる人の作成

ステータスはこんな感じで推移させます。 「”Walk”」…初期値、画面右に向かって移動するだけ。 「”Drag”」…指でスワイプされてる状態、指に合わせて一緒に移動する。 「”Throw”」…指を離された状態、物理法則にのっとって落ちたりぶつかったりする。

投げられる人の作成

画面の左から右に向かって移動するだけです。

“Walk”

【主なステータス】 ↓Update時にすこしずつ右にずらす transform.position += new Vector3(walkSpeed * Time.deltaTime, 0, 0); ↓重力などの外部の力に左右されない rigidbody2D.isKinematic = true;

“Drag”

指に合わせて一緒に移動します。

【主なステータス】 ↓Update時に、指の位置とキャラの位置を同じに合わせる Vector3 currentScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z); Vector3 currentPosition = Camera.main.ScreenToWorldPoint(currentScreenPoint); transform.position = currentPosition; ↓重力や衝突などを外部の力が加わるように rigidbody2D.isKinematic = false;

“Throw”

物理演算で動きを処理します。

【主なステータス】 ↓重力など外部の力に左右されるように変更 rigidbody2D.isKinematic = true;

後は、Unityさんに計算をおまかせ☆

キャラが画面外に出たときに消します。 if (transform.position.x > 10) { Destroy(this.gameObject); } if (transform.position.y < -0.5) { Destroy(this.gameObject); }

その他処理

やりたい事をプログラムにします

今回のプログラムは、ここに載せました。 ※突っ込み大歓迎です☆ http://i-tai.net/apps/ningen-tamaire/dev/

閑話休題 Unityってコンポーネント指向なんだって~。

へぇ、それって食べれるの?

Unityでは、従来のクラスを拡張したコンポーネントベースでの開発を推奨しています。Unityで使用する、どのコンポーネントも基本的には「MonoBehaviour」クラスを継承しています。…あくまで噂です。

コンポーネント指向ってなんぞ?

MonoBehaviour クラス

RigidBody 2D

Camera

Script(C#)

MonoBehaviourはよく使う、「rigidBody, Collider, audio, animation, camera」などの各コンポーネントの変数をすで

に持っています(使用する場合は、該当コンポーネントをAddしている必要があります)。

コンポーネント指向ってなんぞ?

Game Object RigidBody 2D

Camera

Transform

※お互いに知っている

まとめると…

MonoBehaviour クラス

Transform

Rigidbody

Script(C#)

Audio

Game Object

当たり前ですが、コンポーネントのプロパティはプログラムで全て(?)いじれます。あと自分の作ったコンポーネントは、定義時にpublicにすると、外側から変更可能です。

コンポーネントのプロパティ

コンポーネントのプロパティ

GameObjectやaudio Clipなどを 参照したいときは、AssetsやHierarchyからドラッグで指定できます。

ちなみに、キャラクターの叫び声のAudio Clipの設定もこれで行っています。

投げたときに、ランダムで叫び声を あげさせるのはこんな感じです。 public AudioClip[] shoutSe; //音声を沢山用意 int i = Random.Range(0, shakeSe.Length); audio.PlayOneShot(shoutSe[shoutIndex]);

音声の再生

この話はあくまで、Unityのシーンに含まれるGameObjectに紐づくコンポーネントの話ですので、画面に表示されない部分(いわゆるロジック部分)については、普通にクラスベースの開発を行えます。…あくまで噂ですが。

その他のロジックについて

Logic部分 View 部分

相互に

やりとり

オブジェクト間の 通信方法について

この話の流れついでに

これやって> <いいよ 通信

大きく2つ方法があります。

・GameObjectのコンポーネントを取得して メソッドにアクセスするパターン ・メッセージを送信するパターン

オブジェクト間の通信方法

たとえば「parson」というGameObjectの、 RigidBody 2DのisKinematicのチェックを外したい場合。 GameObject parson = GameObject.Find(“parson"); parson.rigidbody2D.isKinematic = false;

コンポーネントのメソッドにアクセス

自分で作ったコンポーネントの取得は、 GetComponent<ParsonController>();

で、取得できます。もしGameObjectをまたぐ場合は、 GameObject.Find(“parson").GetComponent<ParsonController>(); のようにとることが可能です。

コンポーネントのメソッドにアクセス

たとえば、「PersonController」の public void Dragging() に、アクセスしたい場合。 ParsonController parsonController = GameObject.Find(“parson").GetComponent<ParsonController>(); parsonController.Dragging();

コンポーネントのメソッドにアクセス

メッセージを送信する

たとえば、「PersonController」の public void Dragging() に、アクセスしたい場合。 …のSendMessageバージョン GameObject.Find(“parson"). SendMessage("Dragging"); ※コンポーネント間の呼び出しとパフォーマンス

ゲーム自身のロジックを 制作していきます

いよいよ佳境ですよ☆

中身をわかりやすくするためにフォルダ分けします。 僕は、とりあえず2D Platformer(まめ)を参考にしました。

Assetsの整理

Project View

Create→Folder

Prefabsフォルダは後で使います。

空のGemeObjectを作り、ファイル名と同名 (今回は「GameMain」)にし、TransformのPositionが 全て0なのを確認します。

Hierarchyの整理

GameObject→Create Empty

Hierarchy ViewでGameObjectをドラッグして移動させ、 分かりやすく、こんな感じにします。

Hierarchyの整理

「GameMain」に、 C#スクリプト 「GameMain.cs」を Addします。 あと音楽もならしますので「Audio Source」もAddします。

ゲームのメインロジックの追加

おおざっぱなフローの概要

・音楽の再生 ・GUI Textの 設定 ・ゲームの開始

・一定時間毎にキャラクターの クローンを作成 ・キャラクターのドラッグ判定 ・タイマーのカウントダウン ・GUIのスコア追加と時間を変更

・GameOverの 表示 ・タイトルに戻る 処理

ゲームの初期化 ゲーム中 ゲーム終了

重要なのをいくつかピックアップして説明します。

あ! 今のままだと、キャラクターを複製ができないので、

キャラクターをPrefab(プレハブ)にして、 複製できるようにします。

キャラクターのPfefab化

Hierarchy Viewから、 ドラッグして Assets Viewに 持ってきます。

Prefab完成!

「GameMain.cs」の変数定義で、 public GameObject peasonPrefab; という空のGameObjectを用意します。 すると、Inspector Viewの Game Mainにプロパティが出ますので、 ここに、作ったPrefabをドラッグします。 そうすると、プログラム上で、 定義したのと同じになります。

キャラクターの複製

後は、出すだけ! Instantiate(peasonPrefab); ちなみに、Updateに そのまま書き足したら、こう。 なので、一定間隔で 出るように調整をします。

キャラクターの複製

ちなみにタップの判定については、複数の方法があります。 ・ MonoBehaviourのメソッドOnMouseを利用する。 ・RaycastHit2Dを使用する(今回はこちらで制作)。 ・ タッチ系の操作をサポートするAssetを使用する。

キャラクターのドラッグ判定

MonoBehaviourのメソッドとして用意されている、 Mouse関連の関数を使う方法です。 OnMouseOver, OnMouseDrag, OnMouseUpなども 同様に使用できます。 どうもモバイルだと判定が遅れてしまうようです。 ストラテジー系なら気にならないと思いますが。 OnMouseメソッドについては、 ここに詳細が記載されています。 Mouse入力 Event, OnMouse, Input

OnMouseメソッドとは?

まず、特定したいオブジェクトに、 Box Collider 2Dと Rigidbody 2DをAddする。 物理演算の影響を 受けたくない場合は 該当箇所をそれぞれチェック。

OnMouseメソッドを利用する

Scriptにて、任意の場所に void OnMouseDown() { Debug.Log (“クリックされたよ!"); } と書きます。クリックすると…

OnMouseメソッドを利用する

でます。

任意の位置から任意の方向に向けて架空の線を出し、その線分上にあるオブジェクトを取得することが出来ます。 RaycastHit2Dは、それの2Dヒットテスト用になります。

Raycastとは?

<ドキーン 届けこの想い>

画面

Raycast

RaycastHit2Dを使用する

まず、特定したいオブジェクトに、 Box Collider 2DをAddする。 当たり判定のみの場合は 該当箇所をチェック。

Scriptの void Update()内に、以下のスクリプトを書きます。 if (Input.GetMouseButtonDown (0)) { Vector2 tapPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition); RaycastHit2D hitObject = Physics2D.Raycast(tapPoint,-Vector2.up); if (hitObject) { Debug.Log("クリックされたよ!"); } }

RaycastHit2Dを使用する

前のページのスクリプトでは、マウスダウン時に、マウスポジションの位置をカメラ目線で取得してRaycastを飛ばして当たったらConsoleを出すという処理を記述しています。

RaycastHit2Dを使用する

Raycast

InputTouchesは、試しに触ってみましたが、 かなりよさそうです。 http://terasur.blog.fc2.com/blog-entry-168.html トリガー判定はもちろん、細かな携帯での挙動やフリック時の移動距離や角度まで取得することが可能です。 それらを自前で用意することを考えると…。

Asset Storeを利用する

ざっくり書くと、こんだけです。 private float nowTime = 60f; void Update () { nowTime -= Time.deltaTime; }

タイマーのカウントダウン

やりたい事をプログラムにします

今回のプログラムは、ここに載せました。 ※突っ込み大歓迎です☆ http://i-tai.net/apps/ningen-tamaire/dev/

色々あって 完☆成

※画面は開発中です。

・キャラクターにMecanimを使用した パーツアニメーションを作る http://blog.cshool.jp/2013/12/5215.html ・ゲームバランスの修正 ・GUIをNGUIに変更

今後の課題

付録 NGUIについて えぬぐいですよえぬぐい

・Unity標準のGUIツールよりかなり優れたGUIツール (というより、Unityの標準GUIがあまりにも貧弱です) ・結構、モバイル独自の挙動にも対応している。 (スワイプによるコンテンツのスクロールやドラッグなど) ・今後標準リリースされるuGUIはNGUIをベースにしている。 (ちなみに、NGUIの作者がuGUIの開発に関わっていた) ・Asset Storeにて95ドルで販売中 http://u3d.as/content/tasharen-entertainment/ngui-next-gen-ui/2vh

NGUIとは?

NGUI 3.0.7 Tutorial (英語ですが、スクロールウインドウなど、映像だけでもどのように作るか大体わかると思います)

http://www.youtube.com/watch?v=B66xhIvYF00

参考前知識

NGUIでスクロールしてみる

今回は画面全体に スクロールウインドウを作り、 その中にOTFテキストを 沢山入れて表示してみます。 ここ以降はNGUIをAsset Storeで 購入した前提で記述します。

・新規別シーンを用意します (今回は「Story」というシーンを制作) ・カメラの画面サイズをスマホ用に設定します (よければスライドの前半戦を見てください☆) ・使いたい文字のOTFフォントファイルをAssets Viewに

下準備しましょう☆

NGUIをインポートする

Window → Asset Storeからインポートします。 メニューに「NGUI」が出てるのを確認してください。

Demoで何となくできることを把握

Assets Viewから、 NGUI →Examples → Scenes で色々デモがみれます。

NGUIのUI Rootを作ります

NGUI → Create → 2D UIで UI Rootを作ります。NGUIオブジェクトは こちらに入れることになります。

UI Rootのプロパティの該当箇所の Scaling Style を「FixedSize」、Manual Height をカメラのサイズに合わせると、大きさの数字が合うのが確認できます。

UI Rootを画面サイズと合わせる

UI Rootを選択した状態で、右クリック。 Create → Scroll View でaddChildする。

Scroll View を addChild

Scroll View の該当箇所のサイズをカメラに合わせると、 UI Rootと大きさが合うのを確認してください。

Scroll View を addChild

Labelを addChild

次は、Scroll Viewを選択した状態で、右クリック。 Create → Lavel でaddChildする。

Label を addChild

LabelのFontをUnityにし、右のフレームに 読み込んだOTFフォントをドラッグしてください。

好きな文字を入れる

出た。

LabelのWidget部分の下記を、画面より大きく設定し、テキストも大量に入れます。画面では640 x 5000の大きさにしています。

スクロールできるように

さらにLabelを選択した状態で、右クリックし、 Attach → Box Collider を追加。さらに、 Attach → Drag Scroll View を追加します。

スクロールできるように

これでスクロールしますが、なぜか横にしか動きません。

Scroll View の Movement を Vartical に変更してください。

スクロールできるように

動いた。

2D Spriteで作った背景と同時に 表示すると、うまく合成されているのが分かります。

他オブジェクトとも表示

終わり? ここまでのご清聴、ありがとうございました☆

こちらにもUnity情報を載せています~ http://i-tai.net/apps/unity/

ありがとうございました☆

ばいばい。

Recommended