UE5でオンラインマルチ

7年前、Unreal Engine 4 で一度steamのフレンド機能を利用したオンラインマルチプレーヤーゲームを作ったことがあったが、その時はUEに対する理解度の低さやマルチプレーヤー特有の知識が必要でかなり苦労をした記憶がある。

あれから7年経ちUEも5になり、自分の制作知識や技術も上がってきたことで心理的・技術的ハードルがだいぶ下がってきたこともあり、そろそろオンラインマルチについてしっかり学んでおこうかなという気になった。
オンラインマルチプレイ機能の実装について躓いたところや学んだ知見を未来の自分のためにここに記しておく。


・Run on Server - Multicast という基本的な手法について

Run on Server は文字通りサーバーで実行だが、その後マルチキャストにしたカスタムイベントをつなぐという基本的な手法について理解が追いついておらずぼんやりとした雰囲気で当時は作っていた。
Run on Server は文字通りこのカスタムイベントはサーバーで実行しなさい、という命令で、その後ろにマルチキャストのカスタムイベントを置くと、サーバーでマルチキャストを実行しなさい、という命令になる。マルチキャストのカスタムイベントは全てのゲームクライアントで実行しなさい、ということ。
例えば、プレーヤーBが敵の攻撃を受けて血を流して死ぬとする。プレーヤーBのキャラクターBP内でその処理を書いてもプレーヤーBの画面でしかBは血を吐いて死なない。全てのプレーヤーの画面でBが血を吐いて死ぬ、という事象を発生させるには、サーバーから「みんなプレーヤーBの死を一斉に起こしてね」という指示が必要。Run on Server でマルチキャストのカスタムイベントを実行するというのはそういう理屈。サーバーに向かって、「”みんなにプレーヤーBの死を一斉に引き起こしてね”と指示しなさい」という命令をしている。


・レプリケートについて

レプリケートは、サーバー内で変更があったらその変更を自動的に随時受け取り更新します、という設定。重要なのが、クライアントで発生した変更を随時サーバーへ送ります、という機能はない。サーバーからクライアントへ一方通行。

例えば、プレーヤーはそれぞれヘルスという変数を持っていて、その変数はレプリケートがオンになっているとする。プレーヤーAのヘルスが初期値10で、プレーヤーAが毒薬を飲んでAのクライアントでヘルスが5になっても、サーバーでは10のままなので、自動的にすぐ10に戻される。ちゃんとみんなでヘルスの減少を共有するなら、Run on Server のカスタムイベントでプレーヤーAのヘルスを5にする必要がある。レプリケートされる変数であれば自動でサーバーからクライアントに同期されるので、マルチキャストは不要。


・一斉に全員にBP内のカスタムイベントを実行させる処理について

セッション参加直後、各プレーヤーに名前を入力してもらい、各キャラクターの頭上に名前を表示する、という機能を実装しようとしたとき躓いた。
名前を入力してOKボタンを押したら、キャラクターBP内のRun on Serverカスタムイベントへ飛んで、入力した自分の名前をplayer stateに保存し、マルチキャストで自分のplayer state から自分の名前を確認し、自キャラの頭上にそれぞれの名前を表示する、という記述をした。しかしこのロジックではだめで、他人の名前は表示されなかった。
これは先程のヘルスの例を思い出してくれれば当然なのだが、セッションに参加しているあるプレーヤー鈴木が毒薬を自ら飲んで自分のヘルスを-5し、それをマルチキャストしたところで鈴木のヘルスが-5されたという情報が同期されるだけである。全てのプレーヤーでヘルスが-5されるわけではない。
同様に、今回自分で書いた処理も、鈴木が「鈴木」と名前をplayer stateに保存しました、鈴木はplayer stateから自分の名前を確認して鈴木の頭上に表示します、というのがマルチキャストされているだけ。あらかじめ参加している佐藤や田中には、鈴木のクライアントでは「自分の名前を確認して頭上に表示します」という処理が走らないため、鈴木からは佐藤や田中の名前が見えない。一方で先に参加している佐藤や田中からは鈴木の名前は見える。
必要なのは、全プレーヤーが一斉に「自分の名前を自分のplayer stateから確認し、頭上に表示する」という処理。具体的には、Run on Serverで Get All Actors Of Class (CharacterBP) → For Each Loop で全てのプレーヤーのBP内にある「自分の名前を player state から確認し頭上に表示する」というマルチキャストのカスタムイベント を実行すればよい。


