Unityはじめの第一歩

無限に登場するまるとらをクリックしたら、隣接する同種を巻き込んで消滅するツムツムクローンを製作中。ツムツムやってことないけどルールは多分同じ。クリックしても隣接虎が消えない時があるんだよね、再現性は無くランダム。隣接判定にミス?クリックしたら消える虎たちをマウスオーバー時に半透明処理を施すと…。謎の明滅を開始。わけが分からなくて解決できず困った。

原因はわかった。Unityから呼び出される関数の順番によるエラー。各オブジェクトのUpdateが呼び出される順序は原則ランダム。優先順位が付けられるが、クラス単位での順位。インスタンス同士の順序はどうやるんだろ。相互に依存していて情報をやり取りしているとまずい場合があるね。通常のUpdateと物理エンジンのUpdateは別物だったことも原因。文字で説明すると面倒なので省略。解決したからOK

虎消滅時に小さい虎を多数登場させて分裂消滅させようと思ってパーティクル機能のお勉強を開始。パーティクルにアニメーションを設定できるから、絵の切り替えなしアニメを設定したら想定の動作をするはず、っていうか動作成功。虎の種類によって絵を切り替えようとしたところで絶望。startframeの数値を変えればできるはずだが、設定が反映されない。コードからの変更は出来ないの?まったくわからないから放置。最悪、手間ひまかけて数十個のプレハブに個別設定すれば解決…。うわめどい。

パーティクルは無視して次へ。

虎消滅後即座に他の虎たちが落下するけど、消滅時はすべてを一時停止したいよね。物理エンジン止めると全部止まってあかん。個別に止める方法あるかな?

