はりうすブログ (のすけのメモ)

湘南にある小さな会社 代表 ”のすけ”のブログです

【コードが織りなす複雑系な世界】UnityのコーディングとWebのコーディングの違い

こんにちは、のすけです。

Unity(ユニティ)デビューして2ヶ月くらい。

作った物は2つくらいですが。


だんだんWebのコーディングとUnityコーディング(ゲームコーディング)の違いが分かってきたのでメモ

Unityとは?

誰でも作れるゲーム!とゲームの民主化をはかった最強のゲーム制作ツール。

それがUnity。(主観入ってます)

f:id:hollywis:20210122154352j:plain

youtu.be


HTML的なコードはない!

Unityは全て、GUI(グラフィカルユーザインタフェース)で作っていく。


ゆえに、使うのはキーボードというよりかは[マウス]や[トラックパッド]。

なので、全体の構成を記述するHTML的な物はなく


[Sceneビュー]と呼ばれる3D空間ないしは2D空間上に配置される。

f:id:hollywis:20210122141646p:plain


だから、このキャラクターも、Sceneビュー上にマウスで配置した。

ただ、x,y,zの絶対座標はあるので、キーボード入力で位置を微調整できる。



HTMLを積み上げ的に書くのではなく

position:absoluteを使いまくって実装していた人は

Unityでも近い感覚で作ることができる。(relative的な相対座標はおそらく無いっぽい)

そこに表示されているのは全部GameObject!!

[Sceneビュー]上に表示されている物は全て[GameObject]という型で定義されている。


Webでいうならば全てDivみたいな感じだ。(DOMと言ってもいいかもしれない)

だから、、、

キャラクターもGameObject

四角い箱もGameObject

地面もGameObject

光源(太陽的な)もGameObject


さらには、我々が見ている、この世界を覗き込む[カメラ]ですらGameObject



GameObjectには[座標と大きさ]などだけがある。


そこに様々な機能をAddComponet(コンポーネントを追加)していくことで、あらゆるものに変身できる

f:id:hollywis:20210122142951p:plain


この箱は、ただのGameObjectに

[箱型のメッシュ]と[箱型のメッシュレンダラー]、そして[箱型のマテリアル]の3つを付与することで表現できる。


コンポーネントを切り替えることで、箱にも球体にも、ボタンにも、光にもなれる。

メッシュという三角形の集合体

あらゆるGameObjectにはメッシュやマテリアルを設定できる。


メッシュとは言わば装飾だ。

メッシュがあるから、僕らはそこに物があると認識できる。


厳密にいうとメッシュとは三角形(ポリゴン)の集合体だ。

f:id:hollywis:20210122143805p:plain


例えば、この箱は六面体だが、1つの面に対して2つの三角形(ポリゴン)を使っている。

だから、三角形の数(ポリゴン数)は面の2倍なので12個だ。

マテリアルはCSSっぽい

Webの世界でボタンに色をつけたりするときCSSを使うと思う。

画像を貼り付けるときは、backgroud-colorなんかを使うよね。


じゃあUnityはどうするのか?


答え:マテリアルを使う


f:id:hollywis:20210122144155p:plain


マテリアルとは質感を表現するモノだ。

メッシュ(ポリゴンの集合体)に色を塗りたくるか、画像を貼り付けることができる。


こんな感じで、マテリアルをただの箱に貼り付けるだけで、様々なオブジェクトに擬態できる。

コーディングは生態系??

ほとんどマウスでできちゃうなら、Unityでコーディング不要では?

いやいや、もちろんある。


Unityのコーディングは基本的には GameObjectに対して行う


重要なのでもう一度言うけれど


Unityのコーディングは基本的には GameObjectに対して行う

のだ。



これはちょっとビックリした。


f:id:hollywis:20210122144941p:plain


こんな感じでコードすらGameObjectにAddComponet(コンポーネントを追加)していく。

この画像で言えば[BoxScript]がそれだ。


だから例えば、何かにぶつかった時に消えるとか。大きくなるとか。のコードはその箱のGameObjectに対して行う。


f:id:hollywis:20210122151018p:plain


何だかめんどくさそうに思えるけれど。

これはこれでコードがスパゲッティのようにグチャグチャしなくていいと思う。


JavaScriptで言うところのAddEventListenerで全て書いていく感じに近いと思う。

ボタンをクリックしたらevent発動!的なあれだ。



だから、全ての挙動を管理する巨大なコードがあるわけではなく。

複数のGameObjectに紐づくコードが織りなす複雑系な世界がUnityだ。


それは渡り鳥やの飛び方やイワシの群れに似ている。


