Imaginantia

思ったことを書きます

雑記 あなたの言語、わたしの言語

一年前にも言語について考えていたらしいです。

phi16.hatenablog.com

が、最近考えてる話はまた違う側面でした。あと今日の話題とは関係ないです (根本では繋がっていますが)。

 

なんとなく「言葉を大事にするとはどういうことか」について考えていました。

というのも、私は一応「言語」が持つ機能について長いこと考えてきた人のうちの一人なので、一家言あるつもりなのです。

確かに私の分野は「表現に用いられる自然言語」ではなく「意味を明確に伝える為の人工言語」なのですが、「言語」という存在について考える上でこれらは不可分なものだと思っています。

だから、今の私が考える「言語」という概念について、書きたいことを書いてみようと思います。

 

つらつら論理立てて書いていこうと思っていたんですが、なんかあんまりおもしろくないので、思いついたことから雑多に書きます。

色々思ったことについて調べてみたところ、考えていたことの一部はポスト構造主義という名前がついていることがわかりました。私が考えていたのは、「言葉それ自体が意味を持つのではなく、言葉の意味は文脈から初めて定まる。だから言葉遊びは意味を持たないし、非論理的な比喩もまた意味を持たない」ということでした。

別にこれは悲観的な話ではなく、ただ眼前の事実を認めた上で、じゃあ現状をどう捉えるか、について考えていたんですけど。

まずここで問題なのは「意味」という言葉の意味が人によって異なっていることです。私は「価値」という意味で「意味」という言葉を使うことは無いのですが、世間的にはわりとその用法が知れ渡っているようです。だからとりあえずもう一度言っておくと、私の使う「意味」という言葉は「それが表わす事柄」というだけの意味です。

つまり「言葉遊びは意味を持たない」というのは、そんなのに価値はないって言ってるんじゃなくて、「言語を論理的文脈の積み重ねのツールだと捉えた時、言葉遊びによって組み立てることが出来る論理的文脈は存在しない」という話です。これは即ち「論理性以外のところにフォーカスがある」ということになります。

同様に、比喩というものを人は多用しますが、私はそれが意味あるものだと思っていません。「元の表現だとなんだかわからない」という状況はその通り元の表現の「意味」がわかっていないということなので、それが解決しない限り比喩は何も解決しません。

もうちょっと書くと、比喩によって「理解の補助」になることがあるのは事実だと思いますが、「比喩単体で理解したことになる」のは違う、という話です。私はこのことを最近の画像生成AIの議論を見るたびに毎回思います。

そして「言葉そのものには意味が定まっていない」というのもなかなか共有されていないポイントです。特にここは数学系の議論を通したことがある人とそうでない人で解釈が大きく異なるんだろうと思います。もちろん (双方にとって) それは言い訳にはなりません。

辞書に乗っているのは言葉の定義ではありません。言葉が意味するものは定義されていません。そんな曖昧な自然言語であっても人間はなんだかんだ意思疎通が取れていますが、それは文脈の力によるものです。

だから私達は、たとえ日本語であっても、「どんな言語を喋っているのか」を記しておかないと、わかってくれないことがあるわけです。

ここで難しいのが、どんな言語を喋っているのか記す方法もまた言語であるという点です。

その基本的な語彙の時点で乖離があったら、もうその後何もできることはないのです。お互いに

例えば根本的に、「相手が意味わかんないことを言っている」と思ったら、それは「相手の言っていることがおかしい」か「文脈が共有できていない」かのどちらかです。私は他者がおかしいと考えるよりは、他者もまた論理的思考の下で会話している対象であり、私がそれを理解できていないのだと捉えるほうが妥当だと思うので、そう思います。

何が言いたいかと言うと、見知らぬ他者にリスペクト (=人として対等であると見做す精神) があれば、「それは間違っている」なんて簡単には言えないはずなのです。その時点で対話が成立していないわけです。

だからあんな話になるんだと思いますけど。

まぁこのしょうもない話はいいや。

 

もっと表現の話が書きたかったのでした。

なんとなく「韻」ってどこから来たのかな、って考えたことがあります。昔の言語はかなり活用 (conjugation) が活発でしたから、文法構造上自然に韻が産まれていたケースは多いんじゃないかなって思いました。今の言語でもだいたい品詞によって語尾に強い傾向があって、「韻を踏む」ということは「並列表現」に近い事柄のように思います。言葉の長さが揃っていることも並列表現として捉えると妥当ですし。

全てを論理的機能に還元しようとするのは好きではありませんが、論理的解釈を試みること自体は否定されるものではありません。

言語というものは論理性にかなり強い影響を与えているというのは昔から言うことですが ("語り得ぬもの"とか)、それで言うと論理性最強の言語は当然プログラミング言語ということになります。何故かと言うと、その「文章」の指す「意味」が、明確だから。

…明確じゃない言語もありますし、まぁ明確な方が少ないですが、例えば私は Agda を知っているので、まぁそれくらい言っても文句は言われないでしょう。

次点で「数学の言葉」があります。これも難しいところですが一階述語論理と ZF(C) とかを考えれば明確です。そこまで行かなくても、数学書に書かれている「自然言語の証明」は、明確な意味を持って (読み取り方が確定するという意味) 書かれています。

どうして意味が確定するのかというと、身も蓋もない話ですが、意味を確定させたもの以外を使わないからです。自然言語で書くと二重否定を使わないと記せない感じがありますが、要は「全ての各部分が論理的に意味が確定しているから、全体も確定する」のです。

この手段は、別にこんな論理極振り言語に限った話ではありません。パターン化、使う道具、コマ割り、カット、どんな媒体においても私達は「意味が確定した表現」を使っています。

それがないと何もできないからですね。

もちろん自然言語だってそうで、言葉自体の意味は確定してなくても、助詞の意味は確定しているのです。

こういうものを、多分「文法」(grammar) と呼ぶのでしょう。言語に依らず、至る媒体にあるモノです。

 

でも同時に思うことがあります。「文法から読み解く力」が無いとそれを理解できない、と言っていいのか。つまり文法から読み解くという論理的思考無しに作品は成立していたはずじゃなかったか。

つまり感情に訴えかける作品とは何だったのか。

私個人の意見は、「論理的思考無しに作品は成立しない」です。つまり作品を作る側は、文法通りに構造を読むときに用いる思考のことを、もはや当たり前すぎて思考と認識していない、と解釈しています。

例えば特定の民族音楽に慣れた人は和音が理解できないみたいな話も聞いたことがありますし、極論を言えば英語がわからなければ英語の歌詞で感動することはできません。小説が読めない人、漫画が読めない人、詩が読めない人、多分どこにだって居ることです。

残念ながらこの言説は科学的ではありませんが (反証可能性がない)、まぁここから導ける事柄があるわけでもないです。問題提起でもない。

まぁでもこれを基準に考えてみると、どんな作品ジャンルにも相応の「読み方」というものがあって、それがわからなければ確かにわからないのかもしれない、ということになる。それを補填することは結構難しいし、やろうとする動きも無いでしょう。

強いて言うなら「国語」があるくらい。

意味を明確に定めるプログラミング言語系においては「解説」が一般的な行為で、それは理解すべきものがあからさまであるからでもあるわけですが、所謂作品というのはなかなかそういう視点で見られない気もしますね。

私は「文脈」の話をするよりは「文法」の話をしてくれたほうが好きなのかもしれません。個別の事情よりは、普遍的ルールの方が応用できますし、何より全体の見通しがよくなります。

何の話だったか忘れました。ああ、でも、「言葉遊び」も意外と文法なのかな、とかちょっと思いますね。こう書いてみると。

 

「表現」という言葉についても前にいろいろ書きました。その1つの理由は「表現論」(representation theory) という数学の分野があって、群とかを行列として捉える (何らかの対象を、行列として表現する) ことを司っているんですが、それ表現すること、だと私が思っているからです。別に私はその辺学んだわけではないんですが。

つまり、表現とは「A」を「B」として表現すること、という話です。特に、「A」の本質的な部分 (up to isomorphism) を表現するという点。まぁ一般には単なる「部分」として読まれている印象ですが。

…わかるように、私は結構 (日常) 語彙を明確な意味ある言葉として捉えていることが多いです。もちろん定義そのまま当てはめたりはしませんけど、そういう「図式」を明確に想像していることが多いです。

そういえば私は「文脈」という言葉も明確な意味で使っています。前に「矢印の左側」と言いましたが、頭の中のイメージは dependent product とか slice category とかその辺です。まぁどっちでもいいんですけど、このあたりの利点は「計算できること」があります。

つまり「文脈に沿っていること」は型導出が出来ることだし、「文脈が適切に使われていること」は linearity を守っているかどうかで判断できます。

理論の言葉が自然言語に綺麗に対応しているとはもちろん思っていませんが、まぁ、そんなに外してもいないようです。

linearity (1つの要素がちょうど何か1つの為に存在していること) は結構面白い視点だと思っています。これは自然言語で言うと「伏線を追跡する能力」で、でも最後まで使わなかったものに対して不満が出たりはしません (exponential がついてると解釈されるだけ)

なんであれそういうものまぁ、私の中では大事な「言語」の一つなのです。

 

特に何も順序立ても結論も無しに書いてるので本当に支離滅裂な感じになってますね。まぁいいや。

普通の言語の話題に戻りますけど、まーほんと、人間は言葉がわからないみたいですね。ついったーを見ていると毎日痛感します。

正確には文章によって派生する論理展開がわからない、ということになるのかもしれませんけど、会話における言語は主としてそれを目的にして使われているので、まとめて言語と呼んでも差し支えはないでしょう (この差し支えのなさについては十分伝わったかと思うんですけど、そうでもないのかもしれない)。

