カテゴリー
日記

習慣に改善の余地あり

最近の過ごし方を振り返るとまだ改善の余地があるように思える。

週一でのブログ更新を始めてから半年。
ノルマが達成できていること自体は良いのだが、逆に週に1回以上更新する必要は無いという感覚になりつつある気もする。もっと更新頻度を上げられるように心がけたい。

また、更新を後回しにしがちで日曜の夜に行っている点も改善する用が良い。
遅い時には日付が変わって月曜の2時になっている事もある。
宿題を先に片づけてしまうという意識で早めに取り組むようにするべき。

注意するべきなのは、自分にとってブログは自己管理のために書いているのであって、ブログを書くこと自体は目的ではないという事。ブログの他にもやるべき事があるので時間の使い方を見直す必要がある。

カテゴリー
制作

壁の高さをランダムにしてみた

作ったマップを歩いているともう少し景観に変化が欲しくなったので、壁の高さをランダムにしてみた。見分けがつきにくいので壁の上面に色を付けてみた。
進捗が少なすぎる。進捗と言えるほどの進捗でない。

敵のモーションを作ろうかと考えていたが、他の事をやりたくなってしまう。
剣や銃で戦うゲームはいくらでもあるが、ただそれをコピーするだけだと思うといまひとつ面白くない。学習としての意味はあるだろうけど。

そもそも何を目的としてこれをやっているのか。
学習か、面白いものを作りたいのか、副業での小遣い稼ぎを目指しているのか。
どれも当てはまるような気もする。
売りたいなら面白いものを丁寧に作らなければならない。
売る事よりもとにかく公開する事を目指しているだけなのか。それなら下手に風呂敷を広げずに手軽なものにする必要がある。いきなり3Dでは敷居が高いのではないか。2Dなら簡単とは言い切れないが。
結局、何を作りたいものかが煮詰まっていないような気もする。

カテゴリー
制作

4方向ランダム床 その2

前回作ったマップ生成のアルゴリズムのバグを調べているうちに初歩的なミスで全く見当違いの事をしていることに気づいたので修正。

生成アルゴリズムは一回の生成につき一回だけ呼び出すところを、記述する場所を間違えたせいでマップのマス目の数だけ呼び出していた。
初期化せずに床を何度も配置することをしていたので開始点周辺が床でほとんど埋め尽くされていた模様。

飛び石が起きる仕組みは詳しく解析できなかったが、上記のバグを直したら飛び石は見られなくなった。

床を100枚配置する設定で何度か走らせると、思っていたよりいい感じのマップができるようになった。マップ生成はひとまずこれで一区切りついたことにする。

次は敵の挙動の実装に取り掛かる。

カテゴリー
制作

4方向ランダム床

マップのランダム生成ができないか試行中。まずは単純なものから作りたいので、平面の方頑丈のマップに壁や床を配置する方法で考える。

ダンジョンマップを作る際の提条件として、どの場所もプレイヤーが歩いて到達可能であるようにしたい。到達可能にするには床がつながっているか、そうでないなら壁の向こうに移動できるテレポートのような手段が必要になる。

まず床がつながった空間を作る事から始めてみる。

一筆書きの要領で床を配置すれば途切れる事は無いはずなので、開始地点からランダムに上下左右の4方向に進みながら床を配置するアルゴリズムを作ってみた。

とりあえず動かしてみたが、開始地点を中心にごちゃっとした床の塊が配置された。
隣の床同士が隣接して塊になっているので通路らしい通路がほとんど無い。かといって部屋というには壁の輪郭が乱雑すぎる。しかも何度か繰り返すうちに飛び石の床ができる事もあるのでバグがあるようだ。この程度の単純なアルゴリズムでバグを仕込んでしまうのは情けない。

バグ修正とアルゴリズムの改善が必要。

カテゴリー
制作

マップ生成が課題

とりあえずダミーの敵キャラクターにスクリプトを付けた。
攻撃を受けたら体力にあたる変数を減らし、ゼロ以下になったらオブジェクトを破棄する。
攻撃を複数回当てると消えることは確認。

殺風景な環境での作業に飽きてきたので地形やマップの生成を実装しようと思い立った。
手始めに簡単なものから始めようと思い、立方体を敷き詰めてダンジョンのようなものをつくってみる。

2m四方の大きさの立方体をプレハブ化し、指定した位置から指定したサイズ分だけプレハブのコピーを敷き詰める。立方体の位置は今のところは2段階のみの単純なものとする。低ければ歩ける床となり、高ければプレイヤー侵入不可の壁となる。高さの概念が無いが、今は単純なもので進めたい。

マップの高低を2次元配列に記憶して、プレハブの配置位置を決める。ランダムな値により高低を決めて壁と床が配置されることを確認。

マップを自動生成できるようにすれば手間を省きつつ繰り返し遊べるが、マップを生成するアルゴリズムを考える必要がある。

…それにしても進捗が芳しくない。週一のブログ更新というノルマ自体は守ってはいるが作業進捗はたったのこれだけかと自分でも思う。真剣さが足りていないのではないか。

カテゴリー
制作

コライダ有無の切り替え

前回の判定がうまくいかない原因は凡ミスだった。
other. CompareTag(“タグ名”) とするべきところでotherをつけ忘れていただけだった。

カウンターで命中のタイミングを決めるという面倒な方法でやろうとしていたが、OnTriggerStayではなくOnTriggerEnterを使う方法に変えた。Stayだと「命中は攻撃一回に付き一回のみ」という処理を実装するのがややこしくなる。多段ヒットする攻撃があってもいいかもしれないが、それは後で考える。