渡り鳥の群れ全体を管理しているモノはいないが、個々の一羽一羽は独立した機能(法則・ルール・意思)を持っているだけ

でも全体としては意思があるような群れの生態系を描いて、効率的に島から島へと渡っていく。


だから、Unityのゲーム画面は常に生きている。

そこにはルールがあるだけで、精密な管理はない。二度と同じ画面には出会えないのだ。


UnityにおいてはGameObjectに如何に美しい(法則・ルール・意思)を持たせるかがコーダーの腕の見せ所だと思う。


Webはどちらかと言うと全体管理を徹底しているため、この点の思想が全然違うと思う。


ちなみにコードは全てC#という言語で書いていく。


所詮はデビュー2ヶ月の妄想かもしれないけれど、Web歴は相当長いのでこの点が感動ポイントだった。

UnityでもWebで出力できる

こんがらがって来るんだけど、実は

この複雑系な生態系であるUnityはWeb上でも表現できる。

こんな感じでブラウザ(Safari)で実行してみた。

f:id:hollywis:20210122151909j:plain


しかも、WebAssembly(ウェブアセンブリ)というブラウザからアセンブリ機械語)を実行できるようにする最新技術でコンパイルされるらしい!?から、実行速度も結構早い。


全部Javascriptで作るよりUnity使っちゃえ!とも言えるかな。

Webでできる、その他もろもろはできるのかな?

もちろんサーバーと通信できるし

  • 内部ブラウザでWeb画面を表示
  • 画像表示
  • 音声再生
  • 動画再生
  • データベース接続


なんかもできるのでWebでできることは大体全部できる。


ただ、C#で実装するので、C#のライブラリがないAPIなんかは利用しにくいけれど。

ゲームエンジンなのでPS4でも実行できるらしい

Unityで作ったモノはあらゆるプラットフォームで実行できる。


Webは紹介したけれど、Unityはゲームエンジンなので、iOSAndroidWindows, Mac, Linux,さらにはPS4やXboxOneなんかにも出力できるそうだ。

f:id:hollywis:20210122153541p:plain


そして、今後でるあらゆるデバイスもサポートするのではと思う。


正直、ビルドしたファイル群をどうやてPS4で実行するかは謎だけど、夢が広がるね。

終わりに: ゲームエンジンってつまり現実世界の物理シミュレーションってことは・・・

ゲームエンジンって、つまりは現実の世界の法則をシミュレーションしているってことなので、

つまりは、現実世界の諸法則を画面上で表現するための、地球における現在の最適解なんだよね。


という事は、記号表現においてはUnityの思想は全てを包含するわけで。。。


UnityやばしとWebエンジニアののすけは感じたのでした。


でもね。一番大事なのは、Unityでも表現し切れないあなたのその体!

それでは、また!

UnityのVisual Studio Codeセッティングメモ

こんにちは、のすけです。


Unityねたです。

前置き

今まで、nuxt.jsにtyrano scriptを入れてハイブリッドwebシナリオゲーム開発なんかやっていました。
↓↓↓
2039アナ民キャンパス


が、そろそろwebの表現力に限界を感じており、スマホアプリへ全てシフトするべく、勉強をはじめている今日この頃です。


Three.jsやbabylon.jsなんかも触り、webでもいろいろ出来て良いのですが、やはり「ゲームの民主化」を図ったUnityは素晴らしく

もうその恩恵に授かろうといういう気持ちです。


次はなんだかんだUnityは避けてきたんですが、もう避けきれなくなってきたので、潔くドップリつかります。


巷では、ゲーム以外のアプリ開発の事例はあんまり出てこないUnityですが、もう切り開いていくしかないですね。


取り急ぎ、Firebase接続してwebっぽく使えるように整備中です。

ただ、なにぶんゲーム開発が素人なもので、フォルダ構成やら構造造りから手探り状態です。



長くなってしまいましたが、今回のメモはUnityでのコーディングの味方

Vsual Studio Codeのセッティングメモです!!

必須設定

素のままいじっていて、全然インテリセンス効かなくて辛いな〜と思っていたので調べました。


まず、Unity側の設定として

Visual Studio Code Editorというのをインストールされている必要があるようです

f:id:hollywis:20210114150752p:plain

上のバーの[Asset]-[Package Manager]にあります


次に上のバーの[Unity]か[File]あたりにある[Preferences]を開いて

ExternalToolsのExternal Script Editorの設定をVisual Studio Codeにします

f:id:hollywis:20210114151417p:plain

これで、UnityからC#プログラムを開いた時のエディターがVSCodeになります。



続いてインテリセンスを効かせるためには2つツールをPCにインストールします

  1. Monoインストール

https://www.mono-project.com/download/stable/

  1. .NET SDK core

