Unityでインディゲーム道!

プログラム、Unity初心者がインディゲーム制作を目指して日々思うことなどを書き綴ります。

下から叩くとアイテムが出るブロックの再現。二重コライダーの活用。

今回はUnity上で、マリオなどのアクションゲームで目にする"下から叩くとアイテムを出すブロック"を再現してみたいと思います。Unity2Dになりますので、3Dとの違いにご注意を。 

 

f:id:miur-us:20170813163431g:plain

完成版のGIFです。こんな感じでニュッと出るようにしました。明らかに敵っぽい目つきですが、アイテムのフラワーです。

Unityはcollider(コライダー)が準備されているので、それを各ゲームオブジェクトにアタッチすれば、簡単に"当たり判定"を付けることができます。

今回は2Dになるので、BoxCollider2Dという感じで後ろに"2D"がつきます。付け忘れると動かないので注意しましょう。

 

 で、ボックスにとりあえずコライダーを付ければ、プレイヤーキャラとの単純な衝突は検出できるようになるので、アイテムボックスのスクリプト側にOnCollisionEnter2Dを書いて、そこに"アイテムを飛び出させるコード"を書けば何とかなりそうです。

 

下からだけに反応させる!

しかし!このままでは、ボックスのどの位置にプレイヤーが当たってもアイテムが飛び出してしまいます。下から当たった時にだけアイテムが出るようにするにはどうすればいいか?自分が思いついたのは"二重コライダー"です。

つまり、ブロックにコライダーを二個設置することで、プレイヤーがブロックの下に当たったかを検出するという方法です。通常のコライダー以外にトリガーモードのコライダーを下側に設置します。

 

f:id:miur-us:20170813170020p:plain

 少し見えにくいですが、下に少しだけ飛び出している、コライダーがあるのが分かるかと思います。(緑の四角)

要はこのコライダーでプレイヤーが下にいることを確認しつつ、メインのコライダーに当たったか?という判定を行うわけです。そのために下のコライダーはトリガーモードでの使用、ということになります。 

 

 

 f:id:miur-us:20170811224644p:plain

Diamondというのは、赤い模様の部分なので無視してください。

"UnderTrigger"というのがそれです。コライダーのみアタッチされています。ヒエラルキー上では、ItemBoxのチャイルドに置かれています。

f:id:miur-us:20170811224835p:plain

IsTriggerにチェックをいれると、トリガーモードにできます。これにより単純にここに重なっているかどうかを検出できるようになります。"当たり"はなくなります。

↓アイテムボックス本体のインスペクターはコチラです。

f:id:miur-us:20170811225100p:plain

Box Collider 2Dがアタッチされています。これが単純にブロックとしての当たり判定になります。最終的なプレイヤーとの衝突はここが検出します。

下にある、Item Box Controllerが実際のスクリプトになります。

 

コードを確認してみる!

f:id:miur-us:20170811225350p:plain

f:id:miur-us:20170811225415p:plain

各変数から説明していきます。

"content"

まさしく箱の中身でアイテムです。今回はフラワーですが、Unityのインスペクター上でアイテムのプレファブをドラッグすれば、いろんなアイテムに入れ替えられます。

悩んだんですが、Startメソッド、つまりシーンがロードされた時点でプレファブをInstantiateしています。でSetActiveでfalseにして隠しておきます。

"movePoint"

アイテムの飛び出す位置です。本来はアイテムごとに飛び出る位置を調整する必要があるでしょうが、ここでは省略しています。Startメソッドで座標を指定しています。

ニュッと出すためにVector2.Lerpを使いますが、きちんと動くためにここで宣言しておく必要があります。(フィールドというやつです。)

"IsOpened"

これは開いたかどうか?当然最初は開いてないのでfalseです。プレイヤーがきちんと下にあたったらtrueにします。

"IsActive"

動かすのにVector2.Lerpを使うと移動し終えるまでUpdateでループさせる必要があるんですよね。で移動し終わった後もコードが実行され続けてパフォーマンス的にまずいと思うので、アイテムがきちんと出たらコレをfalseにして、つまりボックスの動作がオフになった、ということにしてコードを実行されなくするためのフラグになります。

 

"sr"