お互いの文脈不理解が根底にあるのは間違いないんですが、更に「自分の持つ観点のほうが優先度が高い」と考えているというどうしようもない状況が重なって話が一向に進まない、みたいなこともよく見ます。

この話不毛な気がしてきた。いや最初からまぁそうなんですけど。

いや不毛だから毎回色々見ても見過ごすわけですけど、性質的に気になっちゃうんですよね。異常論理展開とかを見ると。既にいろいろ書いたことありますけど、これでも結構我慢してるんですよ。

なんかね、目先の話題について喋る前に「会話の構成」について考えなきゃいけないわけです。実際それをやる人もちゃんと居るんだけど、そういう相手ってだいたいそういうところがわからない人だから、そうやって「大前提の確認」をしようとすると「話題のすり替え」とかに感じるみたいなんですよね。で無理やり戻そうとするから本当に進まない。

「相手と話が通じないと思ったら大抵自分が悪い」とかも真理な感じあります。だって相手がわからないような話題を振ってしまっている時点でこっちが悪いのです。でもそれは恥ずべきことなんかではなく、ただそこからフォーカスを合わせに行けばいいだけなんですけど。

さっきも言いましたけど、話が合わないと思ったときに自分の解釈が間違ってるかもしれないとか考えないのはその時点でよくない振る舞いだと思います。きをつけようね。私も気をつけています。

あ、気をつけているけれど、例えば「それはおかしくないですか」って言うことはありますね。これは確かに数学語みたいなやつで、一切非難とかのニュアンスはないんですけど、この辺言語の違いで伝わってないかもしれない。「私はこう思うのでそうはならないと思うのだけど、私が間違ってたら指摘してください」の意味です。

いや、というか、私は指摘してもらえるのがとても好きで、どんな内容であれ論理的に妥当であればありがたいと思っているのだけど、なんかその時点で乖離があるよね、世間と。難しいね。

 

本当になんでもないことについてだらだらと書いてしまいました。

人によって言語って違うもので、私のこれに極端な成分は確かにあるわけだけど、それでも論理性に基づくというところは共通してるんじゃないかと思います。

気になったことを吐けたので、もうちょっと自分の視点も広がったかもしれません。論理って広がっていくものなのよ。

今度はもうちょっとまとめてから文章書こうと思います。

おわり。

雑記240320 内部実装いろいろ

ディレクター以外の話を書きます。普遍的な話しか書かないので、実用性があることもあるかもしれません。

Udon関連

全体管理

本当に普遍的な話ですが、複雑な物を作るためには、それを簡単にする手段が必要です。一般にはこれを「独立した各要素を作り、それらを組み合わせる」ことで行います。

それを実現するのに必要なことが:

  • 各要素の責務を明らかにすること
  • お互いに知るべきでないことを知らせないこと
  • 知りたいことをちゃんと伝えること

です。それを行う方法は色々あって、ぶっちゃけなんでもいいです。例えば要素の責務は「私の直観」に従って決めているので、チームが大きくなるとこれはうまくいかなくなります。

で、今回その各機能とやらはだいたいワールドにちょうど一個あったりしていて、一般にこういうものを Singleton と呼んだりしますが、まぁ Udon の場合は普通に GameObject として顕現することになるので普通に参照を渡すことで実現できます。

が、各 GameObject に参照先をいっぱい渡すのは面倒くさい (必要なものが増えたときに増やすのもめんどい) ので、全部を集めた Udon を作りました。そしてそれを参照するのも面倒なので、GameObject.Find で拾ってきています。

各々の野良オブジェクトは初期化のタイミングで GameObject.Find を呼んで「全部集めたUdon」を拾ってきます。あとはそのメンバにいろんな Singleton が入ってるので参照し放題ということになっています。

美しいかというと一切そんなことはないですが、まず Udon はだるい環境だということを考えるとそのトレードオフとして良い塩梅だと思っています。

 

今回良い設計が出来たかというと一切そんなことはなく、全体的にカスみたいな構造をしていますが、ゲームって「思ってたよりもいろんなものに影響する」ケースが一般に多く、逃れられないものな感じがありますね (大体アニメーションのせい)。

今回は「構造が把握できなくなったら作り直す」戦略でどうにかなっていました。幾ら頑張って作ったものでもヤバいことになってたら破壊するしかないです。その点ほぼ全部自分でやっていたのは本当に楽で、「なんかデータが変な流れ方をしている感覚」があったら気軽に組み直してました。

プログラムを組み直すの、結局ロジックは変わらないので (設計さえ頭の中で組めれば) 意外と素直に済むのでおすすめです。何よりもその方が作る速度が速いので。

状態管理

一般にプログラムの最もである部分が「状態」で、これを如何に減らすかが構造を単純化する為の肝みたいなところあります。

例えば機能だけを見ると単純だけど、アニメーションとかエフェクトとかが付いてくるといつの間にか状態がめっちゃ増えてるみたいなことがよくあります。

というわけで、今回はアニメーションもエフェクトも状態を持たないようになっています。view-model みたいなやつです。今回は view はシェーダのこと、model は MaterialPropertyBlock (に設定するパラメータ) のことですね。

Animator はよくわかんないので使っていませんが、別にどっちでも良いと思います。私にとって楽だからこうなってるだけですね。

基本的には「表示したいデータ」と「表示開始時刻」を MaterialPropertyBlock に突っ込んで MeshRenderer にセットすることでアニメーションが行われます。シェーダでは「現在時刻 (後述)」との差分を取って、いい感じにアニメーションするようにします。

エフェクト (パーティクル類) は別の Udon に全部投げてます (後述)。中途で制御する必要がないやつはこっちです。

シェーダでアニメーションを書くと「どうしても view が状態を持てない」構造になるので強制力が働いて、自然に綺麗になっていくので嬉しいです。まぁ代わりに「瞬間的にモノを出して消す」ようなことをすると不連続な動きになったりするんですが、今回は許容しました。

例えばメガホンをターゲットに向けたときにちょっと反応するのは、こうなっています:

public void Focus(int bar, float beat) {
    pb.SetVector("_FocusTime", new Vector4(bar, beat, 0, 1));
    renderer.SetPropertyBlock(pb);
    colliders[0].enabled = false;
    colliders[1].enabled = true;
}

public void Blur(int bar, float beat) {
    pb.SetVector("_FocusTime", new Vector4(bar, beat, 0, 0));
    renderer.SetPropertyBlock(pb);
    colliders[0].enabled = true;
    colliders[1].enabled = false;
}

これを見てすぐわかるように「片手でフォーカスした後、もう片手でフォーカス当ててから外すと、フォーカスしてない状態に戻る (まだフォーカスは残ってるはずなのに!)」んですが、戻ったところで判定処理に一切関係しない (状態を持ってないので自明) ので特に問題ありません。コライダーがちっちゃくなってちょっと判定狭くはなるけど、大体の人には問題ありません。

というわけで、どうにか Udon をシンプルにしつつシェーダで好き勝手を書くことでなんとかしました。状態さえなければバグなんて起きないのよ。

同期

しかし状態は変化するわけで、加えてなんとか同期を上手くやる必要があります。それでもどうにか見通しよく組む為に、「ひたすら robust にする」という方針がとても有効でした。どういうことかというと:

  • 同期はいつ行われるかわからないので、いつ行われても大丈夫なように組む。
    • せめて「1小節」(1.7秒) くらいは待てるように組んでいます
    • 後続に影響のあるイベントは ManualSync でゆっくり渡します
  • 「変化しにくいもの」を同期させる。
    • 機械のオン/オフそのものではなく、「いつからオン/オフか」を同期しています。
  • 負荷が掛かってもイベントがスキップされないように、時刻ベースで処理を組む。
    • late-joiner の為にもこれは必須要件だったりします
      • joinした瞬間に「これまで実行されていたであろうイベント」を順次実行
  • うっかりデータが変な値になってるかもしれないので、たまにチェックして修正する。
    • 音再生タイミングがズレてることを検知したら一時停止し、後に復帰
    • 各着色用のビンは1フレームに1個ずつ表示位置を検証したりしてます
  • うっかりイベントが複数発火されても大丈夫にする。 (冪等性)
    • リズムの判定を複数人でやっても問題ないようにとか
  • 一部のデータが整合してなくても、全体の流れに影響させない。
    • ラインを流れるモチポリの色は実は人によって異なる場合があるけど、「全タスク完了」判定には影響しないしラストのモチポリの色にも影響しません
    • 着色数も人によって異なるけど Owner の値を信用することにしています

要は「データをできる限り信用しない」「雑にやっても大丈夫にする」っていうことです (Eventual Consistency に近い話)。

当然「これまでの結果を信用する」モデルよりも対処することがたくさんになって大変ですが、一度組めば後は適当に値を投げたらうまく動くようになるのでだいぶ気楽になります。

まぁ実際には「素直に組んだら微妙に不整合が発生することになった」→「仕方ないので不整合から復帰できるようにした」が殆どですが。

根本的に分散処理なので不整合からは逃れられないと思っているので、「どうにか整合させる」よりは「不整合に対処する」方がなんだかんだ楽だと思います。

 

ところで複数人でデバッグしていたら色々と"ありえない"不具合がたくさん出てきて、どうして~と悩んでいたら、原因が「UdonSynced な配列変数に null が入っていた為、その Udon の同期が一切行われなくなったから」でした (どっかに公式の言及ありませんでしたっけ?忘却…)。OnPostSerialization でもらえる SerializationResult を観察してやっとわかりました。

でも自分の書いたコードはちゃんといろんな状況に対応できてるはずだから (不変条件とか契約とかその辺の概念もおすすめ)、もしや私の知らないぶいちゃの仕様があるのか、と思って調査できました。ありました。

時間合わせ

