カテゴリー
制作

何を作りたいのだったか

ここ最近、いろいろと用事が重なったのもあるが制作が進んでいない。
敵キャラクターがプレイヤーを視認する方法を作ろうとしていたが、いまひとつモチベが沸かなくなってきた…。いっそ学習のためと割り切ってでもやりきるべきか。

自分が何を作りたいのか分からない。過去に自分が遊んだゲームの表面的なシステムや見たことのあるシーンをそれっぽくコピーしたいだけのような気もする。作りたいものがはっきりしないと仕様も決まらないし、仕様が決まらなければ実装するべき機能が決まらず、必要かどうかも分からない機能をダラダラと追加するだけになり終わりが無いのでは…。

学習のためなら学習のためと割り切って一つのテーマで完結する方がいいのだろうか。

量も質もまずはできる範囲でコンパクトにまとめるべきでは。

それにしてもこのブログも中身の無い記事を無理矢理更新している感じが否めない。何も書かないよりはマシなのだろうか。

カテゴリー
制作

プレイヤー視認方法を見直し中

敵キャラクターからのプレイヤーキャラクター視認方法を見直し中。

四角形の隅から隅までレイを飛ばすというのは効率が悪い処理のような気がする。

敵の視点からプレイヤーの位置に対するベクトルを計算し、プレイヤーの立ち位置が一定の距離及び角度の範囲内かつプレイヤーとの間にさえぎる障害物が無い時に視認する方法を試してみる。角度を扱うのに試行錯誤しそうではあるが。

こういう時はローカル座標とワールド座標の違いを意識しておく必要がある。

transform.TransformPoint(変換したいベクトル)

でローカル座標をワールド座標へ変換できる。

カテゴリー
制作

視覚と攻撃判定を追加

敵のモーションに続いて、レイを使った視覚判定と攻撃モーションの当たり判定を追加。

敵の視界は敵の目線の代わりにレイを飛ばして判定することにした。コライダで四角錘や円錐が使えればそうするのだが、基本形状に無いものだとうまくいかない気がする。
敵の目のあたりから例を飛ばす角度を少しずつ変えて平面上を走査するような方法にした。

敵の右手にダミーの武器を追加して、攻撃アニメーション時に当たり判定を行う。攻撃動作を行っていない時に攻撃判定が発生しないようにアニメーション時に判定有無を切り替え、武器を振る瞬間のみ攻撃判定を行う。この時に衝突したオブジェクトにプレイヤーのタグが付いていたらプレイヤー側でダメージ処理を行う形にした。

歩き回る機能、プレイヤー発見時や未発見時の挙動などはこれから作っていく。

もっとペースを上げないといけない気がする。

カテゴリー
制作

簡単な人型モデルを動かしてみた

3Dモデルを動かすとき、Unityではどうするのかとざっと調べてみたが馴染みのない言葉ばかりでしり込みしてしまった。

手っ取り早く動かすならモデルもアニメーションもどこかから持ってくれば良さそうなだが、できているものを使ってもいまいひとつ面白くない。
自分で中身を理解していないデータを持ってきても応用が利かなそう。
バージョンアップで動かなくなると自分でどうにもできなくなったりしないか。

できる範囲でやってみようと思い、まず立方体で胴体、腕、足、頭を作って簡単な人型のモデルを作った。
腕、足などをジョイントとなる空のオブジェクトの子オブジェクトにし、角度を指定することでアニメーションさせてみる。とりあえず某サンドボックスゲームで見たような歩行モーションや攻撃モーションが用意できた。
スクリプトから歩行の状態と待機の状態を切り替え、攻撃モーションを動かすことができた。

アニメーション機能はTransformやアニメーションパラメータ以外にも、アタッチされたスクリプトのパブリック変数も変化させることができるようなので、いろいろな使い道がありそう。

カテゴリー
制作

モーションを作ろうと思ったが…

敵の攻撃動作を作ろうと考えているうちに敷居の高さを感じ始めた。

攻撃動作を作るなら骨格を決める必要があり、骨格を決めるならそれが人間か獣か機械かなどを決める必要がある。
攻撃と一口に言っても人間が剣を振るか銃を撃つのか、獣が噛み付くのかひっかくのかなどで攻撃動作が変わる。

敵がどんな姿をしていて、どんな能力を持っているのか、など具体的な事がある程度決まっていないと攻撃動作を作れない。

3Dモデルが3D空間で動き回るという情報を肉付けするのはかなりの根気が必要になると思われる。

とりあえずこれを後回しにしてモーション無しで歩かせてみようとも思ったが、歩くアルゴリズムを考え始めるとまた課題が見えてくる。
視界に入ったプレイヤーに向かって真っすぐ突っ込んでくるだけなら実装は難しくないが、それではゲームとして単調になってしまう。
プレイヤーを見失った時はどうするか。
時間経過で持ち場に戻って待機するのか。探索しないと間抜けに見えてしまうが。
持ち場で待機しているときははただ突っ立っているだけなのか、歩き回るのか。
歩き回るならどこを歩くのか。ランダムなのか、決められた経路なのか。

これらのアルゴリズムの良し悪しがゲームの面白さにつながるのだろう。コーディングやツールの使い方といった実装する方法だけではなく、仕様設計でもはやり工夫が必要。

敵のアルゴリズムといえば、画面スクロール型のシューティングゲームの場合はこういった敷居は低いのではないかと思う。敵の動きは直線や曲線など単純で経路探索も不要のため、あらかじめ決められた動きで成り立つからだ。持ち場で待機するとかプレイヤーを探すという挙動も必要ない。

完成したものを公開するならどこを落としどころとするのか決める必要がある。
いっそのこと敵がいなくても成り立つゲームにするのも一つの手かもしれないが、それとも何とか頑張って素人なりのアルゴリズムで動き回る敵を実装するか。
考え事をするだけで全然進んでいない。
プロトタイプと割り切ってとにかく作ってみるしかないのだろうか。

カテゴリー
制作

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

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

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

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

カテゴリー
制作

4方向ランダム床 その2

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

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

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

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

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

カテゴリー
制作

4方向ランダム床

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

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

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

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

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

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

カテゴリー
制作

マップ生成が課題

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

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

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

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

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

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

カテゴリー
制作

コライダ有無の切り替え

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

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

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

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

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