これはSpriteRendererのオブジェクトです。叩き終わった後、もうアイテムが入ってないよ!ってことを示すために色を変えたいんですが、その際に使います。

"m_Colliders"

このコードでもっとも重要な複数のコライダーを扱うためにBoxCollider2Dのオブジェクトを配列として宣言します。Startメソッド内でGetComponentsInChildrenを使って、ボックス本体のと下側の二つの参照を得ています。なので・・・

m_Colliders[0]はItemBoxのコライダー、m_Collider[1]は下部のトリガーをそれぞれ指すことになります。

"playerCollider"

プレイヤー自身のコライダも必要なので、オブジェクトを作り、StartメソッドでFindWityhTagを使い、参照を得ています。

 

実際の処理の流れ

というわけで準備は整いました!

プレイヤーがブロック下にぶつかると、どういう流れで処理が進んでいくかを、実際に説明していきたいと思います。

まずはOnCollisionEnter2Dが作動します。二つの条件を判定します。

  • 下部トリガーがプレイヤーのコライダーを検出しているか?
  • 本体に当たったゲームオブジェクトのタグが"Player"か?

最初の判定はm_Colliders[1].IsTouching(playerCollider)という文で行います。IsTouchingはコライダのメソッドで、引数として入力されたコライダが自分と触れ合っているかを判定し、触れていればtrueを返します。二番目は公式チュートリアルでも出てくるCompareTagで判定。

col.gameObject.CompareTag("Player")でプレイヤーのタグをチェックします。

 

どちらもtrueとなったら以下の文が実行されます。

content.gameObject.SetActive(true);

IsOpened = true;

StartCoroutine(WaitSwitchOff);

SetActiveでアクティブにし、IsOpenedをtrueにすることで移動の処理が始まります。

StartCoroutineIEnumratorを使って、WaitForSecondを含むメソッドを実行する際に必要ですが、コレによりアイテムが出た後、IsActiveがfalseになるようにしています。一秒もあれば移動も終わるので、1.0f秒待機、としています。

f:id:miur-us:20170811235740p:plain

さて!ではアイテムが飛び出るための処理です!