・オンラインでセッション作成や参加がうまくいかない時用のログの取り方

exeのショートカットを作り、プロパティ→リンク先を "場所” -log としてOK、ショートカットを起動するとログも表示される。


・Steam経由でセッション参加時のビルド不一致エラーについて

オンラインマルチ開発中は steam app id = 480 を使うと思うが、これが原因で問題を起こしていて悩んだ。
セッション検索機能を実装せず、セッションへの参加を自動にしている場合、これのせいで見知らぬ人の見知らぬゲームに参加しようとする場合がある。当然違うゲームなのでできない。セッション検索機能で知らない人のゲームが引っかかるのも煩わしいので、自分のゲームだと識別したい場合、自分でKEYを設定できる。Make Literal Session Property String で適当な文字列の組み合わせを鍵代わりに作って、Extra Settings に追加した状態でセッションを作ればよい。検索する側は、ForEachLoopで、その鍵と同じ文字列かどうか確認していく。画像を見た方が速いので画像を貼っておく。



・マルチプレイでP2P接続を拒否られるエラーについて

SteamセッションはみつかっているのにP2Pが確立できない場合、相手のWindowsDefenderが悪さをしている可能性がある。
Windows Defender ファイアウォール → 詳細設定 → 受信の規則 → 新しい規則
ポート → TCP → 特定のローカルポート:7777 → 接続を許可 → 全てチェック → ゲーム名とか適当に名前つけておいて完了
同様にUDPポートも開いておく


・一度セッションに参加してAlt+F4でゲームを終了すると、再度ゲームを起動した時に画面が真っ暗になる問題

DestroySessionしないとSessionが残る。




またどこかで引っかかったら追記していく。

窓を自動で配置

前回の記事の続き。

box と box を boolean subtract して窓枠を作る
nゴンがきもいので polydoctor ノードでnゴンを殺す
(III-Formedとかをいじってれば四角になる)

grid から attribute wrangle の左から二番目の入力ピンへつなぐ
一番左じゃないからな
一番左はオブジェクト全体がぶっこまれる
二番目は参照

run over = detail (only once) に設定

コードを書く

vector p_start = point(1, "P", 1); // Gridの左端
vector p_end   = point(1, "P", 3); // Gridの右端
float WallLength = p_end.y - p_start.y;

float pointA = p_start.y + WallLength * 0.25;
//float pointB = p_start.y + WallLength * 0.5;
float pointC = p_start.y + WallLength * 0.75;

vector newpointA = set(p_start.x, pointA, p_start.z/2);
//vector newpointB = set(p_start.x, pointB, p_start.z/2);
vector newpointC = set(p_start.x, pointC, p_start.z/2);

addpoint(0, newpointA);
//addpoint(0, newpointB);
addpoint(0, newpointC);  

壁の端から 1/4, 2/4, 3/4 の位置に窓がきてほしいので

Y軸方向はその座標を代入、
x,z座標は元々の位置を代入
ただ実際にこの間隔で窓を配置すると窓の間隔がほぼゼロのギチギチ状態になるので
真ん中位置の窓は設置されないようにコメントアウトした

addpointの仕様について
addpointは引数(vector)の位置にポイントを追加する。
addpoint(0, vector)
引数の0は現状なんの意味もなく0を入れておく。(将来的に機能が追加される予定)
vector のところには 座標(x,y,z)を入れる。

あとはcopytopointsノードで窓のオブジェクトを追加したポイントに配置する。
以前作った壁とmergeして終わり。

 

 



壁の両端に柱を自動で設置する

Houdini apprentice版で練習
はじめから有料版なんていらなかったんだ
前提としてY-UPはきもいのでZ-UPでやってます
Z-UP教徒だから鳥居くぐれないんです

家をプロシージャル的なジェネレーター的な自動で作ってくれる的なあれ的なのを
作る的な目標でいく
今回はとりあえず壁の両端に自動で柱を設置してくれるようにしたい

ノード置き場で右クリック
Geometryと入力してGeoフォルダを作成

ペラポリを作るにはgridノード
orientation を YZ Plane にして壁状に立てる
Rows と Columns を 2 にして不要な分割を消す

この状態だと半分地面に沈むので
Centerの値をSize(高さ)の半分にするようにしたい
Centerのtzに ch("../grid1/sizex")/2 と入力する