Time.timescaleを変更せずにRigidbodyの一時停止&再開処理【Unity】【拡張メソッド】 – (:3[kanのメモ帳]

あったわ。速度と回転量を保持して復帰かー。そりゃそうか。ついでにプロパティと拡張メソッドを覚えたぞ!

一時停止と再開が出来るようになった。コレを利用して、消滅時に演出を表示しつつスコア表示してからゲーム再開の処理を組み込んでみよう。switchや関数ポインタでゴリゴリ切り替えても良いが、C#ってコルーチン使えるよね?調べてみるべー

UnityのCoroutine(コルーチン)でできる事のメモ – テラシュールブログ

消えるときに一時停止させることに成功。効果音も鳴らせたし、最低限の機能は把握できたのかしら?シーン遷移時にデータの受け渡しはどうやるのだろう。

WebGL版ぽち潰し

フォントが無いらしく、スタード画面でタイトル文字が表示されない。設定どこ?

つむつむやったことない

他のチュートリアルも見ておこう。まずはInterface & Essentials。これ超基本だけど知らない操作もあるだろうから全部見た!見終わった!これで!私!うにちーますたー!!

チュートリアルでちゃんと学べたのか試すために、ゼロからゲームを作れるか試してみましょ。

数時間後

ごめんむり。すべてのオブジェクトをコードから生み出そうとしたけど、そんな方法わからんがな。諦めて別の方法を取ろう。すべてのオブジェクトはシーンに配置しましょう。動的生成なんて後回しだ。

まるとらずを配置して、重力の作用で、画面外へ落下。床を作るためにイカちゃん海の家を配置。当たり判定をどうやって作ろうかと思っていたら、線分配置も対応してんのな。輪郭をなぞってコリジョン完成。ゲームだから、まるとらずがどんどん増えていって欲しい。つーわけでプレハブ作って動的生成だー!

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-18-01-15-54

イカちゃんがまるとらずを投げる感じ?下にどんどん積み重なる。

クリックしたら消えて欲しい。マウス位置とクリック検知を仕込み、まるとらずとコリジョン取ってDestroy(this)を記述したらあら不思議、バグ!Destroy(gameObject)にしないとダメなんだってさ。thisだとC#コードだけ外れる。罠すぎるわ。

隣り合うとらも消えてほしいけど、隣り合ってるって判定どうすんの?判定時にコリジョンを大きくしたらいいのかしら。衝突時に相手のIDを保存させる方が楽かな?って、コリジョン判定してくれない。小一時間悩み抜いた末

void OnCollisionStay(Collision collision)

ではなくて

void OnCollisionStay2D(Collision2D collision)

このように2D指定しないとダメだってさ!気づかんわ!!

修正したけど永久ループでUnityフリーズ。あー、相互に呼びあって終わらんわコレ。

処理を修正して解決したけど別の問題が発覚。見た目では接触して隣り合ってるようにみえるけど、隙間があって接触してないから消えない。ゲームとして作り込むと、見た目との相違でプレイにストレス溜まる?コリジョン大きく取って判定したほうが良いのかな。コリジョンだけスケール変更できたら良いのに…。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-18-01-15-55

exe、apk、ブラウザ上の3つで動作確認OK。このサーバにUPしての動作もOKであった。

C#のコード量は50行程度なんだよね。それでも苦戦中

sceneLoadedで詰まる

アンドロでの動作確認をいちいち実機でやるの面倒だよね。エミュレータ使えば楽になったりする?ってことで調べて

英語とか Unityで作成したアプリをAndroid Studioのエミュレータで動かす

エミュ動かせるまでにはなったけどさ、Unityでビルド&ランを実行したらビルドは瞬時に終わるんだけど、エミュへのインストールに5分以上かかってまじうざい。実機へファイル転送してからのインストするほうが時間が短いってどういうことだよ。エミュの出番ないじゃん!複数解像度試せる利点はあるから良いのか。何か設定が悪いのかしら?

エミュは一旦我慢するとして、サンプルコードに以下の関数が有りましてね

//This is called each time a scene is loaded.
void OnLevelWasLoaded(int index)
{
   //Add one to our level number.
   level++;
   //Call InitGame to initialize our level.
   InitGame();
}

OnLevelWasLoadedが非推奨になって将来廃止予定だよって警告がでるの。代替案があるんだろ?って探したらSceneManager.sceneLoadedを使えば良いらしい。あまり深く考えずに書き換えてみよう。要点抜き出すと

void Awake()
{
    SceneManager.sceneLoaded += TestSceneLoaded; 
}

void TestSceneLoaded(Scene sceneName, LoadSceneMode sceneMode)
{
    level++;
}

これで解結すると思ったらバグ発生。ローグライクでlevel1(1階層目)から始まるはずが2でスタート。次のlevelへ移動したら数値が+1ではなく+2される。なんじゃこりゃー。Awakeが複数回呼ばれてsceneLoadedへ関数2回登録したとか?調べたけどそんなことはない。Loadedがゲーム開始時に1回呼び出され、レベル変更時には二回呼び出されてる。なんで?

そもそも、Levelは1で初期化してんだよね。シーン呼び出し時に+1されるのだから、2から始まるのは当然か。最初のサンプルコードでは何故+1されず1でスタートしてんの?OnLevelWasLoadedが呼び出されてないんじゃね?調べてみると

Awake
OnEnable
OnLevelWasLoaded
Start
の順番で呼び出される。
Awake,Startはひとつのオブジェクトについて、一度しか呼ばれない。
しかし、OnEnableは、Enableされるたびに呼ばれる。

で、OnLevelWasLoadedが呼び出されてないんだがどういうことだよ。よくよく調べてみると、最初のシーンロード時はOnLevelWasLoadedが呼び出されないんだってさ。

わ か る か よ

名前見たらロード後に呼び出すとしか思わんわ。2回目からのロード時に関数が呼び出されるのなら、OnLevelWasLoadedの話は解決。次はsceneLoadedの仕様を解かねばならぬ。解説ブログをぐぐり

  1. Awake
  2. SceneManager.sceneLoaded
  3. Start

の順番で呼び出しが発生すると判明。つまり

Startでメソッドを登録すると最初のシーンでは実行されず
Awakeでメソッドを登録すると最初のシーンでも実行されます

あーなるほど、そういうことか。

わ か ら ね ぇ Yo!

結論として

void Awake()
{
    //SceneManager.sceneLoaded += TestSceneLoaded; 
}

void Start()
{
    SceneManager.sceneLoaded += TestSceneLoaded;
}

void TestSceneLoaded(Scene sceneName, LoadSceneMode sceneMode)
{
    level++;
    InitGame();
}

こう書けば良いのでした。

【Unity】OnLevelWasLoadedとSceneManager – うら干物書き

Unityローグチュートリアル完了

2Dサンプルなローグゲームチュートリアルを無事に完遂。本当に基本だけのチュートリアルだから、色々いじって使い方を覚えていくのが妥当。何を変えようか。イカちゃんローグの絵を持ってきて貼り替えるところからやってみる?

それはともかく、Winデスクトップアプリ以外にAndroidなAPK出力にも成功。スマホとガラホに入れて動作確認もOK。WebGLが選べたのでやってみたけど、ビルドに30分近くかかったんだよ。この規模が小さいソフトでこれって…。なおかつブラウザで正常動作しないオチがついてきた。chromeとfirefoxどちらもアウト。こりゃどうにもならぬ?何か設定あるんかね

無料の3Dモデルが無いかと探していたら

ImagineGirls – ImagineGirls オフィシャルサイト

エロもOKらしいよ。

二択:英語orポルトガル語

Unityの書籍は手元に2冊あるけど、今作りたいゲームとは方向性が違うので封印。Unity入門や学習個人サイトがたくさんあるけど、ちょっと肌に合わぬ。公式サイトにあるチュートリアルで学んで全体を把握するのが最初は良いかしら?ってことで

1

全部英語でござる。すべての動画に字幕を付けてる人が居るらしく、聞き取れなくても安心。一時停止して英文読めば何とかなる程度のレベル。英語わからなくてもコードと操作方法を見ればわかるよ。んなわけで2Dの基礎とローグタイプを題材に簡単なものを模写なう。

日本語訳は無いけどポルトガル語はあるんだよ!何故ゆえに…

Unityの中の人はもうちょっと頑張っていただきたいであります。みんな書籍出してるからそれ買ってくれ、で済ませる姿勢はわからんでもない。

数カ月ぶりの開発

オレオレエンジンにはGUI関連で仕様なバグがあるけど無害だったので放置していたのさ。GUIパーツにテキストや枠線を表示させるとスクリーン座標系で描画される。にょにょ時に作ったからそれで無問題。だけどな、今やっているのはすごろく。ワールド座標にパーツを配置してビュー座標系に変換しないと位置が狂う。枠線はデバッグ用だから放置しても良かったけど、テキスト表示は今後問題になるかもしれないがそんなことは無いな。でも一応直しておこう。

座標変換するだけだもの、修理は簡単であった。

ワールで座標でテキスト表示使う場所はあるのかねぇ。スクリーンだけで事足りるんだけど。

イベントスペースで同人ゲームfes

本日は同人ゲームオンリーイベント『同人ゲーム.fes』 | なのですよ。

2時まで酒を飲み、8時に目覚める素晴らしき一日の始まり。ご飯食べて艦これ任務をこなし、グラブルのAPとBPを消化したところで出発だー。電車の発車時間ギリギリだけどいけるやろー。

なんで今日はこんなにも券売機に行列ができているのさ。リュックを背負った子どもと母親が多い。なんかイベントあるのかね。連休だから散策っすか?んでもって当然のごとく電車に乗れずお見送り。いってらっさーい!

電車に乗り遅れるとか乗り継ぎ失敗とか、アクティブスキルだから気にしない。そう、絶対にだ!

最近知名度急上昇な裏なんばを経由してオタロードを歩いていると、肉屋の前でショタを発見。そういえばまぜのべ軍団で食べに来るんだっけ。声をかけずそっと隣につけて反応を待つスネーク動作。

なんやかんやで11時到着予定が20分頃到着。今回の会場は人通りが少ない場所にあるイベントスペース。4月にできたばかりで知名度低そう。メロン前から交番のある方を見たこっち。

1

奥の交差点に交番あるじゃん?あの交差点、携帯ショップがある箇所を右に曲がると。3

ゲソがおる!!!

4

違法侵略はイカンでゲソ。あのサークルの中の人が貼ったのかなぁ。犯人の特定が余裕すぎてどうなのこれ。

2

イベント会場はゲソ横のこちらとなっております。うわ、交差点から歩いて数秒。でも、この通りは普通通らないよな。遠くに見える看板、小さくて存在感が薄い。

6

書かれた文字も小さくて…。わかるか!

壁にポスター貼っても良いのかな?店長さんに許可をもらってポスターをぺたぺた。矢印的に貼ってみたけど、わかるかな?交差点で誰か呼びこみすれば良いよね。薄暗い内部へ入るには勇気がいるけど、店頭では女性声優さんが案内してくれるから大丈夫やろー。

5

筆者さんの代わりに売り子をするのさ。委託コーナーを兼任してるからRingletやイカゲームも。スペース配置的には一番奥。写真向かって右側にはステージがあるのさ。ここでアイドルたちが毎週末踊って歌って握手してフェロモン振りまいてファンがヲタ芸で血と涙を振りまいて?このステージにモニターを置いて試遊台にしたらもっと楽しめるかな?

ショタがまぜのべらー連れて顔を出しにきましたよ。おみやげがあるらしい。なになにくれくれー。猫ラベルの日本酒!いいねぇいいねぇ。え?つまみのあるの?なになにくれくれー。

7

いや、おかしいだろコレ。なおかつ青のりと削り節は開封済みよ?なんなの、昨夜おまいらでお好み焼きパーティーでも開いたの?

大正解であった。

おまいらの行動なんてすべてまるっとお見通しなのだわ!( ゚д゚ )クワッ!!

流石にイベント中は飲酒ダメだろ。イベントスペースだから酒というかカクテル売ってるけどさ。サークル側は呑めんわー。いや、飲むけど。イベント開始1時間を待たずして泥酔脱落する壁際スペース。誰もが疑わずその惨状を受け入れる流れが見える。まぁ、ワンドリンク制にしたら客が入らないだろうから酒の提供は断ったけど。次回はやっちゃう?

入れ替わりでパパが登場。本来は来る予定なかったけど、岡山のメロンとアニメイトが消滅していたから日本橋へ途中下車したのさ。お酒をもらったぜー、その名は白菊。白雪白露菊月を三体魔神合体。大奥って書いてるからケッコンカッコカリかよー!全員Lv100超えかよー!と騒いでいたけど、よく見たら大興。誤差だ誤差。きにすんなぁぁ。

場所が場所なので客は来なくてお通夜進行かと思われたが、結構来てくれた。全員が0枚販売を前提で二次会メインだったけど、予想を反しての大盛況。コミトレより売れるとかどうなの。やっぱり、コミトレは要らない子やったんや!コミトレって本とエロコス以外に参加する意味ないだろ。同ソ参加者も毎回減ってるだろ。独自に同ソイベントをやるのです。いろいろと企みはあるのです、企みだけは…、ふっふっふ。

意外と売上があり、サークルの中の人に売れただけとも言うが、二次会参加費ゲットだよ。今日は現金ゼロだからさっさと帰る予定じゃった。だって、孤児によって突然伊勢に連行されるんだもの、手持ちの金なんてなくなるってば。だが!よびのいちまんえんふだをよういしておいたのだよわっはっはっは。

…イカ、昨夜の出来事回想。

ハーフプライサーとしてイオンへ出勤。オラオラオラオラオラオラオラオラ!戦果を抱えてレジへ行ってワオンでお支払い。だけどな、残高たらんかってん。思わず1万円札出すじゃん?全部入金しちゃうじゃん?

…回想終了で頭を抱えるターン。

二次会行かなくてもお家にはパパ土産があるから一人宴会するもん。ええもん。そんなこともあろうかとおつまみ買ってあるし!でも、今日は売上があったから二次会いけちゃうね。いつもの山内農場へ行くよー。あそこは立地悪いから客少ないねん。団体で行っても余裕で入れるねん。

8

恒例の突き出しセット。キャベツときゅうりと特製味噌。この味噌がうまくておかわりを繰り返す。突き出しをお交わしし続ける謎団体は俺らだけだろう。一人きゅうり一本キャベツ3枚で380円。おそらくは379円が味噌代。野菜はおまけ。

ここで気が済むまで酒を飲み続けると以前のように記憶も飛んで支払いも忘れる流れだよなぁ。家に酒あるからさほど飲まなくてもいいよね。お初の人も多いし。メニューを眺めて飲んだ想像で楽しむ貧民。そう、ビール4杯ロック焼酎1杯なんてスタートダッシュ段階だよな。全然飲んでねーわー(アル中

喉の渇きを癒やすために最初はビールよりも水を頼んで飲むほうが経済的なのな。賢すぎる。

今回料理の写真はとってない。あおさ入りさつま揚げを頼んだけど、食感が全然さつまあげじゃないの。噛まずとも口の中でホロリと蕩ける。箸でつまみ上げるのも一苦労なほど。妙に甘くて青さと玉ねぎの味しかしない。これ、玉ねぎ炒めで良かったんじゃね?

締めにお茶漬けやラーメンを頼む人がでてきて、じゃぁ俺らは何を頼もうか。締めカレーってあるね。甘口と辛口の二択だぜ?中間を許さぬこの姿勢。辛口で行こうぜ!

9

辛さで涙目になるかと思ったが、そうでもなかった。

11

カレーにかけるウスターソースと醤油がセットだったの。かけるとマイルドで辛さが和らぐ。

二次会へ向かう途中、ATARIなゲーセンを探したけど見つからぬ。

kinacogames(@kinacogames)さん | Twitter

この人のところね。帰ってから調べたら会場から南下しないとダメなのな。そりゃみつからんわ。

レトロアーケード筐体がアツい!話題の大阪・日本橋のゲームセンター「KINACO」へ行ってきました! | そうさめも

動画があるから、年寄りはこれみて心ぴょんぴょんしとけ。

結論、売上以上のお金を宴会に注ぎ込むな危険。

同人サークルさんはお釣り用に小銭を持ち歩いているから死なずにすんだけどなー。

Win+あれこれ

AutoHotKeyを使っているのです。しかし、WINキーって色々使えるんなー。方向キーをJKLIに割り振ってるけど、Win+Lが先に判定されて→の代替として機能してくれない。しゃーないから<>にも左右を割り振って解決?デスクトップやタスクの切り替えが楽に。

左WinとCtrlを同時に押しっぱなしにする設定がわからん。

#SingleInstance force
vk1Csc079 & i::Send,{Blind}{Up}
vk1Csc079 & j::Send,{Blind}{Left}
vk1Csc079 & k::Send,{Blind}{Down}
vk1Csc079 & l::Send,{Blind}{Right}
vk1Csc079 & ,::Send,{Blind}{Left}
vk1Csc079 & .::Send,{Blind}{Right}
vk1Csc079 & u::Send,{Blind}{PgUp}
vk1Csc079 & o::<Send,{Blind}{PgDn}
vk1Csc079 & h::Send,{Blind}{Home}
vk1Csc079 & +::Send,{Blind}{End}
vk1Csc079 & p::Send,!{PrintScreen}
vk1Csc079 & f::Send,{Blind}{BS}
vk1Csc079 & d::Send,{Blind}{Del}
vk1Csc079 & e::Send,{Blind}{Esc}
vk1Csc079 & w::Send,!{F4}
vk1Csc079 & t::Send,<#{Tab}

またしてもデータが消滅した時用にペタリ。EscのつもりでWを押してよく死ぬ。NotePad++に自動セーブがあってよかったわ。「編集中だけど未保存で終了してもよいの?」って聞いてこないし。

今日はフィールド管理部のコードを整理して終了。

慣れると便利な予感

コルーチンをどう使えば効果的なのかわからないまま適当に使ってみた。コルーチンにする意味が無い関数をコルーチン使用に書き換え。想定通りの動作をしたので使い方はあってるね。今はサイコロを用意するだけの処理だけど、将来処理を追加しやすいはず。サイコロ振るときにセリフ出したり何かしらエフェクト出したり。

サイコロを振った後はマスを進んでいくわけであり、その処理をコルーチン使用で書き換え。これは書き換えの利点がわかりやすかった。一歩進むごとに指定秒待って次、って処理が書きやすい。というか見やすい。フラグ管理や関数切り替えはGoto並に把握しづらいからなぁ。

イカちゃんローグ制作時に組み上げたタスク管理は、コルーチン使えば無用っぽい。言語機能は使い倒さぬともったいないんなー。

はじめてのこるーちん

ゲーム開発復帰に向けてコルーチンの使い方を覚えるのです!
lua解説書やサイトを眺めて適当にコードを書いて……。基本は簡単ね。これを上手に活用するノウハウが無いから実践で試しつつ頑張ります。コルーチン生成は重い処理だから使いまわせってあるけど、とりあえずは逐次生成&破棄でいいよね。

コルーチンを使えば、今までスタックを活用して処理していた箇所をすっきり書けそう。書きなおさないけど。

今回はマウスだけで操作するから、キーボードで操作していた箇所を修正する作業から開始。難易度設定はボタンで表示させてマウスイベントを拾うように改造。とりあえずはそこまでやってからゲーム画面へ遷移させよう。関数群の使い方どころか存在を忘れてるから思い出しつつ。

1 2