https://dotnet.microsoft.com/download

これで最低限、PCとUnityがわの設定は終わりです

続いて、Visual Studio Codeをカスタマイズしていきます

おすすめ設定

Visual Studio Codeはとても便利で、公式・非公式のプラグインを入れることで

どんどんパワーアップしていきます。

ここでは、おすすめのプラグインを紹介します。

使いやすいエディターにカスタマイズしていきましょう!!

C#を扱えるようにするプラグイン

  • Code Spell Checker

英語のスペルミスを修正してくれる。これでいいんだ!という自作ワードも辞書に追加できる

  • Debugger for Unity

Unityをデバッグするやつ

  • Japanese Language Pack

日本語化するやつ

  • Unity Code Snippets

Unityのスニペットを一撃で入れるやつ

  • Unity Tools

Unityのツールらしい。

アイコンを表示してくれて見やすい!!

  • Bracket Pair Colorizer

ネストされた記述をわかりやすく色分け

  • zenkaku

全角文字をわかりやすく表示。半角と全角間違いを防ぐ。


これらをインストールして設定!!

最後にOmniSharpe設定

Visual Studio CodeのSettingから

f:id:hollywis:20210116210813p:plain


Monoと検索して


「Omnisharp: Use Global Mono」

の設定をautoからalwaysに変更します


f:id:hollywis:20210116210826p:plain


そして出てくる

f:id:hollywis:20210116211013p:plain


Restart OmniSharpをクリック!!!



そうすると......



f:id:hollywis:20210114152457p:plain


こんな感じでコード補完(インテリセンス)してくれます!!


「G」と入れただけでGameObjectがサジェストされまする。


まことに気持ちいい。


これでUnityライフが捗りそうです。

JetBrainのRaider買おうか悩んでましたが、VSCodeで良さそうです。

終わりに

これからUnity猛勉しつつ、ここにメモっていきます。

それでは。

Nuxt.js をPM2でデーモン化しながら起動する方法 最新版

Nuxt.js2系にリプレースして、PM2での起動方法が変わったため

紹介しておきます。


PM2のインストール

$ npm install pm2 -g


次にecosystem.config.jsに以下のように記述

module.exports = {
  apps: [
    {
      name: 'NuxtAppName',
      exec_mode: 'cluster',
      instances: 'max', // Or a number of instances
      script: './node_modules/nuxt/bin/nuxt.js',
      args: 'start'
    }
  ]
}


ここのscriptを呼び出す部分がキモですね
script: './node_modules/nuxt/bin/nuxt.js',


そしてビルド開始

npm run build


ecosystem.config.jsを読みながらデーモン化したサーバー起動

pm2 start


起動している事を確認

pm2 ls


ログを確認

pm2 logs

以上!


参考
How to deploy using PM2 cluster mode? - NuxtJS

Nuxt.jsで大規模なサイトをSPAで作って大丈夫?→やめた方がいいと思う

f:id:hollywis:20201103141159j:plain

こんにちは、のすけです。

Nuxt.jsチップスのお時間です。

Nuxt.jsはSPA・Universalモード(SSR&SPA)を選択できるのだけど

SPA(Single Page Application)

シングルページアプリケーション

全てのページ1つのHTML上に展開し、ページ遷移はクライアントサイドのJSでガシガシ書き換えることで

夢のような高速なサイト作成ができる!!

SSR(Server Side Rendering)

サーバーサイドレンダリング( Universalモード)

Nuxt.jsはSSRとか行っておきながら、どちらもいいとこ取りする(どっちも実装しなくてはいけなくて辛い!?)

Universalモードというのがあります。


HTMLをサーバーサイドでレンダリングするので、SEOに強いと言われている(詳細は不明。もはやGoogleが追いついている気もするので気にする必要もないかも)


従来のサーバーサイドコーディング&Vueを合わせた実装になり、かなり面倒。


サーバーサイドでHTMLをレンダリングするので貧弱なWebサーバーや回線だとSPAほどの速度は出ないが
Nuxt-linkを踏む場合のみ高速で画面遷移できる。

問い

「Nuxt.jsで大規模なサイトをSPAで作って大丈夫?」


最初よく分からなくて、まぁSPAでいいしょ!と思って作っていたのですが、、、

SPAで1年間運用し、その間に機能拡張をしまくって盛り盛りになったプロジェクトは

どうなったのでしょうか??

結論:やめた方がいいよ

規模が大きくなるにつれ、初期訪問者のjsコードのロード時間が長くなり

「なかなかページが表示されない!」

という結果になりました。


そこで、Universalモードに切り替えたわけですが全てのページをSSR対応に書き換える必要があり、大変に面倒でした。