Amebient の時には AudioSource.time をベースに時間合わせをしていましたが、時間が経つと負荷などによりズレが起きることがわかっていました。今回は「完璧」に合わせる必要があるのでどうにか全員の共通クロックが必要です。

なんと Networking.GetServerTimeInSeconds() は全プレイヤーでほぼ共通の値を返してくれます! 毎フレーム呼んでも綺麗な値が返ってくるので、今回はこれを基準に処理を走らせることにしました。

ただこの値は当然 AudioSettings.dspTime とズレます。仕方ないので「初期化時に差分量を保存」「ある程度ズレたら差分量を計算しなおす」ようにしました。

また音楽ベースのワールドなので基本的には「小節」「拍」単位で時間がもらえると便利です。というわけで:

  • 時間軸は dspOffset, beatTimeOffset, bpm で決定する。beatTimeOffsetbpm は同期する。
  • 現在時刻 t = Networking.GetServerTimeInSeconds() に対して「拍時間」 double bt = (t - beatTimeOffset) * bpm / 60 が定まる。
  • 「小節数」 int bar = (int) (bt / 4), 「小節内拍数」 float beat = (float) (bt - bar * 4) が計算できる。
  • 音を鳴らすときは (bar * 4 + beat) / bpm * 60 + beatTimeOffset + dspOffsetPlayScheduled を呼べば良い。

このようにして全プレイヤーで共通の時間軸を手に入れることができました。嬉しい。この辺の管理をする Udon は相変わらず Metronome と呼んでいます。

拍時間そのものではなく小節数/拍数 (以降 bar/beat) に分離しているのは、「1日インスタンスが継続すると200000拍くらいになって18bit消費する」「シェーダに渡すと float になって仮数部23bitなので拍内の時間間隔が5bitくらい (15msくらい?) しか貰えなくて足りない」からです。int + float で表現するようにすれば余裕です。それはそう。

単純な floor/frac ではなく4拍単位にしたのは、今回ちゃんと「音楽」をやる必要があったので、そっち側の convention に合わせた方が都合が良かったから、です。が、小節数が 1 から始まる点についてはプログラム的にも面倒なので 0 始まりになってます (モニタの表示では +1 してます)。

この bar/beat の値は SetGlobalFloat/SetGlobalInteger してあるのでシェーダ側から自由に参照できるようになっています。なのでアニメーションとかはこの値からの差分を計算することで「アニメーション開始から何拍経ったか」 がわかるわけです。

 

また、今回BPM変化する予定があったので、そのようにしました。bpm が変わるということは beatTimeOffset が変わるということですが、この値は計算すれば出ます。のでなんとかなりました。

全てを bar/beat 単位で管理したので、途中でBPM変化が発生しても、アニメーションは勝手に拍に合ってくれます。つまり自動的に加減速することになります。

イベント処理

拍タイミングに合わせた処理が非常に多いことが想定されたので、「16分のタイミングで自動的にイベントを発火してくれる Event Listener」を作りました。

特に、負荷が掛かっても「前フレームから現在までのイベントを発火する」仕組みなので、イベント抜けが発生しません。

private int lastBar16th = 0;
private int lastStep16th = 0;
public override void PostLateUpdate()
{
    int bar = lastBar16th;
    int step = lastStep16th;
    int curBar = time0; // bar
    int curStep = Mathf.CeilToInt(time1 /* beat */ * 4);
    if(curStep == 16) {
        curBar++;
        curStep = 0;
    }
    int count = (curBar - bar) * 16 + (curStep - step);
    for(int i=0;i<count;i++) {
        for(int k=0;k<rhythmCallCount;k++) {
            var c = rhythmCalls[k];
            c.OnMetroCall(bar, step);
        }
        step++;
        if(step == 16) {
            bar++;
            step = 0;
        }
    }
    lastBar16th = curBar;
    lastStep16th = curStep;
}

IRhythmCall を継承して OnMetroCall を実装して MetronomeSetCallback をお願いすると、後は定期的な処理が書けます。ついでに Update ほど頻度高くないので負荷軽減にも寄与していますね。

16分のことをなんて呼ぶべきかわからなかったので step という名前にしていますが、これによって bar/beat 管理と bar/step 管理が入り混じったりしています (型が違うので判別は容易なんですけどね)。ちょっとミスったかも。

機械の音再生

効果音とかは素直に PlayScheduled で鳴らせばいいんですが、「常時鳴ってる機械」をそれでやるには 流石に AudioSource が足りません。Quest だと同時再生24個までらしい (検証しました) ので、効果音とプレイヤーボイスのマージンを考えると「機械音で10個くらい」に収める必要がありました。

各機械は 場所が違う のでどうしても AudioSource を分ける必要があって、結果として「1機械1AudioSource」で処理する必要があるということになります。というわけでそうなっています。

やり方は:

  • 5秒くらいの AudioClip を loop で流し続けておく
  • 1小節の始まりのタイミングで「次の1小節分の音バッファを GPU で計算して RenderTexture に書き込み」しておく
  • 生成された音バッファを VRCAsyncGPUReadback で読み出して AudioClip.SetData して追記していく

以上です。別にシェーダじゃなくてもいいんですが今の Udon だと速度が足りないのでシェーダしかないと思います。

AudioClipのバッファは2小節分収まる長さが必要で、今回ワールドの最低BPMが 90 なので、2小節 * 4拍 / (90bpm / 60秒) で 5.333秒になっています。

開発中はまだ Unity 2019 だったので Quest で VRCAsyncGPUReadback が動いてなくて 恐々としていました。

 

VRChat で GPU で音バッファを生成するためには音源をテクスチャに焼く必要があります。焼きました。

このテクスチャが一番ワールドで容量を食っています。音源ファイルなら音源らしい圧縮が出来るんですけどね…。

音源データを初期化時にコピーしようとすると float[]Color[] に変換しなきゃいけなくて、このコピーをQuestでやると1秒以上掛かっていたのでやめたんです。同じ型の配列の部分コピーとかなら System.Array.Copy で全部対応できるのに…。

って思ってたらどうやら beta 版なら BitConverter / Buffer.BlockCopy が追加されてるらしい です。これからやる人はこれを使いましょう。

 

シェーダに渡すリズムデータは対象小節数のものだけでなく一個前の小節のものも必要です、前小節の音のリリースがまだ残ってる可能性があるので。逆に言えば機械の音は1小節以下の長さに抑えてもらいました。

float4 o = 0;
for (int j = 0; j < 32; j++) {
    int step = j - 16; // 負なら前小節の音
    float clipInfo = GetRhythm(index, _RequestBar, step);
    int clipIndex = (int) floor(clipInfo);
    if (clipIndex == 0) continue;
    int offset = 0;
    if (j >= 16) offset = step * len / 16;
    else offset = ((16 + step) * prevLen / 16) - prevLen;
    o += sampleClip(clipIndex, pixelIndex - offset);
}

ちなみに「あるBPMに対してサンプル数 (48000 * 4 / (bpm / 60)) が整数になるとは限らない」ので、同じBPMでも各小節内のサンプル数が微妙に変わります (lenprevLen がコレです)。

 

音生成をする為にシェーダにリズムデータを送っているわけですが、実はこれは SetGlobalFloatArray で送っていて、そのまま各機械のアニメーション (を行うシェーダ) でも参照していたりします (GetRhythm 関数)。

パーティクル

今回はパーティクルをちゃんと出したいなあと思っていたので、パーティクルシステムから作りました。

昔はパーティクルの生成/消去がGPU的に面倒だなあと思っていたんですが、Knot Puzzle を作ったときにうまいやり方がわかりました。これ です。

あとは「1フレーム中にパーティクルを大量に生成したい場合」にどうするかなんですが、Udon 側に queue を作って順次送り出すことにしました。このワールドのパーティクルの出現は基本的にリズムに合っているので、各小節始まりのタイミングで既に出すべきパーティクルが確定しています。

よって小節始まりのタイミングで自作パーティクルシステムに全情報を送って、ちょっとフレーム掛けてGPUに順次転送していくことにしました。1フレームに2個まで送れます。

ただそれでも間に合わないのがバトンを振ったときのパーティクルで、これだけ「16人×2本」のパーティクルが毎フレーム生成される可能性があります。仕方がないので、人毎に処理IDを分離しました。

というわけで、64種類のパーティクルを同時に処理できるパーティクルシステムを作りました。実際の内訳はこんな感じです:

  • 0: 衝撃波 (一番よく出てくるやつ)
  • 1: もちに着色料を落としたときの飛沫
  • 2: 顔形成時の熱
  • 3: 蒸し器から出てくる水蒸気
  • 4: モチポリを焼いたときの図形系パーティクル
  • 5: 未使用
  • 6: 旗を振ったときの矢印
  • 7: 射出されているモチポリ
  • 8: DAIFUKU FACTORY行きのもち
  • 9: DAIFUKU FACTORY行きのもち、でかい方
  • 10: モチポリがパイプに格納されるときの飛沫
  • 11: 窯にモチポリが入っていく直前のもち
  • 12: モチポリとクロミちゃんがメガホンを向けたときの六角形エフェクト
  • 13: 衝撃波、白い方 (UI系)
  • 14: 文字とリズムが合ったときにモチポリと一緒に弾けるリング状のエフェクト
  • 32-47: 通常バトンを振った時の白い粒
  • 48-63: 旗を振った時の白い線

各ID毎に 256 個まで出せます。これで 256x256 のテクスチャに収まってるので意外と計算側はちっちゃいもんなんですよね。

あとは表示側の頂点シェーダで適当に読み出していい感じにすればいい感じになります。なりました。

各パーティクルは float4 を 4 つ分の情報を持っていて、共通で位置と時間、あとは好きなプロパティ (9次元分) を渡せるようになっています。

ライティング

