まえがき
2度の作り直しを経て、現在は VRoid Hub SDK 経由で VRM キャラクターデータを利用して Cube の世界を自由に歩き回ることができるようになっています。
www.youtube.com
バックエンドサービスの PlayFab の CloudScript から API Gateway と Lambda 経由で AWS の ElastiCache のデータを読み書きできるようになったので
再び Unity クライアントサイドで、キューブの選択と破壊、設置を行える仕組みを入れていきます。
前試作映像
参考までに前回、実装していた内容を確認
www.youtube.com
データ自体はすべてクライアント側で処理していたので、不正し放題でしたが、これからはクライアントまでマスターデータは降りてこず
世界中のプレイヤーとキューブのデータをサーバー上でやりとりすることになります。
大きな違いは、前作は FPS (主人公視点)だったのに対し、今作は自身のアバターを確認しながら進められるようTPS(三人称視点)で操作が進みます。
一人称視点は画面中央にカーソルを置けば、視点操作のみでブロックを選択できましたが、三人称視点はそうはいきません。
新しい UI
ゲーム内にて、カーソルを表示し、見えている範囲でカーソルで選択したキューブに対してアクションができるようにしてみようと思います。
いずれ FPS をサポートしたときも、同様にカーソルを使って視点を動かすことなくキューブへのアクションができるようになります。
Ctrl キーでカメラロックしたときに、ゲーム内カーソルが出現し、カーソルの先にあるキューブが選択できるようにしてみます。
simplestar-tech.hatenablog.com
でーきたっと…
選択されたことの合図
前作では透明で少し大きめのキューブを明滅させていましたが、今回は対象となるキューブが「もこ」っとアニメーションしながら膨れる
という変化で対応してみようと思います。
カーソルが当たっているキューブをどのように特定するか
選択ロジックをみてみましょう
using CubeWalk; using UnityEngine; public class CubeSelector : MonoBehaviour { #region SceneComponents [SerializeField] GameInputMode gameInputMode; [SerializeField] GameObject cursorCube; #endregion void Start() { this.gameInputMode.onChangeInputMode += OnChangeInputMode; } private void OnChangeInputMode(bool showCursor) { // カーソルが表示されているフラグを立てる this.existingCursor = showCursor; // カーソル表示中はカーソルキューブも表示する this.cursorCube.GetComponent<Renderer>().enabled = showCursor; } void Update() { if (!this.existingCursor) return; // スクリーン中のマウスポインタに向かってカメラからレイを作成 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); LocateCursorCube(ray); } private void LocateCursorCube(Ray ray) { // レイが CubeChunk にヒットした場合にキューブの位置を特定 if (Physics.Raycast(ray, out RaycastHit cameraHit, IntaractRayLength, LayerMask.GetMask(LayerMask_Level))) { Vector3 cubePosition = cameraHit.point - (cameraHit.normal * ChunkConst.CubeSide * 0.5f); Vector3 roundSource = cubePosition / ChunkConst.CubeSide; Vector3Int gridSource = new Vector3Int(Mathf.RoundToInt(roundSource.x), Mathf.RoundToInt(roundSource.y), Mathf.RoundToInt(roundSource.z)); Vector3 newCubePositon = new Vector3(gridSource.x, gridSource.y, gridSource.z) * ChunkConst.CubeSide; // 現在配置しているカーソルキューブの位置からずれたか確認 if ((this.currentCubePosition - newCubePositon).magnitude >= ChunkConst.CubeSide) { this.currentCubePosition = newCubePositon; // キューブデータの取得 // キューブを再配置 this.cursorCube.transform.position = newCubePositon; } } } Vector3 currentCubePosition = Vector3.zero; bool existingCursor = false; readonly float IntaractRayLength = 20; readonly string LayerMask_Level = "CubeChunk"; }
なるほど、法線とヒットした位置について丸めて、キューブの int 位置というものを特定しているようですね
カーソルが当たっているキューブに少し大きめのキューブを描画するテストを行ってみましょう。
チャンクの Layer を変更すると キャラクターが接地しない不具合を見つける
例の TPS アセットのキャラクターコントローラーの Layers プロパティを確認すると Default の Layer を利用することになっています。
グラウンドについては CubeChunk のレイヤーも見るように設定を加えました。(VRMにコントローラを割り当てるところ)
具体的にはここかな?
var vController = vrmRoot.AddComponent<vThirdPersonController>(); vController.groundLayer.value |= LayerMask.GetMask("CubeChunk");
正解
新しいキューブの選択デモ
上記の実装を走らせると次の通り
youtu.be
まとめ
Unity クライアントサイドで、キューブの選択と破壊、設置を行える仕組みを入れていきたいとして
今回はキューブの選択を UI どうしようか想像しながら、一つの案を具現化してみました。
いずれキューブの情報を参照
キューブの破壊
キューブの配置
とステップを踏んで、オンラインデータを更新、参照する仕組みにつなげていこうおと思います。
今回はここまで