この grid1 を壁とし、両端に柱が自動で配置されるようにしたいので、
grid1 に group ノードをつなぐ。
groupノードは何をするノードなのかというと
シンプルに複数の頂点をグループとして保存するのみ。
このノードを使って両端の頂点(Z=0のふたつ)をEndpointsという
名前で保存する。
具体的には以下のように設定する。

Group Name = Endpoints
Base Group = 0 2 

これでとりあえず壁と壁の端部分の頂点情報を用意できたので、
柱を作る。

boxノードを使って立方体を召喚。
これもまた半分地面に埋まってる状態なので、
Centerのtzに ch("../box1/sizez")/2 を入れ、
サイズにかかわらず地面にめり込まないようにする。
Sizeのsizezは ch("../grid1/sizex") とし、
grid1 の高さを参照する。

box1をgridの両端に配置したいので、
copytopointsノードを使う。
右に先ほど用意した壁の両端の頂点情報、左にbox1をつなぐ。
この状態だと座標を取られて用済みになった壁は消えてしまうので、
copytopointsノードの下にmergeノードを置いて
壁と柱を合成させる

とりあえず今回はここまで。

腱鞘炎の手術をしました

1日9時間くらい絵を描き、その合間の休憩時間にピアノを弾いたりDOTA2をする生活を
数ヶ月続けていたら手首が死んだ
マグカップを持つことすらできないくらい痛くなったので整形外科へ
湿布をもらったけどそれで完治するはずもなく
麻酔科で毎週手首に麻酔をお注射をしてもらっていた
麻酔をすると痛みがなくなるので夜ぐっすり眠れるし絵も描けるので
ウキウキで麻酔科に通っていた
その様子を見て麻酔科の先生は「注射痛くないんですか?」とちょっと引いていた
タバスコマンは痛みに対して鈍いので気になりませんでした。
麻酔科で注射(麻酔のみ)を打ちすぎて保険適用できなくなり
毎月の医療費が無視できないコストとなったので
大学病院で手術を視野に入れつつステロイドを注射
DOTAやピアノをやめても結局すぐ痛くなってしまうので
手術決定

手術のリスクとしては麻痺(しびれ)が残ったり
寒くなると疼いたりという一般的な外科手術のものに加え
手の使いすぎで腱鞘炎になったのなら術後も使いすぎたら痛くなるし
腱鞘を切開したところで手の痛みが全てなくなるわけではない、
という説明を受けました。

右手の上腕を圧迫して血流を止めた状態で手術開始
右手全体にこれでもかとアルコールを塗りたくられ切開される
詳しい様子は布の仕切りのせいで見えなかった
自分の体が切り刻まれる様が見たかったのにがっかりですよ
その後麻酔が弱くなってきたのか、圧迫されているせいで右手が痺れてきて
だんだん痛くなってきたが
痛いなと思う頃にはもう手術が終わった

手術が終わってすぐ帰宅
痛み止めをもらったけど日中は痛みがなく
夜になると少し疼くくらいだったので寝る前にしか飲まなかった
あとはもらった抗生物質を1日3回飲んだ
夜に現れる痛みは4日くらいで消えた

手術当日の様子

創部は包帯で固定されていて一週間後包帯取るまで濡らしちゃだめということで
手にビニール袋をかぶせてヘアゴムで固定し
完全勝利した淫夢くんみたいなポーズでシャワーを浴びないといけないのがつらかった
右手に力が入ると激痛が走るので服を脱ぐときにも不便だった
さらに左手だと歯がまともに磨けないので
口からドブ川みたいな口臭を撒き散らす生活を余儀なくされた

1週間経って包帯を取ってからは透明のテープで保護されたが
これも濡れたら剥がれると言われたので
結局ビニールを手にかぶせて淫夢君のポーズでシャワーを浴びる生活に変化はなかった
ただ最初の一週間であった「できるだけ右手を心臓より下げないように」という指示がなくなったので
煩わしさは1%くらい減った

包帯が取れた後

さらに1週間経って抜糸
15秒くらいで抜糸してもう来なくていいよと言われる
病院で自分が呼ばれるまで30分待って診察が1分で終わるという
普遍的な病院の非合理性を感じつつ帰宅

予後良好

抜糸した後は手は普通に使って大丈夫と言われたものの
力を入れると創部が痛いので抜糸から一週間くらいは重い物は持てないし
縫ったところが突っ張って違和感があったりで
絵を以前のように描けるようになるまで2週間近くかかった
なのでアニメーターで腱鞘炎の手術を考えている人は1ヶ月は仕事できないと
見積もったほうがいい