攻撃判定用のボックスコライダを用意しておき、ゲーム開始時にはこのインスペクター上でこのコライダのチェックボックスを外しておく。武器を振り切るタイミングでコライダを有効にし、攻撃動作を終えたら再び無効にする方法で実装。
スクリプトとコライダを持つオブジェクトがあり、OnTriggerEnterなどでコライダから呼ばれる処理がスクリプトに記述してある場合、スクリプトを無効にしてもコライダから呼ばれる処理は動くようになっているらしく、コライダを切る事で衝突判定による処理を停止できた。

ついでに、武器を振るモーションをポーズや会話で一時停止するようにした。

次回は攻撃を受けた側の処理を作る予定。

カテゴリー
制作

振る動作の見た目を試作

武器を振る動作の見た目は試作をひとまず完了。

カメラに取り付けたスクリプトから回転の処理を行うようにしたら解決。
オイラー角やクオータニオンはまた別の機会に調べるとする。

次に攻撃が敵に当たる処理を作っていく。

武器そのものの形状で当たり判定を行うのは物理シミュレーションとしては正確ではあるが、恐らくゲームとしての快適さを損ねる側面が強いと思うため武器そのものとは別に攻撃の命中判定用のオブジェクトを作る。
幅と高さはおよそ画面より少し小さく、奥行きも適当に設定した直方体を作る。
できれば半円中や半球などにしたかったが、基本形状でないメッシュはそのままトリガーとして使えないらしい。

ダミーとして用意した敵に敵用のタグをつけて命中判定を行うことにした。OnTriggerStayでタグを見つけられる事は確認したが、武器を振り切った瞬間に処理をするというのがうまくいかない。
タイミングを監視するカウンタを設けて、OnTriggerStayの中で特定の値に一致または特定の値以上になった時に攻撃命中時の処理をするように記述したつもりだが、処理が行われない。
やろうとしていることは難しいことではないと思うが、自分の理解が不足しているようなのでまだ試行錯誤が必要。

カテゴリー
制作

オイラー角とかクオータニオンとか

視点移動の際に上下に際限なく回転してしまうことに気づいた。
直そうと思ったら回転の概念はなかなかややこしい。
オイラー角を計算して一定の範囲にない場合は上下の視点移動を無効化するようにしたが、もっと賢い方法があるような気もする。
回転にはQuaternionという概念がありVector3とは異なるらしいが理解できていない。

攻撃を実装しようと思い攻撃用の簡単なダミーを作成。
武器を振る動作を実装するためにカメラの前で四角柱を回転させてみたが、これもまだ改善が必要。振り回す動作中に視点移動すると武器の角度がどんどんずれていく。
動作開始時に初期角度を記憶、スケールを1倍にし、動作終了時にスケールを0倍にして初期位置に戻すという処理を行っているが、角度がワールド上の絶対角度で記憶されているのでカメラに対する相対角度を記憶する必要がある。同じ理由で振り回している最中もカメラの動きについてこない。
この処理はスクリプトに直接書くよりアニメーションを使う方が良いのだろうか。

カテゴリー
制作

会話機能を試作

ProBuilderでざっくりと人の形を作り、画面に文章を表示するようにした。
アイテム取得やドアの開閉とやっていることはだいたい同じ。
画面中央にレイを飛ばして、NPCに当たっていたら会話機能を呼び出す。
会話中は先に実装したポーズ機能を拡張して会話状態を設け、会話中も物理演算を停止させ、キー入力による機能を制限したり使い分けたりする。
とりあえず、話しかけたら画面に文字が表示され、キーを入力すると会話を終了し、画面の文字が消えるところまでは実装。

その他、アイテム、ドア、NPCに対してSendMessageを使っていたが、コライダからゲームオブジェクトのインスタンスを取得→各種コンポーネントを取得→コンポーネントのメソッドを呼ぶ、という形に変更。
SendMessageはインスタンスやコンポーネントの取得が不要なので手軽な反面、メッセージの受け取り側を一つにしていたつもりが複数になっていた、など管理を怠ると思わぬ落とし穴があるかもしれないと感じたため。

カテゴリー
制作

扉やら鍵やら実装

一時停止によるRigidbodyの停止をひとつのスクリプトにした。

個別のスクリプトで記述しなくとも、このスクリプトをアタッチすれば、シーン管理オブジェクトの一時停止フラグを見て、IsKineticの有効/無効を切り替えられる。Rigidbodyがアタッチされていることが前提。

キー入力を一時停止中と非停止中で分けた。一時停止中はキャラクターの移動操作をしないなどの使い分けができる。

Rigidbody以外の処理は各スクリプトで個別に停止することとした。
Time.timeScaleをゼロにする方法もあるらしいので試したが、使い勝手が良くない印象を受けた。止めたくないタイマーまで停止してしまう感じ。例えばメニュー画面を開いている間もゲームのプレイ時間をカウントしたいと思った時timeScaleをゼロにするのは良い方法ではない気がする。使い方をよく分かっていないだけかもしれないが。
ただし、個別に停止する場合は処理の止め忘れが無いようにしっかりとした管理が必要。

簡易的だが一時停止中に取得したアイテムの数を表示するようにした。鍵以外のアイテムの具体的な用途は決まっていない。

扉を想定した簡単なオブジェクトとスクリプトを実装。
扉の開閉はアイテムを拾う時と同じ要領で実装した。レイを飛ばし、当たった相手が扉用のレイヤーに設定されていたらSendMessageで扉オブジェクトの開閉用の関数を動かす。

扉ごとに必要なキーアイテムを設定できるようにした。開閉用の関数はシーン管理オブジェクトからアイテムの所持情報を確認し、該当するアイテムを既定の個数所持していない場合には扉が開かないようにした。