Questでちゃんと綺麗な動的ライティングをやりたかったので、やりました。

これは Resonark4 のとき の仕組みと似たようなことをやっていて、工場全体に 16x32x32 のライトプローブがあるような感じで自前でライティング処理を書いています。

  • 各照明 (16個) の光量を決定
  • 各照明ごとのライトプローブデータと光量を乗算して、総和を取って、RenderTextureに書き出し
  • 各オブジェクトのライティング時に読み出す

ライトプローブの配置は、とりあえずグリッドで置いたらオブジェクト内部に入ったりして散々だったので、Houdini で「オブジェクトの裏に居るなら表に押し出す」ようにしています。いい感じになりました。

それでも一部の影が変な出方をしていたので、ライトプローブデータ全体に対して 3x3x3 カーネルの Gaussian Blur掛けました。とてもいい感じになりました。

各オブジェクトのライティングは baseColor * ((diffuse + metallic + ambient + rim) * probe + spotLight + emission) です。metallic っつっても適当な (R\cdot V)^\alpha を 2 個足し合わせてるだけです。

が、Questだと案の定重かったので、「metallic, rim のパラメータを無視」「probe の計算は L0 のみ*1」にして、どうにかしました。正直ギリギリですね…。

余談

Coroutineが欲しい

エンディング時にいろんな出来事が順番に起きるわけですが、それをどう綺麗に記述するかに悩みました。特に late-joiner 対応があるので、「データとして」イベントを記述しなければなりません。

悩んだ結果、こうなりました。