術後一ヶ月経つが親指の第一関節あたりを触るとしびれた感じがして麻痺しているのがわかる
これは手術時に神経をどかした影響だが
数ヶ月すれば麻痺が消えるかもしれないし消えないかもしれない
ただ指が動かしづらいとかはないので個人的には全く気にしていない

肝心な痛みはどうなったかというと第3コンパートメントあたりに感じていた痛みは
とりあえず大きく減った
ただ絵を描き続けていると親指が痛くなってきたりと
手術した場所と関係ない場所でも疲れで痛みが出るので無理はできない

とりあえず腱鞘炎で手術しようか悩んでいるアニメーターがいたら
俺が言えることはこの一言だけ
DOTA2なんかやるな


以上


バラバラと崩れるアニメーション

Houdiniを買ったので手順メモ。

これを作る。



パーツがバラバラになってほしいが骨が砕けたりする必要はない。

以下手順

Houdini をやるなら誓わなければならない契りがある。
それはスケールとFPSの設定。後から変更しようとすると地獄を見ることになる。
スケールの変更は Edit - Preferences - HipFileOptions にある。
アクセスしにくいし HipFileOptionsという名前からスケールの設定が結びつけにくく不親切。



一方でFPSWindows - Global Animation Options から変更できる。

同じ Options なのにスケール変更は Edit にありFPS変更は Windows にある。
Options という項目を追加して設定関連はそこにひとまとめにしてほしい。
この煩わしさにイラついてから Houdini の作業は始まる。

FBXをインポート。今回はボーンのないメッシュのみで試した。
ボーンの入ったモデルでは未検証。



Houdini でノードを並べる場所をコンテクスト?だかなんとかと呼ぶらしい。
いちいち Houdini での呼び方を覚える気はないのでノード置き場と呼ぶことにする。
ノード置き場は至ってシンプルに、床、シミュ、モデルの構成。



Floor の中身は説明の必要がないくらい何もない。
他のノードフォルダで呼び出すときに Null を入れて
そこを目印(マーカー)として利用する。
とりあえずノードの最後に Null を入れておくと Houdini ができる人に見えるので

意味もなく入れることをおすすめ。
YouTubeチュートリアルを公開している人はよく意味もなく入れている。



dopnet の中身。



左上の RBD Object は 床を呼び出している。
Gravity の位置にかかわらず上にキャラクターが乗っていると
その重みで下に落ちていってしまうので
Create Active Object のチェックをはずす。
これで静的なオブジェクトになる。

RBD Object でスケルトンウォーリアーくん(以下、骨)を呼び出すこともできるが
これだとパーツがバラバラにならず塊のままパタッと倒れることになるので、
パーツをバラバラにするには RBD Fractured Object ノードを使用して骨を呼び出す。

床と骨を呼び出したので物理シミュを担当するノードである Bullet Solver につなぎたいところだが
Bullet Solver は2穴同時責めができないので一本しか入力できない。
そこで merge を使ってひとつにまとめる。

これだけ。

Houdini はノードを使っていくタイプなのでUE4はじめたての時のように
どのノードがどんな役割をしているのかをググりつつ進める必要があり
初めて Houdini を起動して試しに簡単なものを作るのに時間がかかる。
習得度の立ち上がりが遅いため初心者のうちはHoudiniを起動することさえ億劫になるのも必然。
1年のサブスクが 270 USD と聞くと一件安めなCGソフトにも思えるが
昨今の超絶円安により40000円もしたことを記憶にとどめ
Houdiniから逃げてしまっては4万円が無駄になると思いながら勉強をしていく。

次はボーン付きのモデルでアニメーションしながら崩れるのとかをやってみる。


参考
https://www.youtube.com/watch?v=XzlZDgr3s8c

https://houdinifx.jp/blog/%E3%83%AA%E3%82%B8%E3%83%83%E3%83%89%E3%83%9C%E3%83%87%E3%82%A3%E5%9F%BA%E7%A4%8E12-rbd-object%E7%AD%89%E3%81%AEglue%E3%81%AE%E8%A8%AD%E5%AE%9A/



FFXII感想

元旦からプレイを開始して本日クリアしました。
合計46時間。
起きたらFFXIIをつけて眠くなるまでやって寝る生活を
4日繰り返しました。