特にクライアントサイドで動くコードとサーバーサイドで動くコードは違うので、それに頭を悩ませました。


なので、プロジェクトが一定以上大きくなるページ数が30ページ越えるくらい??

の場合には潔く Universalアプリケーションを選択してSSRした方が良いです。


SSR時の注意点

SSRモードの挙動はかなり複雑です。


Nuxt.jsのSSR/CSR処理について - 株式会社Japonline


こちらの記事が参考になったのですが、クライアントサイドレンダリング(CSR)とサーバーサイドレンダリング(SSR)のライフサイクルが


「初回アクセス、リロード時」・・・URLを直接叩いたりaタグで遷移した際
「内部アクセス時」・・・nuxt-linkやrouterで遷移した際
で違う!!

というとても複雑な動きをするので、どちらにも対応したコーディングが求められたりします。


ここんところを熟読しつつ、行ける!と思った方は

Nuxt.js適性があると思います。

Nuxt.js環境でGSAPプラグインを登録する方法

f:id:hollywis:20201020112351p:plain

Nuxt.jsにてGSAPのプラグインを使おうとする場合

Docs - GreenSock
このページの通りにやっても

Unexpected token {

とか色々出て動きません。


色々調べた結果、このようにgsap/dist/のパス指定してあげると動きます!

import { gsap } from "gsap";
import { MotionPathPlugin } from "gsap/dist/MotionPathPlugin";

gsap.registerPlugin(MotionPathPlugin);

参考:
Problem with Razzle and GSAP - GSAP - GreenSock

Nuxt.js のエラー 「Failed to execute 'appendChild' on 'Node': This node type does not support this method」

nuxt-linkで遷移した場合には問題ないのですが


リロードやURLを直接叩いた場合に以下のようなエラーが発生します

DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method.
    at Object.appendChild

原因としては、クライアントサイドとサーバーサイドのDOMに差異が発生しているためのようです。



特にv-ifを利用するとほぼ発生するように思います


その場合、v-ifの前後や、場合によってはコード全てを

<client-only></client-only>

で囲えば発生しなくなります



ご察しの通り、これで囲った部分は、クライアントサイドレンダリングになりますので

その辺りはご注意ください


参考:

【Vuetify】NuxtのSSRでVuetifyのDatePickerを使用したら「The client-side rendered virtual DOM tree is not matching server-rendered content. 」というエラー発生 - Qiita

ティラノスクリプトにfirebaseを連携させて自在に操る

f:id:hollywis:20200809020407j:plain

前回、シナリオゲームが手軽に作れるティラノスクリプト

強引にVue.jsを入れることをやりましたが。


次は、、、Firebaseを入れたい!!


やはり本格的なWebアプリケーションを作るためにはデータベースとの連携は必須。

そしてFirebaseのFirestoreならとても扱いやすい。


もし、Firebaseとティラノスクリプトが掛け算できるなら

どんなものでも作れそうですよね。


それではいきましょう!!

Firebaseを初期化する

f:id:hollywis:20200809014750p:plain

例によって強引にindex.htmlにscriptタグを埋め込みます。
firestoreとauthを使いたかったのでそれも入れています。


first.ksなどで初期化します。

;Firebase
[iscript]
console.log("Init firebase");
// Initialize Cloud Firestore through Firebase
firebase.initializeApp({
  apiKey: 'xxxxx',
  authDomain: 'yyyyy.firebaseapp.com',
  projectId: 'zzzzzzz'
});

f.db = firebase.firestore();
f.auth = firebase.auth();
[endscript]

初期設定をして

ティラノスクリプトのゲーム変数(f)にdbとauthを登録しておきます。

呼び出す!

こんな感じで、例えばscene1.ksのiscriptタグの中で

firebase authenticationのユーザログイン情報を取得したり。

;Firebase
[iscript]
f.auth.onAuthStateChanged(user => {
        if (user) {
          f.displayName = user.displayName;
          f.email = user.email;
          f.uid = user.uid;
        }
});
[endscript]


こんな感じで、firestoreの任意のコレクションからデータを取ったりできます

;Firebase
[iscript]
(async () => {
   let query = await f.db.collection("contact")
      .orderBy("created","asc").limit(20);

    const snapShot = await query.get();

    const datas = snapShot.docs.map(doc => {
      return doc.data();
    });
   console.log(datas);
})();
[endscript]


f.msg の内容 : [emb exp="f.msg"][p]

この例では、contactコレクションから20個データを取って来て

メッセージに1つ目の内容を表示しています

f:id:hollywis:20200809022108p:plain

まとめ

ティラノスクリプトでもFirebase使える!

[iscript]タグは万能!

いやぁー。もう何でも作れそうですね。