string[] processEventContents = new string[] {
    "-36,0,K0",
    "-18,0,K1",
    "-14,0,K2",
    "-12,1,H",
    "-11,0,X",
    "-10,0,K3",
    "-9,0,K4",
    "-9,4,K5",
    "6,0,G",
    "7,0,K6",
    "7,8,K7",
    "7,12,F0",
    "11,12,F1",
    "15,12,F2",
    "17,12,F3",
    "19,12,F4",
    "20,12,F5",
    "21,12,M0",
    "22,4,M1",
    "22,6,M2",
    "22,12,M3",
    ...

これは bar/step とイベント名のリストです。初期化時にこれをパースして保存しておいて、「時間が来たら、イベント名で SendCustomEvent を飛ばす」という実装にしました。

大量に関数を生やすので、名前付けが面倒になって1文字 + 番号になりました。まぁ中身は短いので見たらわかります。

Coroutineが欲しいです。でもC#のCoroutineは私が欲しいものとは別物なのかな?まぁいいや。

メッシュの Bounds

よくメッシュの見た目を vertex shader で好き勝手に弄るので、bounds を変更したいことがしばしばあります。

今まで Mesh.bounds を弄ってアセットとして保存しなおしていたんですが、なんかそれだと VRChat 上でうまく反映されないことがありました。

悩んだ結果、Renderer.localBounds を見つけました。私が欲しかったのはこれです。ありがとうございました。

メッシュの UV に情報を詰める

Unity の Mesh は UV1~UV8 までありますが、これは Vector4 が入ります

が、スクリプト経由じゃないと多分生成できないと思います。なので、Houdiniで「XY成分を持ったメッシュ」と「ZW成分を持ったメッシュ」を吐いて、エディタスクリプトでくっつけるなどしました。

とは言え結局 UV1 + UV2 の 8次元で収まっていたので、普通に UV8 とかを使ったほうが早い気がしています。使ったのは:

  • ビンの水面を作るために四面体分割をしていて、4頂点の位置情報 (12) を position (3) + uv (4) + uv2 (4) に埋め込んだ
    • 分割した四面体たちは、必ず2頂点が同じY座標を持っていたので、うまく選択することで11次元になったんだけど、別に uv3 を使えばよかった気もする
  • 星の配置は Scatter で relax したいので Houdini 生成なんだけど各星を回転させたいので、ローカル座標 (3) + UV (2) + 乱数 (2) + 中心位置 (3) が入ってる
    • これも大した必要性はなさそう (UVはローカル座標で十分そう) (ちなみに色は頂点カラーに入ってる)

Android の UI

Android でも何もしなくても動くんですが、唯一バトンの出し方がありません。ので、ボタンをつけました。

が、普通に UI の Button を置いたら反応してくれませんでした。なんかレイが出てないのかな?色々試したけど面倒になって。

代わりに Interact を入れたキューブを視界端に貼り付けました。ちゃんと反応しました。

おまけ: おもちパイプライン

一般的な話ではないですが一応ちょっとだけ。

あのもちたちは UdonGPU が協調して動かしています。「どの位置に居るべきか」は Udon が持ってるんですが、「実際にそこまでゆっくり動かす」のはシェーダでやってます。

まぁまず前提としてパイプライン上のもちは GameObject としては別に動いてなくて、全部シェーダで見た目をコントロールしています。毎フレームもち情報が Udon から送られています。

で、GPU上のフィードバックループがあって、「ラインの端からどれくらいの位置に居るか」をだんだん動かしています。

そしてその値を VRCAsyncGPUReadback で拾って「各ラインの終端にたどり着いた」ことを確認して、Udon で「次のラインに放り込む」という処理が走ります。

なので Udon が処理する必要があるのはラインの切り替わりを跨いだもちだけで、結構短めに済んでいます。ちなみに各ラインは queue で管理されていて、head が動くので全体をずらしたりはしてません。あと最初から長さがわかっているので色々単純化されていたりする。

パイプがどこを伝っているのかの情報は全部テクスチャに焼いてあります (Houdiniで)。先述のもち相対位置計算時に同時にワールド座標上でのもちの位置も計算していて*2、描画時にその値を参照するようになっています。

ラインに依ってアドホックな処理がめちゃくちゃ入っていて最悪みたいな感じになってます。そんなものですね。

おわりに

以上、エンジニアリング的な話でした。

正直こんな話は頑張れば良いというだけで、作品自体の面白さには特に関係がないので「面白くない話題」ではあります。

が、この辺がブラックボックスになって仕組みが accessible じゃなくなってしまうのもなんかまた違う気がするので、とりあえずこういう形で書きました。

今まで色んなところでいろんなことをやってきた集大成っぽい感じになって面白かったです。

おわり。

*1:L1 だと RGB 毎 に xyzw を 2度 (Z方向の linear 補間) サンプルする必要があって6回、L0 だけなら 1px に収まるので補間だけやって2回なので3倍軽い

*2:ぷるぷるさせる為

メモ240312 旗の判定の話

色々考えてこうなったので、考えたことについて書いておきます。

前提

  • エンディングのアレがやりたかったので、3種類のインタラクションを用意する必要がある
    • 根本的にあのワールドは「体を動かす」ことに趣旨がある
    • 最後に手を自ら伸ばしてもらうための布石として、手を動かすことに慣れてもらう必要があった
  • それぞれで別物にする為に、判定方法の異なる3種を考えた
    • 叩くもの・振るもの・向けるもの
      • (それぞれ近距離・中距離・遠距離という意図)
      • 「盛り上げ隊」のイメージからビジュアルがアレになった
        • ちなみに各バトン形態の名称は特に決めてないです
          • 以後、便宜上青いやつを「旗」と呼びます
  • これをうまく実現する為に必要なこと:
    • 何をすれば、何が起きるかをユーザに伝えること
    • 十分な精度で挙動をコントロールする能力をユーザに与えること
    • (逆に、例えば動作が直感的であることは、ゲーム一般においてあんまり必然性がない)
      • 補助として機能することはもちろんある
  • 一般に、連続操作を離散化するのは結構難しい (連続写像じゃないから)
    • 状況Aと状況Bの間を「切断する」のが離散化
      • 今回は「A: 動いてない状態」と「B: 素早く動いている状態」として捉えた
        • 実はこれが間違っていた (後述)
    • 特に今回はユーザに「切断」させるタイミングをコントロールさせる必要がある

どうなっていたか

判定

  • 「止まっている状態から、ある程度の事前動作を伴った状態で、旗の先端が一定速度を越えると、判定が入る」という実装
    • 厳密に言うと: 「先端位置 p のEMA*1と、p との距離」d のEMA \bar{d}閾値を超えたときに判定
      • EMAを使っているのはFPS非依存にする為
      • 加えて、次に旗の判定が入るためには \bar{d}閾値の3/4以下に落ちる必要がある (hysteresis)
      • ちなみに振った向きは「p のEMAから p へのベクトル」から判定
    • 何が起きるか?
      • 止まっている状態から急に位置が変わった場合、d は即座に大きくなるが、そのEMAはまだ小さいままなので、判定が入らない
        • つまり急激に移動させると、判定がちょっと遅延して入る
      • 手をぷるぷるさせて振りまくると、先端位置のEMAが平均点に収束するので d も一定以下にしかならず、判定が入らない
      • ゆっくり振り始めながら振り切ると、d もそのEMAもゆっくり大きくなりながら期待するタイミングで閾値を超え、判定が入る
      • 旗を振るように事前動作と事後動作を行うと、ほぼその中間のタイミングで判定が入る、という想定
  • 何故か?
    • 一番簡単な「叩く入力」に対し、もうちょっと丁寧に体を動かすようなインタラクションがほしかった
    • 振るたびに音が出るので多少の報酬として機能していて、ちょっと難しくても大丈夫という想定
    • ぷるぷるして判定が入りすぎると簡単になりすぎる可能性があるので、丁寧に入力を行うことを促すために判定が入らないようにした
    • 今思うと、旗の物理による「質量感」にもうちょっと期待していたかもしれない

チュートリアル

  • 各バトンの振る舞いを学習してもらう場として用意したもの
    • 学習とは何か?
      • ユーザの入力に対し、システムが応答を返し、その応答結果とユーザの期待の違いを元にユーザがシステムの挙動予測の精度を高めていく行為
    • 3種類のバトンはそれぞれ違うことに伴い、チュートリアルの内容もそれぞれ別物にした
      • タイミングの精度を高めるもの
      • 将来の行動予測を継続的に行うもの
      • 丁寧な動きを心がけるもの
  • しかしこれによって旗の学習が破綻していた
    • 余計な入力が入るとリセットされてしまうことで、メインの工場フェーズで過度に緊張させてしまった
      • 工場フェーズで余計な入力が無視されていることは白いやつを観察すればわかるのだけど、恐らく緊張している為にその余裕がない
    • 旗の入力タイミングを不問にしていたことで、タイミングよく旗の判定を入れる練習ができていなかった
      • (一拍ごとに入れるとちょうど良い間隔で入力し続けることができる想定だったが、システム (スコア表示のこと) がそれを示していない)
    • 丁寧に動かさせすぎたことで素早い入力に対応できなくなってしまった
  • どうしてこうなったのか
    • チュートリアルの内容を他と変えることに気を取られた
    • 最初から手首で私は振ってたので腕でしっかり振る人の想定をあんまりしていなかった
      • 多分ゲーム慣れしていると「判定さえ入れば良い」という意識から行動最適化が自動的に走るのだけど、そうでない場合は「形式」を優先してしまう様子?
        • もともとゲーム好きな人に向けたワールドではあるけども
      • 例えば私は精度上げる為に、頭でリズム取りながら、旗振るときに足も同時に動かしているのだけど、この辺の感覚は確かにそこそこの経験が要るかも
        • そこまでこのワールドで学習ができるとは思ってないわけで、そこまでの要求は要らない構造にするべきだった
          • とはいえ音を楽しもうとしてくれる人は結構そういう行動をしてくれてうまくいっている印象
        • 無意識にやっているから自分でわかんないんだよね…
          • テストプレイもっとしたかった…
    • 内部事情: エントランスだけBPMが違う (時間管理系が異なる) ので「タイミングを合わせる」ゲームを作る実装コストがちょっと高かった
      • なので判定は工場と同じ粒度で取っていて、これによって期待したタイミングとはちょっとズレて判定が出ていたはず
      • これを誤魔化すために緩めの判定処理 (向きオンリー) にしたという経緯もある

実態

  • うっかり旗の判定処理がバグっていて、EMAになってなかった (しょうもないミス)
    • lerpの左右が逆だった (aveD = lerp(aveD, D, exp(-dt)) になってた)
    • FPSが高い場合は d\approx\bar{d} になり (迅速な判定が入る)、極端に低い場合は d\approx 0 になっていた (全然判定入らない) はず
      • ごめんなさい
      • エンディング、人数多いとなんか判定入らないな~とは思ってたけど普通に凡ミスで悲しい気持ちになった
        • ちなみにこれは叩くやつも同じ仕組みだったりするので、多分叩くやつで判定入らないと感じてた人も居るはず (私もそう)
  • モチポリが腕を大きく動かしてるのでユーザも腕を大きく動かしたくなってしまう
    • 「旗の動き」は真似すべき点があるのだけど、腕まで真似するとすぐ疲れちゃうんですよね (モチポリの腕は強靭なのかな?)
    • 疲れるからもっと楽な方法を探そう、ってなってくれることを期待していたけど難しいですよね
      • ポップコーンも同じことが起きててまぁそうだなあっていう感じ (うまい人はこのフェーズをすぐ越えられるんですよね)
  • 素早い動きの入力を入らないようにしたことで、エンディングのシナモンルートがほぼ不可能になっていた
    • BPMだいぶ上がるので… (多分理論上は可能なんだけど人間に可能かどうかは別問題)
      • つまり「2連続の入力をするとき、途中に動いていない状態は存在しない」ということがわかっていなかった
    • 毎回全然できね~~~って笑えるのはまぁそれはそれで良かったんだけど、パフェ取れないのは普通に問題
      • 別に得点を取れなくても全体の流れは何も変わらないので体験はギリギリ成立しているけど…
    • 何よりも自分が悪いのかシステムが悪いのか判断できないあたりがつらい (そのせいで原因究明が遅れた)
    • 一応書いておくと、エンディング以外の旗判定は私はほぼ確実に正確に入力を入れられます
      • そこまで行くと逆に面白くなくてどうしたものかな~と悩んでいたくらい

どうしたか

  • 判定
    • 2段階目のEMAを消した
      • これによって素早く動かしたときに即座に判定が出るようになった
      • 多分大体の人が感じていた不満はここ
        • 丁寧に旗を振らせるように誘導するというのも考えたけど、それをあのチュートリアル形式で説明できる気がしなかったのでやめた
        • というかチュートリアル無しでもちゃんと遊べるべきなので、まぁこうするのが筋という感じ
    • 安定状態になったと判断する閾値を0.75から0.95に上げた
      • 2連続で旗を振ったとき (上右とか) に、きっちり途中で止めなくても判定が出るようになった
        • ただちょっと方向は意図してないことがあるかも (先端のEMAがまだ収束してないから)
        • 途中で気持ち止まるようにするくらいにすれば大丈夫
      • シナモンルートがパーフェクトできるようになった
        • パーフェクト自体を取ったことはまだ無いけど最後の6つを全部取れたので大丈夫だと思う
  • チュートリアル
    • タイミングを判定に入れ、余計な入力を無視するように変更
      • 実は前と「理想的な方針 (拍に合わせて入力)」は一切変わってないのだけど、点数の増え方が変わることで意識が多分変わる (ことを期待している)
    • 紆余曲折
      • もっとゲーム的にする (ユーザを積極的にさせる) 案
        • どう判定を入れればいいのか・快適に入力するにはどうすればいいのかを探ってもらう意味合い
        • でも元々旗のチュートリアルは「メガホンのチュートリアルでちょっと盛り上がっちゃう気持ちを落ち着けさせる」意味合いがある (工場への静かな廊下に繋げる為) のであんまりよくない
        • ちなみに今のを倍速にして一回やってみたんだけど全然できなかったのでやめた
      • 手首で振らせることを示唆する案
        • 素早く2連続入力することを要求することで、腕では間に合わないことを悟ってもらう
        • これも結局楽しくなっちゃうので却下
        • 今の「リズムを判定する」方式だと必然的に素早い動きをしたくなるので、まぁ、大丈夫ではないかという気持ちもある
      • 頭や足でリズムを取ることをもうちょっと説明する案
        • 言語無しでやるにはちょっと無理がある
        • 代わりにスクロールする画面の方にはたまに出てくるようにした

これで本当にプレイしやすくなってるかは正直わかんないです。よかったら感想もらえるとわかりやすいです。

まとめ

こういうの難しいよねっていうのは昔からずっと言ってましたので、まぁ難しいなという感じですね。

結局複雑な処理でどうにか判定をするよりは「単純な処理」のほうがユーザもわかりやすいみたいな話が普遍的にありますよね。メタ的に捉えてるわけでは無いと思うんですが、結局そういうものが (人間に取っても) 単純なのかしら。

ただ今回の問題の4割くらいはチュートリアルの設計の失敗だと思っていて、ここは大きな反省点です。まだまだ「無知の人間」になるシミュレーションが足りないですね。

あと修正が遅れたのはいろいろやってて忙しかったからです。はい。

残りそんなに期間もありませんが、ぜひ楽しんでいただけると嬉しいです。

おわり。

*1:exponential moving average, 気持ちは low-pass filter

雑記240303 コメ返

phi16.hatenablog.com

想定していたよりも外に届いてしまったみたいです。でも思ったよりも反論は少なかった (細かい話は色々あるけど)。

いくつかコメントを頂いていた ので、また勝手に面白そうな話題を抽出して勝手に喋る回をやります。

タイトルからわかる通り、この (this) 記事はそんなに広まることを想定したものではありません (だからと言って何か意図があるわけではないが)。

VRゲームについて

nkawai “特に「VRゲーム」というジャンルが死に体 (に見える) ” VRチャットとかやってる人たちは、VRのゲームは、既に終わっていると考えている。日本でVRのゲームがほとんど出てこないのはそういうことなんだろうか?

tattyu VR体験するとどうしてもシングルゲームでもメタバースとかOWな要素を求めてしまうけど、実際には狭い箱に押し込められる様なゲームばっかりで狭さを実感してしまう。。。ゲームって狭いんだなって感じる。

これは的を射ている且つ興味深い話題で、確かに私はほぼVRゲームをやっていません。いくつか (Rez Infinite, Beat Saber, Thumper, TO THE TOP, スペチャン, Budget Cuts, HL:A, その他) はやってますが「VRゲームとして」はハマってません。

この「VRゲームとして」というのは結構面白いポイントで、ゲームとしては好きなんですよ。だけどそれぞれやってることが全然違うし与えられる体験が別物なのでこれらを「VRゲーム」というジャンルで括る意味が無いんですね。普通にゲーム (interactiveな、具体的に行動を促される媒体) として楽しいです。

ゲームの表現技法が進化していくようにVRゲームの表現技法もまた進化していっているところなのは疑う余地がありませんが、だからと言ってそれは「VRゲーム」としての技法ではなく「ゲーム」の技法だと思うのです。

何が言いたいかというと、「VRゲーム」それ自体はプラットフォームの名前でしかないということです。「PS5ゲーム」と同じ括りなのです。

 

「何故こうなってしまったのか」という問いを考えたいところですが、ここには2つ前提があります:

  • VRゲーム」は面白くないと考えられている。
  • VR」は私は面白いと思っている。

まぁどちらも納得行くものでしょう。前者は「ただのプラットフォームに面白さも何もない」、後者は「私はゲーム以外の目的にVRの価値が出ていると思っている」という話です。

で、どうしてこうなったかという話で言うと、「VRをデバイスだと思っていたから」だと思います。つまり正しく「新しい入出力装置のこと」だと思っていた。そしてそれは当たり前です。

確かに、プレイヤーの視界を塞いで全方向に自由な映像を投影できる!手の位置・頭の位置を使ってアクションさせることができる!とても魅力的です。

しかしゲームというのは古から「1ボタン」「上下左右」で十分面白かったのです。だからゲームの面白さそれ自体はここ (デバイス) から出てくるものではありません。

特にVRバイスはゲームに向いてないデバイスで、例えば即時入力をする方法がボタンしかありません。これはつまり従来のゲームのインタフェースと何も変わってない (それどころか厳しい) ということです。だいたいメニューとかのコンテンツ以外の用途に使われるし。

ゲームにおける即時入力の重要性はまぁいろんなゲームをやる方ならわかると思いますが、だからこの時点で「話が違う」となるはずなんですよね。ジェスチャ入力では操作精度に限界がある。

 

「メニューに使われる」という現象はある意味で本質的で、これは「ボタンはVR世界に存在するはずがないから」→「世界に存在しないもの (メタレベルの存在) に対応させる」という自然な発想です。

だけどこれは従来のゲームの発想である「プレイヤーには (コントローラを介して) 不思議な能力が備わっている (ことになっている)」というやり方とは逆です。従来のゲームで近い存在としては Wii とかがありますね。人のナマの動きをなんとか取ろうとしている。

でもその WiiキラーコンテンツWii Sports であったように、そういうデバイスによる遊びって多分「手を動かすことによるゲーム体験」が楽しかったんじゃなくて、それを介したコミュニケーションが結局のところ一番面白かったんじゃなかったかって思います。

知らんけどね。でも私は実際それが楽しかったよ。ボウリングの球後ろに投げたりさ。

その延長線を考えれば、確かにそういう「何らかの媒体を介した些細なコミュニケーション」というものが、VRだと有利なんじゃないか、って思えるはずです。

そこが結局VRChatが楽しい理由だと思うし、そこがVRの面白いところだと私はずっと思っています。

 

そうなるともうじゃあ「面白いコンテンツ」なんていらないんじゃないか、ってなるかもしれません。でも私はまだ先があると思っています。

VRというプラットフォームの上に乗った「VRSNS」というプラットフォームは、それ単体が「新しい媒体」になる程の能力があります。これは言わば「ゲームジャンル」なのです。

シューティングという基盤に乗ったFPSという基盤に乗ったバトロワというジャンルがあるように、パズルに乗った落ち物パズルに乗ったテトリスの派生ゲームがたくさんあるように、汎用的な基盤の上には「さらに面白さを特化した体験のジャンル」が乗るのです。

言うまでもなく、VRSNS上にあるたくさんのワールドはその「VRSNS性」を活用した面白さをderiveします。その引き出し方はまだたくさんあるはずです。

分かる通り「VRゲーム」と「VRSNS上のゲームワールド」は別物なわけです。家庭用ゲームと遊園地でみんなで遊ぶためのアトラクションが違うように。それぞれに良さがある

そして、私個人はVRSNS上のワールド媒体の先がもっと見てみたいと思うから、こっちを注視しています。そんな感じですね。

 

そして、これは「VRゲーム」にも言えることです。

VRゲームという外枠に乗っかるだけでは面白さがなくて。何か作りたい、大切なコアみたいなものがあった上で、それを表現するのに「VRが最適である」となる、且つプレイヤーもそれを感じられるような体験をつくれたら、それはとても良い「VRゲーム」になることと思います。

そしてそういうものが市場を埋め尽くすようになったら、きっとジャンルとして生き残れるようになるのです。

 

一つ面白そうな個人的な解釈として、「VRによって不気味の谷を越えてしまったのではないか」と思っていて。普通にコミュニケーションができるほどに没入感が出てきてしまって、従来の「なんやかんやで魔法が使えます」というゲーム的ご都合主義が使えなくなってしまった (正確には、使うと面白みが減る) ように思えます。

つまり「私達はただの人である」ことを認めた上で、それでも、というコンテンツであるべきなのかなって。そういう「ちゃんとしたゲーム」の方向性はまだ残っている気がします。作るのが大変だから。

AIについて

flowing_chocolate 『作れる人がいない。やりたいことをやる為に必要なモノが多すぎて、それをわかっている人がいない。』/作るところはAIで作れるようになる?その膨大なデータ量どうするの?という話が出てきそうな気もする。  

peppers_white ここら辺の問題はフルダイブでも起こりうると思っている(特に小石に夢中になって目の前のイベントに気づかないこと)あとはAIで量を傘増しは手段であって手法ではないのでやっぱ下の下よね今のところ  

yooo_gooo AI搭載ゴーグルが出たら一気に加速すると思う。text2VRで妄想の世界が作れるようになったら楽しそう  

casa1908 読んで思ったけど、すべてを人の手で作るのは無理がある気がする。そう言う意味では、AIとか自動生成の比重が高いローグライクとかと意外と相性がいいのではないかと思った。ゲームエンジン作りが大変そうだが。  

nakamura-kenichi 今までの手法は「ポリゴンとマテリアルからGPUパワーでブリブリと空間を生成する」やったで、最高峰のNVIDIAとUE5な未来やったけど、OpenAIが新しいマイルストーン刻んだからなあ。これから先は全く新しい解釈が要るやで。

言いたいことは分かります。文意も意図も発想もわかります。

が、私はAIによって本質的な問題が解決するとは思っていません。というかそう主張しているつもりだったんですが、なかなか伝わらないようです。

概ね2番目の方と同じ主張ですが、AIで「量」を作り出すことはできても「筋」を作り出すのは結局人間で。

そして筋が大切なのです。大事なものが大事なところにあり、そうでないときには無いように、「筋を表現する力」が。

今はもういろんな創作界隈が「そういう時期」になってきたように思います。実は昔からそうだったはずなんだけどね。

AIがそこまでできるようになる未来を私は否定しませんが、「量産されるもの」はただそれだけの理由で面白くないと言われるはずなので、結局はどこか違うところを目指して人間が世界を広げていくんじゃないかな。

それまでもAIがやりはじめることになったら…どうかな。たぶんその頃にはコンテンツに対する態度がまるっきり変わってそう。

筋じゃない部分はもっと量産化できるようにならざるを得ないのかなとは思います。でもそれでいいんです。例えばゲームエンジンみんなで作ってもしょうがないし、コンパイラ作ってもしょうがないでしょ。

その辺をAIとうまく共作できるようになるとすごく捗るんでしょうけどね。まぁそういうことになるのかな、とりあえず仮でそれっぽくしてもらって人が細かく直すっていうフロー。ちゃんと直すフェーズを遂行できれば、それはそれで理想的かも。

 

「妄想をそのまま表現できる」みたいなのはそれだけ聞くと理想的なんですが、実際に出てくるものは「想像力の限界」になってしまうんでしょうね。この感覚はモノ作ったことある人ならわかるでしょう。

一瞬で考えきれる範囲なんて大したことなくて、それを時間掛けてじっくり濃密にしていく必要があるわけ。それはそれで、現実が見えて良いかもしれませんけどね。次にやるべきことも明白になる。

ORGANISMについて

akanama “今重要なのは「要素要素で他媒体を越える」ことではなく、「作品に筋が通っていること」” … わかる。そして現在のVR体験でもっとも筋が通っているのはVRChatのワールド『organism』だと思う。

で、「では何が筋なのか」という話題です。ここはもう個人差あると思ったので丁寧には書かなかったんですが、ORGANISMは個人的にもある意味で面白い対象だったのでここに書いておきます。いままで感想書いたことないんじゃないかな。

結論から言うと、「VR空間としては筋が通っているかもしれないが、ワールドとしては面白くない」というのが私の見方です。つまり「好みではない」でした。

空間が不思議に繋がっていることそれ自体はいいんです。全体にテーマがあることもわかります。だけど「匂わせが主で答えない」態度、そしてそこから繋がる「私達の存在を世界が認識していない」態度があんまり好きじゃない。

そっけないじゃないですか。それが好きっていうのも理解できますけど。

つまり「体験として筋が通っている」かっていうとそうじゃないと思うんですよね。そこには「一貫性」はあるけど、体験それ自体を司る芯、軸、コアみたいなものは存在していない。正確には「存在しているとおもってはならない」。

あると思っているのなら、それは体験者の主観の中だけです。一応言うと、そういう作品の在り方を否定するわけじゃない。そういうものだ、というだけ。

「ちょっと曲がり角を進むと全然違う世界が広がっている」というのは確かに劇的に見えるかもしれないけど、それはコンテキストを切断する行為です。空間として繋がっていても世界として繋がっていない。切り取られた本のページみたい。

まぁライブ系で急に別世界が出てくるよりは潔いですけどね。世界を切り替えるコストは低いのだから、その劇的さを適切に示すにはそこに努力が、コンテキストがなければならない。見える形で。

私はもっと寄り添ってくれる、人々のことを認識し受け入れてくれる「世界」が好きかな。

ちなみにこれは言葉遊びじゃないから、「こんにちは、なんとかさん」って呼んでくれるキャラが居ればいいとかそういうことではない。どうやらこういうところがわからない人がまだまだ居るみたいなので、良い世界が出来てくるまでには時間が掛かりそうですね。

 

あの世界には動くようなギミックがほぼ無いから、そういう意味で安心して探索できる、っていう話はもちろんあると思うんですよね。だからこそこれは「空間」ではあるのです。対してちょっとでも動くものがあると、全てを疑わなきゃいけなくなる。

だからこういう空間は「世界の深さをユークリッド空間に埋め込む」ことになる。…ちゃんとわかりやすい言い方にしたかったんですが私はこれ以外を知らないです。要は縦横奥行きを使って「世界の深さ」を表現しなきゃいけないってこと。

そうすると深さの限度が空間構造 (\mathbb{R}^3) に支配されることになる。それがなんだか勿体ない気がして、私はそうじゃない世界表現のほうが「先」があるんじゃないかなって思っています。

はい。

おわり

またなんか思うことあったら書くとおもいます。でも最近のもやもやは結構解消できたかな。

最近のVR体験界隈について

私を含む。

結論を先に書きます。

  • まだ面白くない。
    • 私や周りのみんなは満足かもしれないが、コンテンツとして閉じた「領域」にはまだ至っていない。
  • 作れる人がいない。
    • やりたいことをやる為に必要なモノが多すぎて、それをわかっている人がいない。
  • 時間が掛かりすぎる。
    • 極論を言えば「ゲームより自由な媒体」なので「ゲームより時間が掛かる」はず。
    • だから今現在の時間感覚では詰めきることができない。
      • 規定された期間でどうにかするべきというのは、別の話。
  • だから継続性のためのボトルネックになっているのは「限界を作れる人間」だと思う。
    • そこまでいかないと面白くないから。
      • 今現在で面白いと言っている人が、ただ「VRが面白い」と言っているのか「コンテンツが面白い」と言っているのかを私達は区別できない。
  • そして制作時間が全然足りていない。
    • 量産化をするのはコンテンツを終わらせる行為だと私は思う。
    • 作業の為の時間ではなく、その前の設計段階の時間が足りていない。

つまり私には「まだ早い」ように思えていて、様々な根本的問題に面向かって対処しない限り、「当たり前のコンテンツ」に落ち着いてしまう気がする。

あ、「面白い」は interesting の意です。

所感

本当にみなさんよくやってると思います。頑張りを至る所から感じます。

それが文化として醸成されていることは疑いようが無いんですが、ただそれを外の人が楽しめるコンテンツとして出せるようになっているかというとまだ足りないのかなと思うのです。

まぁここには選択があって:

  • 既に中に居る人のために作る
    • 人の動き、文化、そういう基盤の上で初めて成立するコンテンツを組み立てなきゃいけない。
  • 外に居る人にも向けて作る
    • まぁVRなので中に入ってもらうしか無いんですけど、その境界を越える為のエネルギーを事前に与えなきゃいけない。

どっちも大変だと思います (ちなみに私は前者を選びました)。この2つは排反というわけではないんですが、同時に成立させるには必要なものが本当に多すぎます。

後者を目指すとするとその「ガワ」に比重が寄って、コンテンツのコアが薄くなる。前者だと、当たり前のことを当たり前として進めるから (その方が面白いことができるから!) 外にリーチしにくい。

まぁ、前者スタイルで「コンテンツのコア」がちゃんと備わっているものを私は数えられるくらいしか見たことがないですが…。

ともかく、私が思うのは「面白そうだと思って実際行ってみたら、そうでもなかった」みたいな不幸なケースが見えないところで起きているんじゃないか、ってことです。

何がコンテンツなのか

人に依ります。

本当に。

例えば:

  • 人と話せる。
    • 普段のVRChatのように。
  • 特定の人に会える。
    • ライブとして顕現したりする。
  • 視覚聴覚演出を観る。
  • ストーリーを鑑賞する。
  • 世界に干渉する。

極端な例なら、「折角能動的な気持ちになってVRをやってみたのに受け身コンテンツばかりだった」は大きなミスマッチになるわけです。VRChatにゲーム系の人間が少ないのはこういうところにあるのかな?

私はそれでも「体験の話を人とできる」のが楽しいのでそれはそれで良いと思っていますが、それはコンテンツとして閉じたものではなく、まぁ誰にでもできることではない。

万人受けするコンテンツは存在しないというのは昔から言う話ではありますが、これは「受け皿が無い」という話なのでちょっと違います。

例えば今回のVfesはその受け皿をできるだけ広くしようとする努力を感じますね (企画段階から)。

 

能動的コンテンツの範疇は受動的コンテンツの範疇よりもよっぽど広いと思っていますが、ただやればできるわけではないのが難しいところ。

特に「VRゲーム」というジャンルが死に体 (に見える) のは、逆に「受動的コンテンツを軽視したから」でもあると思います*1。要は見栄えがね、あんまりよくない。

対して能動性と受動性を最もうまく掛け合わせることが出来ている媒体領域が「ワールド」だと私は思っていて、だから「ワールド」という媒体はもっと先がある気がするんです。

ただふらっと見に来るだけでも良い。モノに興味を持って色々動かしても良い。そこには「塩梅」があって、人に依る。特に複数人が居るとその特徴が顕著になります。

で、だから、そういうものって、「ゲームを作る人間」にも「映像を作る人間」にも作れないと思うんですよ (大前提が違うから、その肩書を捨てなければ)。それが野生の人間が強い理由に見えます。

しかしそうすると細部に (ゲーム/映像を作る人間なら当たり前のようにやることが) 行き届かないポイントが出てきて、これまた外の人にリーチしない原因になる。

それをどうにか補うためにチームを組む。わかりやすい現状の説明になっていますね。

ディレクターの役割

私は「ディレクター」を director (direct-or, 行先を導くモノ) として認識していて、その意味で以降使います。

媒体が複雑になればなるほど、それが「どうあるべきか」に対する答えは長くなっていきます。

「体験者がどうなるべきか」だけではない。「こういう人はこうなって、こういう人はこうなる」そしてそこにグラデーションがある

理想を掲げること自体が難しい上に、それをじゃあどうやって実現するのかというのも、もっと難しい。だからディレクターは好き勝手な理想を掲げることが出来ない。

だからここの役割を分割することはできなくて、ディレクターが実現しなければならない。まぁ、そういうものなのでしょう。

私 (の担当範囲) はそれを engineering で (矛盾点を一個ずつ潰していくことで) どうにかしました。この補い方は人に依るようで、「演出で人を惹き付ける」「音で強制力を出す」とかもまたその手法の一種かと思います。

全部使えれば一番強いと思います。私はできていません。

 

何か「信頼のおけるコア」が無いと、行先にたどり着けないましてや行先が存在しない可能性が出てくるわけです。

しかもその信頼はちゃんと「この世界に則ったモノ」でなければならなくて (人の動きが違うから、別媒体の為の技法をなかなか流用できない)。それが出来る人間は居ないなって思う。

居ないから、私達はできるだけ固定観念を捨ててこの媒体へ最適化する努力をしなければならない。できるだけ、よくなるように。

努力をしなければならない。

 

そして同時に思うのは、「ディレクターは満足してはならない」ということで。

ディレクターが「面白い」と思うレベルが他の人よりも低かったら、その (作者にとっては) 面白いはずの作品はきっと面白くないものになることでしょう。

例えば来る人間は「映画」「ゲーム」「演劇」その他あらゆるものを体験してきた人なわけで、そんな人に自分の作品を面白いと思ってもらうには「ちゃんとやることをやる」必要がある。

ただ重要なのは「要素要素で他媒体を越える」ことではなく、「作品に筋が通っていること」だと思っています。筋が通るというのは意識の話じゃなくて、明確に観えるものとして。体験として。

何故なら、普通そうするから (しないと勿体ないから)。そしてここがなんだか全体的に足りてない気がするなあと思う部分でもある。

「明確に観えるものとして」というのは、ストーリー的にこういう意図で、とかではなく、ちゃんとVR空間として筋を通すということで。

…まぁこの辺は私個人の課題意識 (「制作者は鑑賞者と対等である」) が絡んでるので今回は省きますが…。

少なくとも、「何でもできる」というのは最弱の意思で、そこから捨てていくことこそが作品性なはずです。

何でもよかった時代は終わりです。

媒体として、「VR空間」としての筋を見極める眼が顕れたらいいなあと思います。

ちゃんと作るために

VR空間として作品を作るの、本当に時間が掛かります。それはそうなんですが、一応丁寧に書くと:

  • ゲームと違い、プレイヤーの行動を規定できない。
  • 映像と違い、プレイヤーの画角を規定できない。
    • 現実で無理やり奥まで歩く。大きなアバターで壁にめり込む。カメラを飛ばす。
  • VRだから、プレイヤーが興味を持つものを規定できない。
    • その辺の小石に関心を持ってしまって後ろで起きている大演出に気づかないかもしれない。

これを「制御する」のではなく、「許容する」ために時間が掛かるのです。私達は何らかの形でこれらを許さなければならない。

一番やらなきゃいけないことは正常系じゃなくて異常系の設計なのです。理想的状況から離れても大丈夫なように。いや、それもまた理想的であるように。

これもやり方は色々ありますが、何にせよやることがあまりにも多い。そのために criteria (判断基準?) みたいなものが必要だったりもしていて、例えば私は「好奇心に従う/自ら楽しもうとすると、体験が最大化される」ように作りました (= そうじゃない場合は体験が弱まることを許容する)。

 

もう一度書くと、見えるものではなく、見えないものを作るのに時間が掛かるのです。正常系に対して異常系の分岐は多すぎる。

だから制作工程って結局こうなるんじゃないかって思う:

  • 意識を確立する。
  • 基礎を検証する。
  • それらしく見える範疇まで辿り着く。(ここで或る種の安心感が得られます)
  • 見えるものを組み切る。
  • 見えない部分を延々と作っていく。

私は完全にこれでやりました、最後の2工程は同時進行ですが。

人々にクオリティが判断されるのは大体4工程までの内容なんです。が、「判断できる以前に実は切り捨てられている人々」を救うために5工程目が必要なわけです。

特に見えない部分って根幹設計にも関わっていることが多くて (誰をターゲットにするか、どんな行動を許すか)、最初から考えなきゃいけないけど、最後に作らざるを得ない。だから制作中に揺れ動いてしまうもので、「きっとできるだろう」が「できなかった」とき、もう一度全体設計を見直す必要が出てきてしまう。

だからそこのイテレーションを回すために、最初の2工程に時間を取る必要が出てくるんだと思います。この段取りはゲーム作りとほぼ同じですね。

結局、今やっている制作期間の見積もりっていうのは全然足りないんじゃないかって思います。私は足りませんでした、ずっと至る所にある課題の解法を考え続けていた。

一年スパンで一作品に集中するのは私に向いてない (他にやりたいことが出来なくて悲しい) ようなんですが、それでも足りないとなると私には手に負えるものではないのかもしれません。まぁゲーム制作に数年掛かるのは当たり前になってますし、今回に関しては最初から全力でやらないと終わらなそうな期間だったのが原因ですが…。

ちょっと本当に、この辺の「制作に何が必要なのか」は明確な言語化が必要になってきている時期なのかもしれません。

 

言語化をするとそこから人に能力が伝わって、「できる人」が増えることにも繋がります。今はそういう状況が始まらんとしている時期で、うまくいけばそのうち能力を獲得した人がたくさん芽吹くような気がするのです。

そしてそうならないと、終わる。

これからどうなっていくのか

素直に、今のやり方は続けられないと思います。が、それは金銭面とか云々以前に、できる人が居ないからです (報酬が云々はまた別の話題です)。

どうしても短い期間でどうにかしなきゃいけない課題を個人のパワーでなんとかしているのが現状で、私はそれはそれで面白いとは思っていますが、「ちゃんと余裕がある状況で」「好きなものを作る」ときのほうが当然面白いと思う。

誰かがtwitterで「制作途中で告知を出すんじゃなくて、完成してから告知をするべき」に類似たことを言っていました。なんだか忘れてしまった感覚でしたが、そうだなあと思います。悪い文化を受け継いでしまっているんだなあと。

まぁ案件はギリギリに来るものみたいなどうしようもない現実の話もあると思いますが、もう少し未来を想定してちゃんと良いものを作れる状況にどうかなってほしいものです。

ぶっちゃけ隔年でいいと思う。

 

だから私は今年を自分の能力を再確認する年にしました。そういう時間が無いと道具も成長しないから、使い古した斧を振るうことしかできません。

まぁ極限環境で成長するのもありますが、もっと根源的に「棲まう土地を変える」とか*2そういう変化ができるのは、制約のない自由なタイミングのみだと思いますので。

 

面白いものがこれからもたくさん出てくることを願います。

おわり。

*1:まぁあと能動性を履き違えているケースも多いですが

*2:Houdiniとか

私とVRChat 6年目

phi16.hatenablog.com

一応毎年書いております。が、今年分は書く内容が少ないですね。はい。

Resonark 4

phi16.hatenablog.com

この頃も光を作っていましたね…。今も変わらん。

実はもともとは全然違う案というか構成で話を聞いてたんですが私がいろいろ言って (?) 現在に至ります。

自分の不得意な領域がよくわかったというか。私は基本的に「コンテキストを通す」のが好きで、それ以外が苦手らしいです。それが良い結果になったことを願っていますが。

確か Cubes (experimental) のライティングの実装はこっちの GI の後に作られていて、そこそこ流用してたりします。「今」にも引き継がれていたりする。

VR演出について考えてみた

もはやいつの…って気持ちだけど確かに1年は経ってない。

結構コレを基にしてアレができているところがあります。大体わかると思う。言ったこと、言わなかったこと、色々ありましたけど。

今年はどうしましょうね。多分もう演出というジャンル自体の限界が見えてきていて、他、つまり「コンテキストをどう組むか」にそろそろシフトしていくんじゃないかって思…っているんですけど。どうかな。私がそれを好きなだけなのかな。

まぁまだ私の視えている限界は世に出ていないので作りますけどね。それが今年の目標です。

次にやりたいテーマとしては…演出よりは、うーん、なんだろう。「インタラクション」もまた違うと思っていて、それによって何をするか、じゃないですか。アニメーションだと狭すぎるかな。ゲームもジャンル違いだしな。

なんだか今年、「結論が出てしまう」気がするんですよね。残酷な話でもある。そうするともう素直にやっていくしかないみたいになるんだよね。

でもいわゆる「VRゲーム」ジャンルが停滞してしまったような状況よりはまぁ良い位置に来ていると思います。ちゃんと媒体というものの意識が育っているから。

今年は成長の年かな、やっぱり。

Knot Puzzle

phi16.hatenablog.com

これは昔からやりたかったやつ。細々と書いたので言う事無し。

面白いのは宣伝?ツイートが 1000RT 3000Fav 行ったこと。わりとニッチコンテンツのつもりで作ったのだけど、やっぱり「パズル」に釣られたのかしら。

ひもがうにょうにょしてるだけで面白い (あと私がかわいい) ところでそこそこ拡散されやすいかなとか思っていたけど、それだけじゃあこうはいかないよね。みんなパズル好きなんかなまぁ。わからん。

世の中の流行りは未だよくわかりませんね。

終わり

なんと今年は終わりです!わ~ 小さいことは色々ありましたけど:

  • Mardini (断念) (~3/18)
  • 曲 (6/1)
  • 初めて (動画配信形式での) VJ をした (6/16)
  • Cubes (experimental) が Venice Immersive の Worlds Gallery に選ばれた (なんで?) (7/20)
  • 1027_experimental を作った (10/27)
  • あと個人的には某アに某方と一緒に行けたのが良かった

どうしてかな~

なんやかんや

わ~

「今」だの「アレ」だのはこれです。はい。

まだ公開始まったばかりですが。ずっとやってました。なんとかなって良かった。

色々制作期間に考えていたことは全部これに入っているので、是非「読んで」ください。

よく書いてるような解説はねー、多分出さないです。が、普遍的な「思うこと」は書いておきたいなあって思っているところです。

あ、だから誰かに解説書いてもらえたら嬉しいなって思っています。何のために何があって何が実現されているのかを。批判も見たいな~

批判見たいから自分で書くかもしれない。どうせ全体に対してなんか書きたいと思ってしまうだろうし。

例えばね、「難しい」ってだけだと批判にならないわけですよ。そこには意図があって、実現されているものがあるのですから。でもその読み取った比重は人によって異なるだろうから、そういうものが見てみたいですね。

あ、質問されれば全然答えますよ。特に技術的な話 (= 普遍的な話) ならもちろん。

 

作ってるときはいっぱい言いたいことあったんだけど、今はなんだか穏やかな感じで面白いです。だから今年あんまり喋れる気しないんですよね。

多分それでいいんだろうけど、それだけだと世界が進まないような気もするので、もうちょっと形式を整えて出力したいところです。

まぁ、その辺はおいおい。「終わった」くらいのタイミングで。

というわけで

今年は自主制作をやります。作るもの、「世界に存在させておきたいもの」がいっぱい溜まっているのです。

あとふわっとアバターとか衣装とかもやりたい。あとリアル服もどうにかしたい。まだ10ヶ月もありますから。

のんびりとやっていきます。よろしくおねがいします。

おまけ?

  • 2023年
    • 3月 Mardini
    • 4月 Knot Puzzle
    • 5月 Knot Puzzle
  • ~以下略~

日記 240129

最近ちまちま考えてることについて考えていたことについてなんとなく書きます。

色々と (今のが終わったら) 作りたいものが (大量に) あるんですが、その中の1つに「万物を作るためのツール」があります。

現在、何かを作るのに…いろいろ。いろんなものを経由しなければいけない状況です。Unityもそうだし、Houdiniとか、モデリングツール、ドローツール、プログラムのコンパイルと実行…

めんどくさい!

というのは世の中の9999割くらいの人間が思っていることだと思うんです。私もそう思います。

でもこういうものは特化することに意味があるので、ツールは絶対に共通化されることはありません。それはそれで良いです。

問題はその間の連携がなかなかできないことだと思います。

今私はHoudiniを軸に据えて色んな物を走らせることでその状況が多少マシになった感じになってますが、もっとやりたいことは色々あるわけです。

というわけで、もっと汎用的な…こう…「空気」を作ってその上ですべてを回すというのがやりたい。空気ほど空気じゃないかもしれないけど。

そういえば前にもちょこちょこ書いたことではありますね:

いやほんと。全人類は不幸やなーと思う。世の中のツールの workaround が出回るたびにそう思う。正気か?と思う。

良くするためにいろんなことを考えています。多分私みたいな人間しか思いつかないものが結構あって、それが良いものになってくれると私は思っている。dependent type とか。

 

でも同時に悩みがあって、まぁ「誰かやるんじゃないか」という。いや、正確には「私よりももっとできる人間がやるのではないか」かしら。

まぁ現時点でそうなっていないわけですけど、そうだとしても「私じゃなくて良いんじゃないか」と思う。つまりこれは外れクジではないかと。

こんなことの他にもやりたいことはいくらでもあって、自分にとってそれがやりたいことではあって。でもそれを止めて「空気」を作ることの是非よ。

何より似たようなことは昔やろうとして頓挫したのよ。まぁその頃は私の性能が低かっただけではあるんだけど、今で十分かどうかも知らん。

同時にどう生きるべきかを考えますね。私はなんだかんだコンテンツを作りたいんだと思います。趣味で。

全部やると常に3人分生きなきゃいけない感じになるので困ります。今でさえ困っているというのに。

 

自分が世界で最もそれに向いていると思えるわけはないけれど、なんだかそこそこ向いてそうではあるんです。

まぁやってみてダメだったらやめるのが良いんかもしれませんね。どうせなんか途中で別のことやりはじめそうだし。

いろいろやりたいですね。