エンディングムービーや一部のムービーは見たことあったので
だいたいこんな話なんだろうなというのは事前知識としてあったので、
多分、亡国の姫がなんか奔走する話なんだろうなと思っていました。
実際にプレイしてみたところ、亡国の姫がなんか奔走する話でした。

まずストーリーについてですが、未プレイの時点ですでに
亡国の姫が作品のテーマになっていることからストーリー展開が
(脚本家からの立場として)難しいだろうなと思っていました。
ストーリーのテーマというのは基本的にわかりやすいもののほうが好まれます。
肉の付け方に上手い下手はもちろんありますが、
世界の脅威と戦うとか、悪い奴を倒すとか、
失った物を取り戻すとか。
しかしテーマを亡国の姫にしてしまったがために、
そういった単純明快な作品の骨が作れなくなっていたように思います。

帝国を完全な悪とすればよかったのでしょうか。
しかし同じ人間が行う、謂わば政治的な行為であれば
もちろん攻める側にもメリットや理由があるわけで、
一概に悪と断罪することはできません。
戦争で負けたら支配されるのは人の世で当然のことでもあるし。

アーシェが再び王としての立場を取り戻すことが
目標だったらよかったのでしょうか。
しかしアーシェは姫であり、支配者として己の治めるべき民や軍を組織したい、という欲求は
自然な考え方ではあまりないように思われます。
主人公がもともと王であり、王として君臨して為すべきことがある、
人の上に立つ者として才と覚悟があることが描写されている
ルルーシュのようなタイプならよかったのですが、
アーシェは姫であって王ではありませんでした。
実際に最初アーシェが持っていた強い行動原理は
自分の身の回りの人を殺し国を奪った帝国に復讐してやるという
およそ人の頂点に立つ器ではないものでしたし
復讐をやめようと考えてからは、ラーサーの「戦争を止めたい」という
誘いに協力しただけでその考えはアーシェ自身から出たものでは
ありませんでした。
むしろ復讐に駆られるヴァンの表情を見て、
復讐の醜さに気づいたからやめたというだけで
そこから具体的にどうしたいかという彼女の意思がさっぱりわかりませんでした。

復讐をやめて、人間的に成長する話にするならいいんです。
復讐なんて馬鹿なことはもうやめよう。そう思って、
例えばやられたからやりかえすという連鎖を自分が止めるために
反乱軍(解放軍)を解散するとか、普通のひとりの女性として生きようとか、
次のステップはいろいろあったはずなんです。
しかしFF12ではラーサーに協力し戦争を止めて、そのあとまた統治者に戻ってる。
このエンディングについては詳しく語られていないのではっきりしないのですが
戦争を止めたからと言ってダルマスカは独立したわけではないはず。
ダルマスカは帝国領でアーシェはラバナスタの首長になったということなのでしょうか。
経緯は不明ですが、帝国で最高権力を持っているのはラーサーなので
ダルマスカ地方の反帝国感情を緩和させるための人事としか受け取れません。
しかもラーサーが皇帝となったとはいえあんだけ憎んでいた帝国に指示されて
首長になれって言われてはいやりますって言うのは今までのアーシェの行動を見てきて
理解ができないです。
ここにきてアーシェは統治者に戻りたかったのか?という新たな(余計な)
疑問が生まれてきてしまいました。
アーシェは帝国の支配者層の一員として平和を維持したい、ということを前から考えていたなら
わかるのですがそんなことしたいと考えてた気配は微塵もなかったし
結局終始周りの状況に振り回されて適当に動いてきた感しかないです。

物語の骨となるテーマが欠落しているせいで、こういう話になってしまっています。
FF12とは、誰が何をする話なのか?それが全く見えてきません。
ゲームのプレイ中に起きたことも、戦略兵器である破魔石を追って世界を奔走したわけですが、
簡単にまとめると

ダルマスカ敗戦→ヴァンが破魔石を手に入れる
→破魔石が帝国に取られる→もうひとつの破魔石を遺跡に取りに行く
→破魔石が帝国に取られる→破魔石を切る剣を遺跡に取りに行く
→新たな破魔石を取りに神の遺跡に行く→やっぱいらねえって破魔石を壊す
→最終決戦

破魔石を取りに遺跡に行ってはその苦労は水の泡になる、を3回繰り返しただけです。

ではどのようにすればよかったのでしょうか。
自分が今すぐ考えつく限りでは…