Updateメソッド上にあります。この処理自体をメソッド化してもよかったのですが、これだけなので、そのままにしています。

 if( IsOpend && IsActive) { //移動の処理 }

まずは箱がオープンされたか?アイテムボックスは仕事を終えてないか?という条件判定です。これについては、上記で説明したとおりです。

 

content.transform.position = Vector2.Lerp( ~ 以下略 ;

これはつまり、フレームごとにアイテム自身の位置目標地点を0.3fの割合で線形補間していく、というもので、要は単純に移動させるのではない、ニュッという感じの動きになります。生々しい動きになるわけです。

sr.color = Color.Lerp(sr.color, Color.gray, 0.4f);

については、正直ブロックを叩いた時点で実行していいですね。

ボックスの色を変える実行文です。

 

そして、先ほど言ったように移動し終わったころには、WaiSwitchOffメソッド内の

IsActive = false;

が実行され、移動の処理は行われなくなります。

if(IsOpend && IsActive)の部分がfalse(偽)になるからです。

 

まとめ!

以上で、プレイヤーが下から叩いたかを判定し、アイテムを出して、ボックス上部に移動させる、という動作の実現についてのレポートになります。

まだ改善点、付け加える部分はありますが、プレイヤーをジャンプさせてブロックを叩いて、その勢いのままにアイテムが飛び出してくる、という手ごたえのあるレスポンスは再現できたのかなと思います。

 

というわけで、Unity上でのまともな実践を扱ったエントリはこれが初になるんですかね?ネタはいろいろあるので、ドンドンやって生きたいと思います!! 

 

 

本ブログのカテゴリー(の定義)を整理しました!

本ブログのメインテーマはUnityでゲーム、あるいはアプリを作る!というものであり、それに付随するプログラミングに関することなども書き記していくのが、主な目的となっています。

それらを中心に、そこからズレ過ぎない程度にいろいろ書いていきたいんですが、きちんと方向性を決めておかないとブログとしてはブレるな、と思ったのでブログ内カテゴリの刷新、あるいは定義をしっかりやってみることにしました。

基本的に自分用メモですが、本ブログを読まれる方の参考にもなれば幸いです。

 

というわけで、より良いブログ運営を目指してGO!

 


 

プログラミング

これはそのままですね。純粋にプログラミングそのものに関することを書きます。基本的にはC#についての内容になります。学んだことのまとめになると思います。

 

UnityのためのC#

今回特にきちんとしたかったのがココです。従来だと"プログラミング"とごちゃ混ぜになっていて、きちんと内容的に分けられていなかったです。

なので、明確に定義しておきたいと思います。

Unity上でのC#に関することで、必ずUnityの具体的な動作を絡めること、とします。

単にコードのみ載せるとかではなく、その結果どういうことが出来るようになったか、などをきちんと明示する、ということになります。なので、どちらかというと実践寄りの内容になると思います。

 

Unity

アセットストアでこんなの買ったよ!とかアップデートでこんな新機能が搭載されてスゲー!などのUnity本体に関わる内容にすること。 

 

MadewithUnity

Unityで作られたゲームの紹介、レビューについてのカテゴリ。 

 

ゲーム評論

Unity関わらず、個人的に遊んだゲームについてのレビュー。MadeWithUnityでもレビュー的内容がある場合にはこれに含まれる。 

 

ゲーム制作

自身の具体的なゲーム作りに関することについて。近いうちに簡単なゲームについては公開してみたいと思ってますが、そうしたものの進捗などはココでやります。

"UnityのためのC#"はコーディング絡みになりますが、単純にUnity上で何か作ったり、アセットを試してみた!等の内容もココでやります。 

 

書籍レビュー

読んだ本の書評についての内容になります。もちろんプログラミングやゲーム制作に関わる本に限定します。 

 

GEEKネタ

"GEEK"とはアメリカにおけるサブカル寄りなオタクを意味するスラングで、任天堂のゲーム『MOTHER』シリーズにおける、ギーグの語源らしいです。アニメや漫画、その他、コンピュータやPCカルチャー的な内容を扱うカテゴリにしたいと思います。まぁ本ブログのテーマとはあまり関係ないようなモノをぶち込むカテゴリになります。 

 

ブログ運営(旧"お知らせ")

お知らせって知らせることなんてあるのかよ!って感じですが、ブログ自体の事について書く時に必要かと思うので、名称も改めつつ、運営に関わるようなことについてはココで書きたいと思います。

 


以上になりますが、さらに良いブログになるよう努めていきますので、これからも本ブログ、"Unityでインディーゲーム道"をよろしくお願いします。

 

"下から叩くとアイテムが出るブロック"の再現!!を近日公開!

 

 

アクセス修飾子やプロパティは、クラス連携のセーフ・ガード。Unity上での実例も含めて。

public, privateとはつまりは公開、非公開のことであります。

今回は"クラス"同士が連携する際のセーフ・ガードの役割を果たす、アクセス修飾子、プロパティについてまとめてみたいと思います。Unity上の使い方についても書いてみました。

 


プログラム全体を1つの大きな部屋だとすると、クラスは小部屋であり、その小部屋に自由に出入り出来るかどうか?ということになります。

これだけだと少し分かりづらいですが、より理解するためにはクラス及び、オブジェクト指向の本質、そしてカプセル化情報隠蔽を理解する必要があります。

では、なぜこのような修飾子が必要になるのか?について書いていきます。


 

いくつものクラスが組み合わさって

そもそもオブジェクト指向におけるクラスとは、何でしょうか。

設計図のようなもの、と言われますが、要はプログラムを分割するためのものです。

オブジェクト指向の本質とは、いかに仕事、機能ごとに分割して、どのようにそのクラス同士を連携させるか?ということになると思います。

ここでの問題は、まずどう分割するかの作業があり、かつそれを上手くやるには物事の本質を見極める能力が必要であるということ。ここについてはアクセス修飾子とは直接的な関係がないので、後日に"クラス"についてのエントリを書く時に触れたいと思います。そして次に"クラス"によって、全体のコードはバラバラにされているわけなので、実際にはそれらのクラスが連携し合うことで、プログラムが動くということです。

 

このいかにクラス同士を連携させるか?という問題が、本記事にとって重要な部分です。ここでの注意点は、別に連携させる必要がないなら無理に連携させる必要はないということです。つまり、あるクラスの中で処理が完結するのならば、それに越したことはない、ということになります。

クラス間の結合度を低く抑える、という風に言われます。

 

各クラスが独立していれば最高 

さて連携すると言っても、どの程度深く関わるか?という話にもなります。

その関わり方が浅い方がより良い、ということです。

結合度という言葉が出ましたが、これが高くなるとクラス同士が絡み合い、プログラムが複雑になってしまいます。分割して、各部をシンプルにするためのオブジェクト指向なのに、これでは本末転倒です。

ここら辺はクラスをいかに分割するか?というクラス設計も関わります。クラスをどう作るか?という問題が実は一番難しい、というような話もあるようです。

 

というわけでpublic, privateやプロパティというのは、クラス間の連携具合、アクセスを制御し、安全性を高めるためにものと言うことができます。

 

身近な例で考える 

さて公開、非公開とはどういうことでしょうか?

もし、あなたの家に友達が来たら、玄関を通り家に中に通します。

もしも宅急便の配達員が来たら、玄関で荷物を受け取り、家の中には入れさせません。

つまりクラスにおけるprivateとは家の中で、publicとは玄関あるいは外の世界ということになります。(玄関は"外との境界"という解釈です。) 

 

家の中はプライベートな部分なので、誰にでも見せるものではありませんし、親しい人にのみ許されます。要するにウチソトです。

 

プログラミングは何らかの事務処理なのですから、今度は市役所に例えてみます。

 


あなたがそこの市民であるなら、市役所に行って住民票を発行してもらうことが出来ます。しかし、それはあくまで写し(コピー)であり、原本をもらうことは出来ません。

そして、市役所の中には入ることはできませんし、内部に保管されている他人のデータを見ることもできません。あくまで入ることのできるのは窓口だけです。

 

プログラミングで言えば、

"市民class"のオブジェクトである太郎くんが、"市役所class"の住民票発行メソッドにアクセスして住民票の写しを取得できるが、"市役所class"内にある自分や他人のデータに直接アクセスすることはできないし、ましては変更することは禁じられている、という風に言うことが出来ます。

つまりクラス間のアクセスを制限するために、アクセス修飾子は必要なのです。

 

privateにすることで外部の人間に触らせないようにする、ということです。

外部の人間が利用したい機能などにはpublicをつけて利用できるようにするわけです。

 

プロパティは設定画面であり、窓口

プロパティも同様です。

変数をそのままpublicにしてしまうと、グローバル変数になってしまい危険です。つまり、どんなクラスからだろうとアクセスできてしまい、誤代入や干渉が発生してしまう恐れがあります。

 

クラスの中に収めつつ、外部から安全に変数にアクセスできるようにするにはプロパティが必要になります。市役所の例を先ほど出しましたが、まさに"クラス"における窓口のような存在ともいえる機能です。

 

変数そのものはprivateにします。しかし、それではクラスの外からアクセスできません。そんなprivate変数へのアクセスの窓口として機能するのが、プロパティです。

つまりプロパティを通してでしか、外部から変数の値を取得したり、変更できないようにすることで"クラス"のカプセル化を維持するわけです。またprivate setにすることで、外部からは変更出来ないようにすることもできます。例えば電話番号とかを勝手に変更されたら大変ですもんね。

private int _money; //privateにしてクラス内からしかアクセスできないようにする。

public int Money {

    get{ return _money;} //外部のアクセスに対し、代わりに変数にアクセスし渡す。

    private set{ _money = value; }

}

  

Unity内での実践

ということで、Unityにおいてprivate, publicをどのようにつかっていくかの簡単な実例を出してみたいと思います。

ここでは二つのクラスを考えます。

プレイヤーキャラの操作などを管理する、PlayerControllerと、

ゲーム全体、スコア、残り時間を管理する、GameControllerです。

 

さて残り時間がゼロになると、ゲームオーバーになるとします。

if( timeLeft <= 0 ) 

この時、プレイヤーが敵に当たって死ぬ時の演出を時間切れの際に、発動させたいわけです。マリオみたいな感じですね。

Death()メソッドとしますが、これはPlayerController内にあります。

しかし、残り時間の管理はGameControllerがやっているので、時間切れを判断した時点で、GameController側がPlayerControllerDeath()メソッドを呼び出す必要があります。

 

とにかくまずDeath()メソッドをpublicにしないといけません。

C#だと未指定は全てprivateになります。

public void Death(){ //死亡時の処理 }

それからGameControllerがアクセスするようにする必要があります。

もしstaticを使えば、直接GameController.Death()とかけますし、

  

あるいは、リファレンスからアクセスすることもできます。

PlayerController playerController;

void Start() {

    GameObject player = GameObject.FindWithTag("Player");

    if(player != null) playerController = player.GetComponent<PlayerController>();

}  //この際、プレイヤーにキャラに"Player"タグを設定しておく

Startメソッドで、シーンがロードされた時にFindWithTagを使って、プレイヤーのゲームオブジェクトを引っ張ってきます。そこからアタッチされているスクリプトに対して、GetComponentを使って、参照を得たPlayerControllerのオブジェクトplayerControllerからアクセスするという方法です。

playerController.Death(); という風に呼び出せるわけです。

このように面倒ではあるんですが、安全性のためには致し方ないというか。

 


またスコア表示についても考えてみたいと思います。

プレイヤーがコインを取った数を画面上に表示するとします。

コインの当たり判定はPlayer側でやって、カウントもそこでやっています。

 

画面に表示する処理はGameController側です。

なので、変数はint coinAmountとするとして、GameController側がこれを取得する必要があります。

もしpublic static int coinAmountとすれば、

PlayerController.coinAmountという風に直でアクセスできます。

あるいは、プロパティ自動実装を利用して、

public int CoinAmount{ get; private set;}

という風にして、前述のオブジェクトからアクセスする、という風にも出来ます。

coinText.Text = playerController.CoinAmount ;

という感じですね。

 

しかし、GameController側にスコアを表示するというメソッドを用意して、Player側がそれを利用する、というやり方も考えられますね。

どちらがいいかをどう判断するかが、オブジェクト指向の難しいところだと思います。 

 

まとめ!

クラス自体がよく分かっていない頃は、アクセス修飾子というものの存在意義がよくわかりませんでした。クラスというものの働きが分からないと、アクセスする、という概念自体がまず理解できないからです。

あとプロパティも意味不明で辛かったですね。要はいろんなソフトにもプロパティがあって、そこでいろいろ設定できる、あのプロパティと基本的に同じなんですけど、なんでわざわざ必要なんだろう、という感じだったので。 

 

でも基本的な考え方については、それなりに分かるようになってきたし、今回このような形で、学んできたことを自分の言葉でまとめられたのでよかったです。

で結論を言えば、やはりどう分けて、どう連携させるか?ということになってくるわけですが、まだまだ難しいですね。鍛錬を続けたいと思います。

 

 

MadeWithUnity探検隊!! [3] == "Pantropy" == (開発中)

久々のMadeWithUnity探検隊は、まさに探検をテーマにしたゲームです。

現在開発中の"Pantropy"(パントロピー)についての情報を、簡単にまとめておきたいと思います。まだα版ということで、早期アクセスがあるにしても発売はまだ先だと思われます。PVは単純にすごいかっこいいです。

 


 

未開の惑星を探検!

公式サイトはこちらになります。英語のみ。後述で情報はまとめてます↓。

いわゆるクラフト要素アリのオープンワールドFPSのMMOですね。

PVを見た感じだと、HALO(ヘイロー)風の世界観のSF系FPSで、なによりメカがあるのが個人的に熱いですね。この手のタイプのゲームはたくさん出てますが、リアルよりでSFはあまりないのかなと思います。"Destiny"とかありますが、あれはミッションがメインのシューティング寄りですし。恐竜世界ではありますが"ARK"とかが近いのかな?あれは恐竜を使役できるようですが、それがメカに置き換わった感じでしょうか。

 

これがMadeWithUnityというわけで、やっぱりこれくらいできるんだなーってテンションが上がります。グラはスゴイきれいですね。

 

αゲームプレイから

マルチプレイがメインで、ゲーム内で10平方km!もある惑星の孤島を舞台にいくつかのグループに分かれて資源などを奪い合う、というゲームのようです。

正直、この手のゲームとしてはそれほど新しい要素はないかと思われますが、後発だけあって、いろいろ洗練されていそうではあります。

こういうタイプのゲームってキリないじゃないですか?なんで、やるにしてもちょっとやって満足!って感じでちゃんとやったことはないんですけど、これはロボの良さもあって、しっかりプレイしてみたいですね。

 

Youtubeに海外の方のテストプレイ動画がありました。少しウルサめ。

戦闘などはなくクラフトや散歩中心の内容なんで特に見る必要はないかと。まぁαバージョンですからね。でも景観というか雰囲気はやはり良いと思います。

クラフト周りはいつもどおりで、鉱石を掘って集めて、溶鉱炉をつくって~という感じであえての説明は不要でしょう。一応、終わりの方でライフル銃は作ってますね。

 

ゲームの内容

簡単にですが、公式サイトからゲーム内容についてまとめてみたいと思います。

 

目的

 このゲームではFaction(派閥の意)と呼ばれる団体に属することで協力しあい、限りある資源を求めて、他のFactionと競合します。Factionを中心としたゲームプレイとなり、チーム内の結束が重要になります。

 

クラフト要素

 プレイヤーはあらゆる"モノ"をクラフトすることができます。建物も建造できます。

アイテムのクオリティはプレイヤーのクラフト能力に依存するので、熟練したクラフトマンは尊重されます。強力なアイテムは、より長いリサーチ(後述)と貴重な資源が必要。

 

リサーチ・システム

 パントロピーの世界のテクノロジーをリバース・エンジニアリング(解体、分析)することで、新たなアイテムのレシピを手に入れることが出来ます。リサーチ能力はクラフトの成功率や質に影響を与え、見習いは超テクノロジーを復元できません。

 

基地建設とエネルギーシステム

 過酷な環境では、基地やシェルターの建設は必須です。プレイヤーは様々な素材とデザインを組み合わせることが出来ます。発電機やリアクターは、エネルギーが必要なメカ、設備を使うのに不可欠になります。

 

NPCや他プレイヤーとの戦い

 パントロピーの世界は、野生動物を含む自然環境が広がっており、資源を求めての冒険は過酷なものになります。当然、敵対する他のFactionのメンバーとの遭遇もあるので、よりスリルに満ちた挑戦になります。

 

かっこいいメカ達!

 過酷な世界を生き延びるために、巨大兵器を製造できます。目的や状況にあった様々なメカを自由に作ることが出来ます。

 

成長システム

 プレイヤーは過酷な冒険を経ることで経験値を得ることが出来、それをつかって採掘能力、クラフト、リサーチ能力をレベルアップすることができます。より高い能力であれば、取れる鉱石量、作れるアイテムは増えていきます。

 

独自の生態系システム

 6つの異なる生態系システムにより、その世界観をより深いものにします。

 

グルーピング・システム

 グルーピングシステムにより、より柔軟な協力プレイが可能に。

 

拠点襲撃

 採掘基地などのFactionの設備は、敵対団体に検知されます。なので、そういう場所はすなわち交戦の場となります。

 

20以上の個性的な武器

 プレイヤーの自由なプレイスタイルに合うような様々な武器が用意されています。近接武器だろうが、戦術的核ミサイルだろうが。

 


・・・こんな感じでしょうか。めっちゃ直訳風ですね。クラフト要素に比重を置かれたFPSって感じになるんでしょうか?たのしみですなー。

 

まとめ

とにかくメカ、SF好きにはたまらないMMOになりそうではあります。

今年中に大きな進展があるかないか?本格始動は来年でしょうか?

ともあれ現在、αのクローズドテスト中なので様子を見ていきたいと思います。

 

 

プログラミングの本で、コードをページにまたがらせるな!! [ 小ネタ ]

小ネタというか、小言というか。タイトルの通りです。

でも、実際かなり切実な願いですよ。

ただでさえ初心者はコードを読むこと自体が難しいし、キツイです。コードがページによって、分断されるなんて嫌がらせみたいなもんです。読みやすいコードを書こう!と言いつつ、読みにくい本書いてどうすんの?という文句のひとつも言いたくなります。
 
でもイライラしたら負けです。
  

コードの流れを掴む

C#などのオブジェクト指向言語は、コードがクラスによって分割されています。もちろん意味のある分割のされ方をされているわけですが、実際のプログラミングにおいてはそれらのクラスが交互に絡み合うことになります。よってコード全体の流れというのはバラバラになってはいるわけです。
 
しかし!以前に、コードの流れについての記事を書いたように、コードというのは自然な流れとして、この上から下にという力学が働いています。本質的には命令が上から下に順に実行されているということです。
 
オブジェクト指向であっても、少なくともある範囲の中では、厳密にこの法則に基づいてコードが実行されていきます。
 
ページに分断されたコードを読むと、これが身につかなくなってしまうのでは?と感じます。いちいちページをめくってコードを読むのも単純にめんどくさいんですよね。
 

理想のレイアウトとは?

なので理想としては、せめてひとまとまりのコードについては、一つのページ内にまとめてほしいわけです。というわけで自分の考える理想のレイアウトはこれです↓。

f:id:miur-us:20170731223121p:plain

見開きの左のページにはコードを。右側には解説文を、というようなレイアウトです。コードと文章をきっちり左右に振り分けるというスタイルですが、コード側にもポップを使い、随時解説を挿入していくという体裁です。
 
自然言語とプログラムコードを混ぜると混乱するので、このように物理的に分けてしまうのが、絶対的に見やすいはずです。
そんなプログラミング本見たことねー!紙面とか印刷費の都合なんでしょうか? 
しかし、見易さというのも大切な考え方だと思うんですが・・・うーん。
 

まとめ!

まとめることもないんですが、とにかくよくわからなかったら本のせいにしてしまおう!ということですかね(^o^;)

初心者だからこそシンプルなコードでいいし、そして何より見やすい分かりやすい本であってほしいわけです。

しかし、C#本に関してはそのような本が(おそらく)ないので、初心者向けの言語でありながら、初心者殺しな状況になってしまっているのかなぁ、というのはこのブログで何回も言っているわけですが。

実際、プログラムの本質が分かれば、確かにC#は『簡単』で分かりやすいんですが。

というわけで小言でした。m(_ _)m

 

 

ゲームのプログラミングにおいても重要な『列挙体』 "Enum" について。

人間にとって、意味のない識別番号を読みやすく、理解しやすくするために、列挙体"enum"は重要な存在!

※2017/07/12 じゃんけんの例を追記 

ゲームと列挙体

ドラクエのやくそう、ポケモンモンスターボールなど。ゲームにおいて、アイテムというものは無くてはならない存在です。

これらのアイテムにはプログラム内部で、それぞれ識別番号が割り当てられています。おそらくこの二つのアイテムは序盤から出てくるアイテムなので、一桁台の番号が割り振られているのだろうと思います。

 

プログラムのアイテムを使うメソッド、例えばUseItemの内部の処理は、この数字に応じて、その処理を分岐させているとします。このような分岐の場合、switch文の方がいいかと思いますが、わかりやすさ優先でif文として書きます。

if ( item = = 1 ){ //やくそうの処理。対象のキャラのHPを回復させるコード }

この"item"はプレイヤーが使用する、アイテムの番号がストアされている変数になります。ここでの"1"というのは、やくそうに割り当てられた数字ですが、数字自体には意味がありません。機械的に割り当てているからです。

 

このように、何らかの項目、状態を表すのに機械的に数字を割り当てるが、数字自体に意味がない場合は列挙体"enum"を使うのが良いとされます。

 

なぜ列挙体を使うべきか?

それは、人間にとってわかりやすいからです。

数字自体に意味がない場合、コンピュータには分かっても、人間にはその数字が何を意味するか分かりません。

前例のコード"1"は薬草を表していますが、これを人間が理解するためには、資料のアイテム表に書いてある、No.1の項目をいちいち確認しなければなりません。

アイテムが10個ぐらいだったら覚えられるでしょうが、現代のゲームのアイテム数は軽く100を超えるでしょうから、これは大変です。

 

読みやすいコードに!

読みやすいコードを書こう!ということは散々繰り返し目にしますが、そのための具体的な対策のひとつとなるのが、列挙体かもしれません。

enum Item{

Stone,

Yakusou,

Water,

Wine,

Beer,

Bread,

Bell,

//以下略

}

数字を特に指定しなければ、自動的に0から割り当てられます。この場合、Stoneには0、Wineには3が割り当てられています。

よって、薬草のコードは次のように書き直せます。 

if( item = = Item.Yakusou ) { player.HP += 20;  }

これでわざわざ資料のアイテム表を確認しなくても、コードを見るだけで分かる説明的な、自明なコードになりました。

やくそうを使って、HPが20回復する!とすぐに分かります。逆に、もし処理文がplayer.HP -= 20;とかになってたら、やくそうでダメージ食らうわけないよな?と考えますし、そういう意味で間違い防止にもなります。

アイテムだけではなく、武器防具にも使えますし、キャラクターの状態、つまりノーマル、毒、マヒ、ねむり、せんとうふのう、を表すのにも有用なようです。

 

じゃんけんの手の形

また、じゃんけんの手の形を表すのにも列挙体を使うことが出来ます。

グー、チョキ、パー0,1,2で表すとします。 

0は丸いので、ぎりぎりグーと見えなくもないかもですが、他は意味不明です。

さらには、じゃんけんの優劣関係により、0は1に勝ち、1は2に勝ち、2は0に勝つ、ということになり、さらに意味不明になってしまいます。

しかし、列挙体を使えば・・・

enum HandForm{

Goo,

Choki,

Pah

}

というように書き表すことができ、わかりやすいですね。

 

Unityにおける列挙体"enum"

せっかくなので、ブログのテーマ的にもUnityの中で列挙体がどう使われているかという実例を見ていきたいともいます。

  

CusorLockMode

Cusor.lockStateと併せて使います。マウスカーソルの状態を示すenumです。PCゲームの場合、ゲーム中PC側のカーソルを動かしたくないときに、

Cusor.lockState = CusorLockMode.Locked;

とすると、動かなくなります。さらにCusor.visible = false;で見えなくします。まさしく、何かの状態を表すのに使われていますね。

Rigidbody ForceMode

RigidbodyのAddForeceメソッドのオーバーロードとして、ForceModeが用意されており、力の加え方を選択できます。ForceMode.Impulseは爆発やジャンプの際の力の加わり方を表すのに使われます。

rb.AddForce ( Vector3.up * jumpForce, ForceMode.Impulse );

Force, Acceleration, Impulse,  VelocityChangeという4つの状態が含まれます。

 

まとめ!

というわけで簡単にですが、列挙体の有用性について、まとめてみました。

はじめは列挙体という名前にピンと来なかったんですが、わかってくるとゲームを作る上で無くてはならないものだとわかり、その有用性に感動しました。

読みやすいコードを書くのに、こんな便利な道具があるんだと!

上手く使いこなせるようにしたいです。

 

 

C#の攻略本はない、という記事の改訂について!

もう半年も前になるんですね。

攻略本なんてないよ!という宣言とともに、自分がプログラミング学習をどう打開していったか、ということを書いた記事です。

 

で最近、この記事へのアクセスが多いんです。調べてみたら、C# 初心者』という検索ワードで、9番目ぐらいに掲載されるようになっていました!

いいのか?グーグル!?マトモなソフト開発経験のないトーシロだぜ!?

 

とは言え、ありがたいことではあります。しかし半年も前なので、今読み返すと内容的に不十分な点が散見できます。当時はブログを書く事自体、まだ不慣れだったですし。なので、これを機に大幅な加筆、修正を試みました。

書いた頃と比べて、プログラミングについての知見、視野は広がっています。その結果、かなり長くなってしまいましたが、入門者が陥りやすい、また自分自身がハマってしまったワナを含めて、多方面をカバーできたのかな、と思います。

改訂 第二版なんて仰々しすぎる気がしますが、まぁそれは気分です。

 

そんな訳で、無事改訂作業は終わりました。

というかUnity何処行った?という感じで、最近はプログラミングの話題ばっかになってますね。実際Unity環境が現在ないので、もっぱらプログラミングの本ばっか読んでいます。でもUnityについてのネタは、いくつかストックがあるので早く書きたいとは思っていてはいるんですけどね。(^_^;)

それでは、今後とも本ブログをよろしくお願いします!