simplestarの技術ブログ

目的を書いて、思想と試行、結果と考察、そして具体的な手段を記録します。

CubeWalk:インベントリシステムの構想

概要

長いことクライアントで閉じていた処理がサーバーで行われるようになりました。
simplestar-tech.hatenablog.com

ふわふわしているアイテム操作のイメージを少しずつ固めていく工程を記録してみます。
構想というやつです。

最後に具体的なアクションリストにして、次の記事からはアクションについて書いていきます。
リスト最後にたどり着いたとき、今回の構想を通して完成した絵が私の手元で見えるようになるでしょう。

現状

キューブを破壊すると
空気プリズム x 2 が、もともとあったキューブの位置に配置され
もとあったキューブを構成していた空気じゃないプリズム x 2 がインベントリに格納されます。

ここで疑問1
プリズムだけを置くことはできますか?

はい

f:id:simplestar_tech:20191120084123p:plain
証拠画像

どういう操作でプリズムだけを置けるように指示するか?

横暴なやり方かもしれませんが、アイテムはすべてプリズムとして
配置するとディフォルトでプリズムになるのはどうでしょう?

キューブを作って置けるようにするか?
はい、そうですね そうしたい

よし、では右クリック長押し中はアローキーで回転を選ぶことができますが
アローキーのすぐそばにある R Ctrl キーを押したら
キューブとプリズムA, Bが交互に入れ変わるというのはどうでしょう?
これでいこう

これならインベントリは一つのslotにプリズムだけを配置することができるようになります。
どちらかというと、プリズム x 2 でスロットに配置でき、ユーザーには Cube 単位で数えさせるのがいいかもしれません
アイコンもキューブとしてボックスに配置できて楽

R Ctrl でプリズムだけ置いたら、キューブの数が 0.5 とか
0.5の状態ではプリズムだけしか置けない形

インベントリ?

PlayFab を使うとアイテムIDと残数の情報がリストで返ってくる
UIでのインベントリはどのアイテムをどこに置いたかが重要になるので
サーバ側のインベントリのアイテムには、カスタムデータとして配置場所についての情報が付与されるべき

例えば9つのホットバーのスロットに 1~9 のインデックスが振られているとして
カスタムデータにslot-1をキーに 2 が設定されていれば、インベントリの情報を引いてきたら、そのアイテムはホットバーの 1 スロットに 2個配置されるとする。

ユーザーが編集したら?

先ほどのアイテムをスロット 1 から 2 に移動させたら?

UIでまず、どうやって移動させる?

それはアイテムビューを開いたとき、マウスカーソルが出てくるモードがあるので、そのときにクリックして
アイテムがあればアイテムをホールド、なければ何も起きない
ホールドしていた状態でクリックしたとき、スロットだったらスロットに配置する
スロットでなければ、外界に高密度キューブとして投げる

高密度キューブはベーシックなキューブではなくスタッカブルタイプとして、タイプとカウントを持つ
最大 255 個まで
slotに 99 個以上は置けないことにしてしまおう

一連の操作を行い、アイテムビューを閉じたときに
クライアントで累積したアイテムのカスタムデータの更新処理の内容をすべて一括でリクエス

リクエストの形式はアイテムインスタンスIDのカスタムデータの Slot-1 の内容をホールド Slot-2 にドロップ
Slot-2 を半ホールド、外の世界へホールドしていた分をドロップなど 数字に関する操作はリクエストしない

でもそうするとアイテムを外界へドロップするときの数の計算ができない

仕方ない、一つの操作ごとにリクエストをなげてみよう
そうした結果を反映させていけば、ドロップ後のキューブ情報をバイナリキャッシュサーバーへサーバースクリプトから正しくリクエストできる

具体的な操作はサーバーの CloudScript 側で実行して、インベントリのアイテム数の調整はサーバースクリプトが行う
ユーザー側のハックで様々な不正なリクエストは投げられるが、数だけは合うという形

外界へ投げるというのも、できるのでしょうか?
ここはできそうであると言っておく

アイテムがすべて一つのスロットにあるとは限らない

確かに 100個あるプリズム x 2 のキューブを 1, 2 のスロットに 50 個ずつ分けるかもしれない

どうやって分けるの?

左クリックだと全部ホールドするので
右クリックで半数をホールドする

左クリックでリリース
空のslotの場合は置く、空じゃなかったら交換してホールド

インベントリのカスタムデータには、どのslotに何個配分するか決める