①話の中心をアーシェにしない
まず亡国の姫が世界を奔走というテーマが全ての元凶なので、
主人公をアーシェにしないようにします。
FF12の主人公はヴァンとかバルフレアとかいろいろ言われていますが、
登場人物たちはアーシェの後をついてきているか、
雇われているか巻き込まれているかという理由なので
今回の場合アーシェが主人公じゃないと言い張るのは難しいと思います。
思い切ってバルフレアに同行する、あるいは利用される亡国の王女であれば
話のテーマをバルフレア中心にすることができ、
自分の父やかつての因縁との決別といった、過去と向き合い、新たな仲間もでき、
成長していく話にできたと思います。
本来であればどこの国がどこと戦争してようが関係ない立場である空賊が、
偶然亡国の姫と出会ってしまい、最初は金のために足になっていたに過ぎないバルフレア
徐々にアーシェと親しくなって、アーシェを復讐から解放したいと思う中、
自分の肉親もまた戦争の原因であったという展開にすれば話の展開がだいぶ楽になるし、
何より作品のテーマが
「政治なんて興味がなかった空賊が亡国の姫と出会って変わっていく物語」になります。

②アーシェの復讐心を設定から消す
周りの人も国も奪われたけど、戦争に負けたからしかたない、という
諦めをはじめから持っていたり、自分を納得させている女性だったら、
物語の間に「自分はどうしたいんだろう?復讐がしたいのかな?
地位を取り戻したいのかな?戦争を止めたいのかな?」と悩んでもらうことができます。
FF12本編のアーシェは最初から帝国に対してぶちギレており、
「帝国を、ぶっ壊す!(NHKをぶっ壊すのイントネーションで)」をスローガンにしてるような
キャラクターで迷いがありませんでした。多分それがいけなかったように思います。
それとこれはFFシリーズ全体に言えることなのですが
キャラクターが大きく傷ついたり過酷な経験をすることが避けられているように思います。
子供が安心してプレイできるようにという配慮なのでしょうけれど、
それなら「亡国の姫」というテーマでやろうとすることが悪手という元も子もない
話になってしまいます…
道中賊に捕まって、奴隷としてオークションで売られたり、
あるいは危険なモンスターに殺されかけたりしないと
「立場を失った」という描写が乏しすぎると思います。
失った物がこんなにある、今はこんなに悲惨なんだという描写がなく
周りには忠実な騎士や仲良くしてくれるヴァンたちもいるし
なんか今の生活も悪くなくね?楽しそうじゃんみたいな雰囲気があるのが
いけないと思います。
自分は本当は何がしたいんだろう?なんのために世界を奔走してるんだろう?
危険なこともたくさん経験した。寝るところもないし明日死ぬかもわからない。
爪はボロボロだし食事もモルボルの触手かじってるだけだし、もうやめたい。
そう考えている時についに見えはじめた一抹の自分の使命や、守りたいもの。
最後は「人が安心して眠るためには-!」といいつつターンAガンダム(シュトラール)に乗り込む。
そしてエンディングでは、孤児だったヴァンやパンネロが暖かい家で安心して眠りにつく。
アーシェは気づいたのです。自分は王女でありたかったんじゃない。
人が安心して眠れる世界を望んでいたのだと。そういうのでもいいんじゃないですか。
アーシェの優しさや慈悲深さ、聖女ぶりを前面に出したキャラ設定にしておけば、
実際にでてきた「わたしは聖女なんかじゃない!」という台詞も
うまく捌けそうです。
本編のアーシェが言った「わたしは聖女なんかじゃない!」はなんだか
彼女をふざけて「お母さん」って呼んだら
「私はあんたのお母さんじゃない!!」って怒られてるみたいな
そういうキレ方なんですよね。
復讐に燃えてたから「聖女」であったことなんて一度もないわけだし、
それをずっと見てたプレーヤーとしては「いやまぁそうやろなぁ」としか反応できねえわけで。
唐突に「聖女になるのだ~!」なんてノリノリで言い出したオキューリアに対して
「こいつ神なのに空気読めない奴だな」と自分は思いました。

ゲームとしてよかったところ
ストーリーは、戦艦リヴァイアサンが轟沈するまではおもしろかったです。
ほかには…序盤のバルフレアがいいキャラでした。後半空気だけど。
正直それくらいしかないかもしれねぇ。

