カテゴリー
制作

振る動作の見た目を試作

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

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

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

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

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

カテゴリー
制作

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

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

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

カテゴリー
制作

会話機能を試作

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

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

カテゴリー
制作

扉やら鍵やら実装

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

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

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

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

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

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

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

カテゴリー
制作

PAUSEを表示

前回に引き続き、ポーズ中に画面に文字を表示するようにした。
ヒエラルキーウィンドウで右クリック→UI→Textを挿入。
アイテムオブジェクトで試作したものと同じようなスクリプトを作り、Textにアタッチ。
スクリプトの内容はおよそ下記の通り。

  • タグから管理者用オブジェクトを見つける。
  • 管理者用オブジェクトから管理者用スクリプトを取得
  • 管理者用スクリプトの一時停止フラグを参照
  • 一時停止用中は文字列をPAUSEに変更する。
  • 一時停止解除中は文字列を空白に変更する。

UI挿入時にCanvasとその子オブジェクトであるTextの他にEventSystemというオブジェクトが追加される。
EventSystemではInputManagerで初期に定義されているボタンの名前(”Submit”など)を使用している。今のプロジェクトではボタンの名前を全て作り直しており、一致するボタンの名前が無いためエラーとなった。EventSystemは今のところ必要無いので無効にしておく。これを上手く使うとメニュー画面の入力操作などの実装の手間を省けるのかもしれないが。 最終的にはメニュー画面を表示したいので、文字列一つを変更するだけでなくまだまだ追加する要素がある。そもそも何を表示するか決まっていない。とりあえず所持しているアイテムの個数でも表示すればいいのだろうか。

カテゴリー
制作

ポーズ機能を試作

ゲーム中にいわゆるメニュー画面を表示することを考えて、ポーズ機能を作り始めてみた。
スクリプトの制御でtransformを直接変えたりしている場合は「一時停止フラグが立っていたら何もせずにreturnさせる」などでこれを停止させれば良いはず。
RigidBody を使っている場合は、一時停止フラグが立っている間Is Kinematicをtrueにすればよいと思ったが、これだけでは停止直前に働いていた慣性が失われてしまう。
そこで、停止時にRigidbody.Velocityの値をVector3変数にコピーしておき、一時停止の解除時にコピーした値をRigidbody.Velocityに戻す方法を試してみた。

フラグの管理はシーン管理者のブール変数で行う。
停止の管理が必要なオブジェクトは、シーン開始時にシーン管理者のタグから管理者のインスタンスを取得しており、停止フラグを参照できるようにした。負荷を軽くするため、停止と再開の処理は一時停止管理用のフラグが変わるときにのみ行う事にした。
各オブジェクトは、シーン管理者の停止フラグがtrueになったら、velocityの保存、IsKinematicフラグをtrueにするなどの処理を行ってから自身の停止フラグをtrueにする。
逆にシーン管理者の停止フラグがfalseになった場合は、IsKinematicフラグをfalseにし、保存したvelocityを取り出して自身の停止フラグをfalseにする。

後々アニメーションなどを追加するともっと考える事が増えるかもしれない。

カテゴリー
制作

シーン管理者を追加

前回、視線の先にあるアイテムを消すところまで実装したのでその先の処理を少しだけ追加。

シーン管理用のオブジェクトを追加。このオブジェクトはアイテム取得や管理以外に様々な管理を行う予定。Scene Masterのタグをつける。
シーンに配置されているアイテムはシーン開始時にタグを使ってシーン管理者を見つけ、Get Component関数でシーン管理者用のスクリプトを取得。アイテムがプレイヤーに拾われた際にシーン管理者のアイテム取得用の関数を呼び出す。拾われたアイテムのオブジェクトは破棄され、シーン管理者が管理しているアイテムの所持数を増やす。

一週間の進捗がこれだけではあまりに少ない。もっとメリハリ付けて作業を進めないといけないはずだが。
どうしても週末で気が緩むとだらだらと過ごしてしまいがちだ。週一のブログ更新とそのネタのための作業を何とかやってはいるが。

カテゴリー
制作

collider.SendMessageを実装