クライアントから利用時はカスタムデータの、ホットバーのslotにあるときの個数だけを消費でき
同様にサーバーでもカスタムデータのホットバーのslotの残数を見ながら
実際のインベントリのアイテムのプリズムの数を消費して、配置する(という CloudScript)

slotには 2桁までしか入らないので 99個詰めたら、別のslotに格納されることになる
限界までアイテムslotとホットバーを使い切ったら
ブロックの破壊を試みても、空きがないことをサーバーで計算され、リクエストは失敗する

リクエストに成功したらクライアントでキューブが破壊されたことにしてしまうので、失敗したら何も起きないことになる

インベントリのカスタムデータを頻繁に更新

ゲーム開始時に全部拾ってきて、インベントリ操作で頻繁に行うが、そんなことできるのか

一応できる
UpdateUserInventoryItemCustomData - Microsoft Azure PlayFab Server API
キーとバリューのペアとなると
slotの一意な名前と、スロットに格納した数をつめると良さそうかな

ですね、slot- のプレフィックスが付いていたらアイテムとするとか
操作することによって対象のアイテムに対するリクエストが作られ
操作完了時にリクエス

サーバー側はリクエスト内容によってアイテム数に増減が起きていないことを確認する

アイテムボックス

プレイヤーのインベントリについては固まってきたが
ゲーム内では取得したキューブデータをアイテムボックスに格納して置いておくなどができるようにする予定…だったが
高密度キューブがその役割であり、基本的な操作に変わりはない

調査したがタイトルデータは使えなかった

タイトルのデータはキーバリューで自由に置くことができ、後からそのキーの値だけ取り出すことができるのか
確かに、しかしドキュメントによると
api.playfab.com
グローバルスタティックなデータの置き場であり、更新には 15分は要し
要するに、アイテムの置き場所として利用するなとのこと

仕方ない、ここは
断念

この世界にアイテムボックスなど存在しない。
インベントリという四次元ポケットはプレイヤーという存在にしか存在しないことにする
そうすればカスタムデータに Slot- * を詰めるだけですべてのアイテム所持の操作が可能になる

ログアウトすると、どうなる?

ログアウトは不慮の事故や悪意ある強制終了で発生したりしますので、終了処理を入れることは期待できない
最後にいた地点に特別なキューブが設置され…なんて考えていたけど、最後にセーブした位置に戻るというのが正しい。

セーブ時に特別なキューブを置けるというのはアリ
そしてそのキューブを破壊した時、プレイヤーのインベントリの内容が周囲に飛び散るというものを考えたりしている

ここで、不正のことを考えていた

例えば根気よく世界のキューブすべてを破壊してインベントリに収めるプレイヤーがいたら
そのプレイヤーによって世界が空っぽになるわけで

やはりサーバー側でアイテムの上限をチェックして
一定数以上 たとえば 99 個以上の元素キューブは手に入らないとします。

ただし、キューブ素材の合成によって消失と新しいキューブ または アイテムの生成は可能とすると
キューブの質量は保存されない

いいんじゃないでしょうか?
不便で、チートはできないけど、いやがらせの行動は行える

その嫌がらせ行動をする人間をログや、他のプレイヤーが観測できるというもの
プレイヤーを分類して色々と小世界に隔離したりして実験できるわけで

思い出してきたことに、それがこのゲーム制作の目的でした。
ユーザーには好きに楽しんでもらい、このゲームをもう一つの世界として、プレイヤーの心理を描かせ
人間がどれだけ社会性を持つ生き物だったのかを証明する

そういう実験を行い、世の中を変えていきたい。

結論、破壊的な行動を行い、ゲームをつまらなくさせてしまうプレイヤーを許可する
例えば、キューブを片っ端から掃除して、世界をすっからかんにしてログアウトして戻ってこないプレイヤーを認める
そういうことするのが人間であると認め、運よくそのプレイヤーが最後に記録したキューブを破壊した人がすべてのアイテムを再取得する

以上

実装ステップ

これから、次の項目について記事を作っていきます。

アイテム対応
1.R Ctrl でキューブ、SideA, SideB キューブと配置形状が切り替わる
2.インベントリ情報を受け取って表示する機能
3.マウス操作でインベントリのアイテムを移動できる機能
4.カスタムデータを更新するリクエスト CloudScript の実装
5.実際にリクエストすることによって、次回のアイテムビューで更新結果が反映されている様子
6.投げて物理挙動したキューブ、速度が落ち着いたら位置としてそこに固定される
7.セーブ用の特別なキューブを破壊すると、対応するプレイヤーのインベントリの内容が周辺に配置される