ガンビットは、キャラが棒立ちになって見た感じアホっぽく見えないように
開発された発展途上(FF13ではかなりよくまとまってる)のアイディアでしたが
いちいち操作しなくて済むのはよかったです。
ただ条件文が少なすぎて、
味方がリフレクされると敵を無限にケアルラで回復してしまったり
リフレクがついてる敵にサンダガ乱射して味方を開幕即死させたりと
リフレクとガンビットシステムの相性が最悪だなと思いました。
条件がふたつ設定できれば
「敵がリフレクでない場合」「敵が2人以上の場合」→「サンダガ」
みたいにできてよかったと思います。
そうなると設定がめんどいけど。
あと「状態異常の味方」という条件がないので万能薬が使いたいのに
全パターン状態異常のガンビットを設定しなくちゃいけないのはゴミだと思いました。

悪かったところ
前述の通りうすっっっっぺらいストーリー(これが原因でキャラに魅力がない)
クリスタルグランデとかいう手抜きなのにクソ長くてめんどいダンジョン
灯台とかいう手抜きなのにクソn(ry
モブハントをしていると毎回依頼主のところに引受&報告に行かなきゃいけないこと
昔のゲームなのでしかたがないけどマップが細切れでいちいちオートセーブ挟むから
フィールドの移動が億劫&道が覚えられない
戦闘中のカメラアングルがクソで空飛んでる敵が見きれてる
ひどいときはHPバーが見えない
戦闘中に操作がほとんど必要ないからボーッと眺めているだけで終わること
(特にラスボス戦)
リマスター版ではラスボスが強化されて倒せなく、無駄にモブハントやらされたこと
連戦終わって最後の最後にラスボス倒せなくてわざわざモブハント数時間やってからまた
連戦やらされるのテンポくそ悪いぞ
ライセンスシステムでアンロックしただけじゃ装備や魔法が使えないこと
(装備や魔法を買ったり見つけたりしなきゃいけないのがめんどいしこのおかげで楽しさが増えていることはないただの手間が増えるだけのクソシステム)

セールしていたので2640円で買いました
フルプライス(5280円)で買っていたら後悔していたと思います
2000円以下なら買いですが同じ値段帯のSkyrim買った方がずっと楽しめます

 

ゴキブリの死とどう向き合うべきか

日に日に暖かくなりゴキブリたちも快適に過ごせるようになってきたが、
最近は死んだゴキブリをよく見つける。
成虫ばかりなので寒くて死んでいるのではなく、寿命で死んでいるのだろう。
毎晩寝る前、餌をやるついでに死体があったら除去しているが、
中にはひっくり返っているもののかろうじて触覚を動かしてまだ生きているものもいる。
その度に吾輩はどうしてあげるのが一番よいのだろうかと悩むのだ。

とりあえずひっくり返っているのはかわいそうなので元に戻してはあげるのだが、
死を前にした虫というものはどんな気持ちで過ごしているのだろうか。
苦しみの中もだえているのであればいっそひと思いに殺して楽にしてあげたいと思うのだが、
どうも見た感じ、彼らが寿命で死ぬときは焚き火の火が徐々に消えていくかのように、
ゆっくりと穏やかに命の灯火が消えていくようなのだ。
あくまで自分の見た感じの感想だが。
本当は苦しい可能性もあるが、のたうちまわったりする老齢の個体はいないし、
虫は動物に比べて神経がシンプルなのであまり複雑な感覚は持ち合わせていないかもしれない。

とりあえず吾輩は、あとは死をただ待つのみとなったゴキブリを起こし、
息を引き取るまでそのままにしておく。
周りには、自分の子を含め今まで一緒に暮らしてきた家族が多くいるし、
こんなに数が増えて繁栄した自分の種を眺めて死ねば、
一匹の虫として悔いはないように思う。

自分が生きている間にやるべきことは全てやった。一族がこんなにも増えて元気に暮らしている。
何も思い残すことはない。
そんなスッキリとした、穏やかな気持ちで幸せに死んでくれたら、育てている自分としては嬉しいものだ。

話は少し変わるが、昆虫ゼリーカッターを買ったー。(激うまギャグ)
ゼリーは毎日交換しないと幼虫が溺れて死ぬ事故が起きるので、食べ残しが多くても捨てていたが、これを使えば1日でほとんど食べきれるサイズになる上、幼虫が溺れる事故もなくなった。一石二鳥。
餌代が事実上半額になってマジで嬉しい。

Amazonのリンクを張っておきます。