前回Physics.Raycastで一定距離のアイテム(などの対象物)に視線が当たっているかどうかを判定するようにした。
この時、レイが衝突した対象物に関する情報がRaycastHit変数に渡されている。
(RaycastHit名).collider.SendMessage((送るメッセージ)) で対象物の関数などを呼び出せる。この時呼び出される関数はpublicである必要は無い。
アイテム側にオブジェクトの破棄などの関数を作って呼び出すと、見た目上はアイテムを拾ったように見える。後で所持品に追加などの処理を追加していけばよい。

コントローラの入力スクリプトはプレイヤーとなるオブジェクトにアタッチしていたが、入力用のオブジェクトを独立させる事にした。
プレイヤーはコントローラで動かす頻度が高い対象ではあるが、いわゆるポーズ画面とかメニュー画面と呼ばれるものを呼び出しているときはコントローラが動かすものはプレイヤーではない。カーソルだったりスライダーだったりと、同じボタンでも状況によって動かす対象を変える必要がある。

カテゴリー
制作

Raycast

一人称視点でアイテムを拾えるようにするため、レイヤーマスクとレイキャストを使うことにしたので覚書を書いておく。以前も使ったことがあるけど、しばらく触らないとすぐに忘れてしまう。

  • Physics.Raycastによって得られる情報はRaycastHit構造体で受け取る。
  • Debug.DrawRay を使うとScene画面で確認できる光線を表示する。
    引数は 開始位置、向きと長さ、色、消えるまでの時間、カメラから隠れた線を描画するかどうか。
  • レイヤーマスクを指定するとビットが1のレイヤーに対してのみ判定を行う。
    ビットのシフト演算や反転などを使うとコードが分かりやすくなる。
  • DrawRay は方向も長さも一つのベクトルで指定するのに対し、Raycast はベクトルで方向、float変数で最大距離を指定する。

とりあえずProBuilderで適当にアイテムっぽいものを作って床に置き、レイを飛ばすスクリプトをプレイヤーのカメラにアタッチ。近づいて視線を向ける事でレイが当たっている事を確認できた。
上記でレイが当たるオブジェクトはアイテム用のレイヤーでマスクされている。
RaycastHit を使いアイテムにアタッチされているはずのコンポーネントを取得しメソッドを呼び出す、という流れでアイテムに何らかの操作ができるはず。

とは言ったものの全然進んでいない…。週末にまとまった時間があっても疲れていることを自分への言い訳にしている気がする。もっとモチベーションを高めるにはどうしたらいいのだろうか。
作品を作ることが面白すぎて止め時が分からない、という状態になるにはどうすればいいのか。それとも作品を作るのは楽しいというより苦しいけどやる、というものなのか。単純に作品をつくるという事に自分は向いていないのか。
…という事を考えるのもブログのネタになりそうではある。

カテゴリー
制作

プロビルさわってみた

ProBuilder のごく基本的なところを触ってみた。
アクションゲームのプラットフォームのようなものとか簡単な構造の建物なら習熟が浅くても作れそうだし、UV編集も何となくイメージは分かった気がする。雰囲気を出せるかはマテリアルとライティングそれぞれの調整のセンスに依存しそうだ。テクスチャに使う絵をまともに用意するとなるとそれだけでかなりの負荷が予想される。センスやらクォリティやらは後回しにして、まずは小さく作って動かす方が先だろうか。

特に斬新なアイデアがあるわけでもないので、既存の作品の劣化コピーにしかならない気がする…というと作っている身としてもモチベーションを保ちづらくなるが。どういう目的で何が作りたいのか分からなくなってきた。これではいつものパターンだ。
時間の使い方はまだまだ改善の余地がある気がするけど、仕事で疲れて帰ってきてから作業をするというのもなかなか骨が折れる…。週末は週末で息抜きしたいし。
しかし、世間で個人製作している人たちはその中で頑張っているわけだ。情熱とか覚悟とかが違うのかもしれない。ハングリー精神というやつだろうか。

あまり卑屈になっても仕方ないので次を考えよう。
アイテムを拾う機能の実装とか、会話の実装とか、メニュー画面の実装とか、簡単なプロトタイプで良いから作ってみることにしよう。