[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
SlideShare a Scribd company logo
ラクガキ忍者制作秘話
Unityを使ったアクションゲーム制作
自己紹介
O 名前
O コッペパン

O Twitter
O @pepa_696

O 所属
O H〇L大阪 ゲーム学科 4年生

O Unity歴
O 1年ぐらい?
ここに立っている経緯
O 4月にHAL大阪×PLAYISMとの産学連携で

「世界を驚かせるゲームを作れ」と言われ、
「ラクガキ忍者」を制作。
ここに立っている経緯
O 4月にHAL大阪×PLAYISMとの産学連携で

「世界を驚かせるゲームを作れ」と言われ、
「ラクガキ忍者」を制作。
O HAL大阪・名古屋合わせて44作品の中から
2作品が選ばれ、配信決定。その中の1作品
が「ラクガキ忍者」である。
ここに立っている経緯
O 4月にHAL大阪×PLAYISMとの産学連携で

「世界を驚かせるゲームを作れ」と言われ、
「ラクガキ忍者」を制作。
O HAL大阪・名古屋合わせて44作品の中から
2作品が選ばれ、配信決定。その中の1作品
が「ラクガキ忍者」である。
O 11月8日からPLAYISMより配信開始。
ここに立っている経緯
O 4月にHAL大阪×PLAYISMとの産学連携で

「世界を驚かせるゲームを作れ」と言われ、
「ラクガキ忍者」を制作。
O HAL大阪・名古屋合わせて44作品の中から
2作品が選ばれ、配信決定。その中の1作品
が「ラクガキ忍者」である。
O 11月8日からPLAYISMより配信開始。
O 現在300円で販売中。
ここに立っている経緯
O 4月にHAL大阪×PLAYISMとの産学連携で

「世界を驚かせるゲームを作れ」と言われ、
「ラクガキ忍者」を制作。
O HAL大阪・名古屋合わせて44作品の中から
2作品が選ばれ、配信決定。その中の1作品
が「ラクガキ忍者」である。
O 11月8日からPLAYISMより配信開始。
O 現在300円で販売中。(買ってね)
PLAYISMって?
O インディーズゲーム配信サイト!

世界の面白いインディーズゲームを
翻訳、販売してるサイトです。
あなたの作ったゲームも配信できるかも!
PLAYISMって?
O インディーズゲーム配信サイト!

世界の面白いインディーズゲームを
翻訳、販売してるサイトです。
あなたの作ったゲームも配信できるかも!
「ラクガキ忍者」販売中!
ラクガキ忍者とは?
O Unityを用いて制作されたアクションゲーム。
O 3D空間上を横スクロールで進む。
O 学校の教室を舞台にプレイヤーは主人公の

忍者を操作して戦う。
O 謎の敵「ポイヘイ」をバッサバッサ切り倒す。
O 詳細は購入してご確認ください。
勉強会と言われても…
O 「ラクガキ忍者」はUnityを使って作られていま

すが、特に凄い技術は使われていません。
O なので、ゲーム作りについての話もします。
O 少しでも何か参考になれば幸いです。
O Unityと関係無い話もあるかもです。
チームで開発
O 開発期間
O 4月中旬~8月末(4か月ぐらい)

O 言語
O C#

O チームメンバー
O 7人(プランナー3人、プログラマー4人)
O 後にサウンド3人追加
O 最終的には10人
開発スケジュール
O 4月中旬

初めて話を聞く
O 4~5月
企画書、仕様書、プロトタイプ
O 5~6月
キャラクター、敵、ステージ作成
O 6~7月
UI、ギミック、敵、ステージ作成
O 7~8月
UI、デバッグ、調整…いろいろ
O 8月末
納品
O 10月ぐらい 配信決定、さらにデバッグ、調整
O 11月8日
配信開始
とりあえず時系列順に
何やってたか詳しく。
4月下旬
O 企画を考える
O プログラマ4人中2人がUnity経験者
O アイエエエエ! ニンジャ!? ニンジャナンデ!?
O デザイナがいない→ラクガキ
O ラクガキ忍者の前身、妄想忍者が出来上がる。
5月(GW)
O ブロックを切るにはどうするのか
O Assetを発見→購入(Object Cutter)

O 企画書を作りながらプロトタイプ作る

O Unityを使う上での意識統一を行う
O Unity開発に関する50のTips

O サーバーを立ててRedmineを導入
O Gitを用いての管理を始める
5月中旬
O CharacterControllerをベースに全キャラク
O
O
O
O

ターのベースとなるクラスを作成
忍者の動きを作り始める
敵を考える
ステージを考え始める
アニメーションの管理をどうするか悩む
O ex2Dを使うことに決定(Asset)
5月下旬
O 敵を作る
O ステージ1(仮)を作る
O ゲームループ作る

O タイトル画面、ステージセレクト画面作る
O ゲーム内のUIを作る
O 5月末α版
O ステージ1が遊べるぐらいまで出来てた
6月
O ステージをどんどん作っていく
O ステージエディタを作ろうかと思ってたけど、
O
O
O
O

結局全部人力で作った(後々苦労する…)
敵を作り込んでいく
文房具ギミックを作る
オプションとセーブデータを保存できるように
外部ファイル書き出し出来るようにする
キーコンフィグ頑張って作る
7月
O 7月頭

β版

O ステージ10まで遊べる
O 大体の部分は完成してた

O 7月中旬

夏休みに入る

O ステージセレクトを1から作り直し
O ステージを半分ぐらい作り直し
O デバッグ
8月
O 学校が閉まってしまうためコワーキングス
O
O
O
O
O
O

ペースを借りて作業
ステージセレクト作る
ステージ作る
デバッグ、修正
デバッグ…修正…
デバッグ……修正……
8月末納品
というわけで
O ざっくり紹介が終わったところで、そろそろ

Unityの技術的なお話をしていきます。
というわけで
O ざっくり紹介が終わったところで、そろそろ

Unityの技術的なお話をしていきます。
O あらかじめ注意
O 全て自己流での実装となっております。
O きっともっといい方法があると思います。
O 参考程度に聞いてください。
というわけで
O ざっくり紹介が終わったところで、そろそろ

Unityの技術的なお話をしていきます。
O あらかじめ注意
O 全て自己流での実装となっております。
O きっともっといい方法があると思います。
O 参考程度に聞いてください。

おk?
Transformを拡張
Transformを拡張
O C#は色々めんどくさい
Transformを拡張
O C#は色々めんどくさい

transform.position = new Vector3(1,0,0);

いちいちこう書かないといけない…
めんどくさい!
Transformを拡張
O C#は色々めんどくさい

transform.position = new Vector3(1,0,0);

いちいちこう書かないといけない…
めんどくさい!
transform.position.x = 1;
C#でもこうやって書きたい!
Transformを拡張
O そこでTransformを拡張する!
public static class TransformExtension
{
public static void positionX(this Transform transform, float x)
{
Vector3 newPosition =
new Vector3(x, transform.position.y, transform.position.z);
transform.position = newPosition;
}
}
Transformを拡張
O こうすると

transform.positionX(1);
という書き方が出来るようになる!
便利!
Transformを拡張
O こうすると

transform.positionX(1);
という書き方が出来るようになる!
便利!

RotationとかScaleも同じように作っとけば便利!
MonoBehaviourを拡張
MonoBehaviourを拡張
O Instantiateがめんどくさいと思ったことは?
Object Instantiate(Object o);
Object Instantiate(Object o, Vector3 v, Quaternion q);
MonoBehaviourを拡張
O Instantiateがめんどくさいと思ったことは?
Object Instantiate(Object o);
Object Instantiate(Object o, Vector3 v, Quaternion q);
Object型で戻ってくるのでキャストしないといけない。
位置指定はしたいけど、角度の指定はどうでもいい。
いちいちResources.Load()するのがめんどくさい。
などなど…
MonoBehaviourを拡張
O MonoBehaviourを継承しよう!
O たとえばこんな感じ
public class MonoBehaviourExtends : MonoBehaviour
{
}
MonoBehaviourを拡張
O MonoBehaviourを継承しよう!
O たとえばこんな感じ
public class MonoBehaviourExtends : MonoBehaviour
{
}

継承して何をするのか?
MonoBehaviourを拡張
O こうしちゃいます
public GameObject InstantiateGameObject (string path)
{
GameObject go =
Instantiate(Resources.Load(path)) as GameObject;
if(go == null)
Debug.LogError(“そんなんねーよ!”);
return go;
}
MonoBehaviourを拡張
O さらにこうします
public GameObject InstantiateGameObject(string path, Vector3 pos)
{
GameObject go = InstantiateGameObject(path);
go.transform.position = pos;
return go:
}
MonoBehaviourを拡張
O さらにこうします
public GameObject InstantiateGameObject(string path, Vector3 pos)
{
GameObject go = InstantiateGameObject(path);
go.transform.position = pos;
return go:
}

生成したオブジェクトをGameObject型で戻してくれる!
位置指定してくれる!便利!!
MonoBehaviourを拡張
O さらにさらに
public GameObject InstantiateGameObject(Object obj)
{
GameObject go = Instantiate(obj) as GameObject;
if(go == null)
Debug.LogError(“えらー!");
return go:

}

Prefabを渡せるようにしたり!
MonoBehaviourを拡張
O さらにさらにさらに
public GameObject InstantiateGameObjectAsChild(Object obj)
{
GameObject go = InstantiateGameObject(obj);
go.transform.parent = transform;
return go:
}

生成したオブジェクトを子供にしたり!
自分が欲しいなぁと思う機能を作り放題!!
いろいろ拡張
O こんな感じで

めんどくさいなぁと思うところを
それぞれ拡張しておけばコーディングが楽に!
新しいプロジェクト作っても
関係なく使えるので結構おすすめ。

興味がある人は
Editorの拡張とかも調べてみるといいかも
拡張する上での注意
O 拡張するとき気を付けて!

拡張すると色々と便利になるけど所詮は
勝手に作ったものです。
思った通りに動かなかった時、
もしかしたら拡張した部分が原因かもしれない
ということをお忘れなく!
MonoBehaviourを拡張
O まとめ
O MonoBehaviourを拡張することで自分好みの

コーディングを行うことが出来る。
O コーディング速度が上がる。
O なんとなくかっこいい。
O 拡張した部分のバグに要注意。
MonoBehaviourを拡張
O まとめ
O MonoBehaviourを拡張することで自分好みの

コーディングを行うことが出来る。
O コーディング速度が上がる。
O なんとなくかっこいい。
O 拡張した部分のバグに要注意。
O 結論
O 上手いこと拡張すれば今後ずっと使える財産

となる。より良いUnityライフが送れる。
当たり判定の話
当たり判定の話
O 地形との当たり判定
当たり判定の話
O 地形との当たり判定

ラクガキ忍者の場合、
地形との当たり判定&移動は
全てCharacterControllerを使っています。
当たり判定の話
O 地形との当たり判定

CharacterController controller =
GetComponent<CharacterController>();

controller.Move(moveDirection );
当たり判定の話
O 地形との当たり判定

CharacterController controller =
GetComponent<CharacterController>();

controller.Move(moveDirection );

Z軸は基本的に0に固定。
当たり判定の話
O 当たり判定

地形との当たり判定はこれだけ。
後はジャンプを適当に実装しただけ。
当たり判定の話
O 当たり判定

地形との当たり判定はこれだけ。
後はジャンプを適当に実装しただけ。

そして、ここからが本題。
地形以外との当たり判定の話。
当たり判定の話
O アクションゲームの当たり判定
当たり判定の話
O アクションゲームの当たり判定

キャラクターの動きによって
当たり判定の大きさ
を変えなければならない!!
当たり判定の話
O アクションゲームの当たり判定

Unityでどうやって
実装するのか…?
当たり判定の話
O アクションゲームの当たり判定

Unityでどうやって
実装するのか…?

知りたい?
当たり判定の話
O ラクガキ忍者はこうやりました。
当たり判定の話
O ラクガキ忍者はこうやりました。

え?わかりにくいって?
では、詳しく説明しましょう。
当たり判定の話
O 当たり判定のポイント
O まず地形との当たり判定は全て

CharacterControllerまかせ。
O 敵との当たり判定はBoxCollider。
O 剣の当たり判定(攻撃)もBoxCollider。

忍者は3つの当たり判定がついています。
当たり判定の話
O 当たり判定のポイント

地形との当たり判定
(CharacterController)
当たり判定の話
O 当たり判定のポイント

地形との当たり判定
(CharacterController)

敵との当たり判定
(BoxCollider)
当たり判定の話
O 当たり判定のポイント

地形との当たり判定
(CharacterController)

敵との当たり判定
(BoxCollider)

攻撃の当たり判定
(BoxCollider)
当たり判定の話
これでキャラの動きに合わせて
BoxColliderの
大きさとか位置を変えれば
アクションゲームの当たり判定
が出来るぞ!!
当たり判定の話
O こんな感じ
当たり判定の話

ん?
当たり判定の話

ん?
ちょっと待って
当たり判定の話

CharacterController
と
BoxCollider
重なってない?
当たり判定の話
このままでは
CharacterControllerと
BoxColliderが
常に当たり続けてしまう…
当たり判定の話

そこで登場するのが

Layer
という便利な機能!
当たり判定の話

コレ
当たり判定の話
Layerで当たり判定
を分けることが出来る。
※イラストソフトのレイヤーと同じような感じ。

Add Layerで自由に
Layer作れる
当たり判定の話

それぞれに違う
Layerを設定!
当たり判定の話
O ここまで出来たら準備は完了
O Project Settingsをいじる
O メニューバーEdit->Project Settings->Physics
当たり判定の話
O ここまで出来たら準備は完了
O Project Settingsをいじる
O メニューバーEdit->Project Settings->Physics
O するとこんなん出てくる
当たり判定の話
当たり判定の話
O ちなみに敵はこんな感じ

ややこしい…
当たり判定の話
O ちなみにちなみに

Scriptからでもいじれます。
Layerはint型で管理されているので注意。
Physics.IgnoreLayerCollision(int, int, bool);
Physics.GetIgnoreLayerCollision(int, int);
当たり判定の話
O まとめ
O レイヤー同士の当たり判定を管理
O 1体のキャラクターに複数のCollederを持たすこと
が可能!
O ただ、レイヤーが多くなると管理が複雑になるので
考えてレイヤーを作ること。
当たり判定の話
O まとめ
O レイヤー同士の当たり判定を管理
O 1体のキャラクターに複数のCollederを持たすこと
が可能!
O ただ、レイヤーが多くなると管理が複雑になるので
考えてレイヤーを作ること。
O 結論
O 内部がどうなっていようとバグ無く思い描いた通り

に動けばいいのです!
ステージの話
ステージの話
O ステージの管理方法は?
O ステージは全て、人力で作ったものをプレハブ

にして選ばれたステージによって生成
ステージの話
O ステージの管理方法は?
O ステージは全て、人力で作ったものをプレハブ

にして選ばれたステージによって生成
O これには問題が…
O プレハブ化したものは元のデータをいじっても

反映されない
O 敵とかギミックとかを修正するたびにステージ
を作りないさないといけない…めんどくさい!
ステージの話
そこで考え出されたのが…
ステージの話
そこで考え出されたのが…

スポーナー
ステージの話
ステージのプレハブを作るときに
実際のオブジェクトでは無く、

起動したらオブジェクトを、生成する。
という機能を持ったオブジェクトを設置する!
プレハブを作り直さなくて良くなる!!
ステージの話
O こんな感じ(プレハブ)
敵のスポーナー

リフトのスポーナー
ステージの話
O こんな感じ(プレハブ)
敵のスポーナー

リフトのスポーナー

これを起動すると…
ステージの話
O こんな感じ(起動時)
生成された敵

生成されたリフト

こうなる!!
ステージの話

しかし!
いちいちスポーナーを作る方が
逆にめんどくさいオブジェクト
も存在する。
ステージの話

コインとか

鉛筆(トゲ)とか
ステージの話
O まとめ
O ステージプレハブは出来るだけいじりたくない。
O スポーナーを置くことでプレハブをいじらなくて

も中身を変更することが出来る。
O でも、鉛筆1本ずつスポーナーを作るのは現
実的ではない。
ステージの話
O まとめ
O ステージプレハブは出来るだけいじりたくない。
O スポーナーを置くことでプレハブをいじらなくて

も中身を変更することが出来る。
O でも、鉛筆1本ずつスポーナーを作るのは現
実的ではない。
O 結論
O スポーナーで管理するところと、管理しないと

ころに分けて上手いことやるのが得策かと。
セーブ、ロードの話
セーブ、ロードの話
O Unityのセーブ、ロード

ゲームの進行を保存したい!
長時間遊ぶゲームなら当然ですね。
セーブ、ロードの話
O Unityのセーブ、ロード

ゲームの進行を保存したい!
長時間遊ぶゲームなら当然ですね。
そこでUnityの機能として
PlayerPrefs
というクラスがあります。
セーブ、ロードの話
O Unityのセーブ、ロード

PlayerPrefsを使えば
簡単にデータを保存することが出来ます!
セーブ、ロードの話
O Unityのセーブ、ロード

PlayerPrefsを使えば
簡単にデータを保存することが出来ます!
やったね!
セーブ、ロードの話
O Unityのセーブ、ロード

PlayerPrefsを使えば
簡単にデータを保存することが出来ます!
やったね!
めでたしめでたし。
セーブ、ロードの話
O Unityのセーブ、ロード

ちょっとまって!!
セーブ、ロードの話
O Unityのセーブ、ロード

ちょっとまって!!
PlayerPrefsには
とんでもない落とし穴が…
セーブ、ロードの話
O Unityのセーブ、ロード

PlayerPrefsクラスによって
保存されたデータは
レジストリに保存(Windowsの.exeの場合)
されてしまうのです…
セーブ、ロードの話
O Unityのセーブ、ロード

流石にレジストリに保存するのは…
セーブデータの移行が出来ない…
とか、思った人は
自分で実装するしかないのです!
セーブ、ロードの話
O .Netを用いたセーブ、ロード

セーブ、ロードを自作するには
Unityの機能では無く
.Netの機能を使います。
セーブ、ロードの話
O .Netを用いたセーブ、ロード

セーブ、ロードを自作するには
Unityの機能では無く
.Netの機能を使います。

Unityのことでは無いので
詳しい実装方法は省略。
セーブ、ロードの話
.Netのファイル操作の話に
なってくるので各自でググるか、
後で聞きに来てください。
そんな難しくはありません。
セーブ、ロードの話
O まとめ
O UnityのPlayerPrefsはレジストリに保存する。

O レジストリに保存されるのは嫌だ。

O .Netを使って実装
セーブ、ロードの話
O まとめ
O UnityのPlayerPrefsはレジストリに保存する。

O レジストリに保存されるのは嫌だ。

O .Netを使って実装
O 結論
O 自分で外部ファイルにデータ書き出せば

万事解決!
O やったね!
インプット管理の話
インプット管理の話
O 入力情報の管理

なぜ入力情報を管理しなければならないのか…
インプット管理の話
O 入力情報の管理

なぜ入力情報を管理しなければならないのか…
UnityにはInputクラスがあるじゃない?
インプット管理の話
O 入力情報の管理

なぜ入力情報を管理しなければならないのか…
UnityにはInputクラスがあるじゃない?

そう考えてるあなた!
インプット管理の話
O 入力情報の管理

なぜ入力情報を管理しなければならないのか…
UnityにはInputクラスがあるじゃない?

そう考えてるあなた!
キーコンフィグを作るためです!
インプット管理の話
O キーコンフィグ

デフォルトのキーバインドでは
しっくり来ない困った人達のために
実装する、実装する側からしたら
凄くめんどくさい機能である…。
インプット管理の話
O ラクガキ忍者の場合

これまた.Netの機能である
Dictionary
を使いました。
インプット管理の話
O Dictionaryを使えば

StringとKeyCodeを
関連付けることが出来る!!
この機能を使い、入力情報を一括で管理
すればキーコンフィグを作ることが可能!!
インプット管理の話
O Dictionaryとは
using System.Collections.Generic;
Dictionary<string, KeyCode> KeyConfig
= new Dictionary<string, KeyCode>();
KeyConfig.Add ("Action", KeyCode.Z);

if(Input.GetKeyDown (KeyConfig["Action"]))
print(“Action”);
インプット管理の話
O キーを入れ替えたい場合
既存のデータを消して作り直す

KeyConfig.Remove (“Action”);
KeyConfig.Add(“Action”, KeyCode.X);
インプット管理の話
O まとめ
O 入力情報は一括で管理した方が良い。
O アクションゲームならキーコンフィグあった方

が良い。
O Dictionaryを使えば比較的簡単に作れる。
インプット管理の話
O まとめ
O 入力情報は一括で管理した方が良い。
O アクションゲームならキーコンフィグあった方

が良い。
O Dictionaryを使えば比較的簡単に作れる。
O 結論
O 実装するのはめんどくさいけど、

キーコンフィグがあると凄くゲームっぽい!
リリースしてからの話
リリースしてからの話
O 色々なことがありました…
O 見知らぬ人に買ってもらえた
O おもしろい、かわいい
O 実況動画
O 4Gamerに載った!
O 挙動が気持ち悪いところがある
O 無駄なアクションが多い
O キー操作がわからない…etc
リリースしてからの話
嬉しいことが山ほどありましたが、
やはり批判的な意見に
目が行ってしまうものです。
リリースしてからの話
その中でも特に多かったのが
リリースしてからの話
その中でも特に多かったのが

操作がわからない
挙動が気持ち悪い
リリースしてからの話
この辺の意見は
技術的に難しいとかではない!
リリースしてからの話
この辺の意見は
技術的に難しいとかではない!
ユーザーのことを考えて作っていれば
特に問題にならない部分です。
リリースしてからの話
では、なぜこんな問題が起こるのか…
大きな原因は
リリースしてからの話
では、なぜこんな問題が起こるのか…
大きな原因は

慣れ
だと思います。
リリースしてからの話
常に新鮮な気持ちで見れれば良い!
しかし、そんなことは多分無理…
リリースしてからの話
常に新鮮な気持ちで見れれば良い!
しかし、そんなことは多分無理…

なので、外部の人に
意見をもらうのが大事!!
リリースしてからの話
O まとめ
O リリースされると凄くうれしい!
O 技術的なことは頑張れば何とかなる
O 同じゲームずっとさわっていると慣れが怖い
O 外部の人に見てもらいましょう!
リリースしてからの話
O まとめ
O リリースされると凄くうれしい!
O 技術的なことは頑張れば何とかなる
O 同じゲームずっとさわっていると慣れが怖い
O 外部の人に見てもらいましょう!

O 結論
O ユーザーのことを考えて!
O デバッグ大事!
結論

デバッグ大事
(プログラム以外の所)
参考にしたサイトなど
O Unity開発に関する50のTips 〜ベストプラクティス〜
O

http://warapuri.tumblr.com/post/28972633000/unity-50-tips

O UnityでSave/Loadを実装するには?
O http://d.hatena.ne.jp/tueda_wolf/20120109/p1

O Unity Reference
http://docs.unity3d.com/Documentation/ScriptReference/
O http://docs-jp.unity3d.com/Documentation/ScriptReference/
O
ラクガキ忍者制作秘話

More Related Content

ラクガキ忍者制作秘話