Unity 2Dゲーム作成 備忘録

Unity(2019.4.15f1 → 2020.3.11f1)でつまづいたところをメモしていきます。

URP対応のモザイク・ぼかしシェーダー(2D / Sprite Renderer)

pya1234さんのモザイクシェーダーをChatGPTを使って、URP対応のシェーダーに修正しました。「経緯とかどうでもいい」という方は、目次でダウンロードをクリックしてください。

 

ことの経緯

私は今まで、冒頭でリンクさせていただいたpya1234さんのモザイクシェーダーを重宝させていただいてたのですが、URP対応のプロジェクトで利用しようとしたところ、エラーが出て使えなくなってしまいました。
これは困った…。
旧来のシェーダーで使えたGrabPassが、URPでは使えないことが原因なようです。

「URPに切り替えたことだし、前々から気になってたシェーダーグラフでモザイクシェーダー作っちゃう?(ウキウキ)」と思ったのですが、これがまた、話はそう簡単にはいかず…。
超ベーシックなモザイクシェーダーであれば、すぐに作れるのですが、pya1234さんのシェーダーのように、オブジェクト越しに見えるものすべてにモザイクをかけることができません。

そこからネット探索の旅に出た末、UI用のモザイクシェーダーの作り方を発見できたのですが、このシェーダーをSpriteRendererに使ってみたところ、うまく作動せず…(当たり前ですが)
ちなみに、Imageで使用すると、ちゃんと作動します。

その他、3D用モザイクシェーダーの作り方はたくさん発見できたのですが、3Dと2Dはまた少々異なるらしく、「そんな設定2Dにないんですけど?」という箇所が現れて頓挫。

そもそも、シェーダーの知識がそんなにない私がネットを探索したところで、探索範囲は限られており、「やはり素人の私には無理か…」と諦めかけたのですが、一縷の望みをかけてChatGPTにお願いすることにしてみました。

実は、pya1234さんのモザイクシェーダーがエラーを吐きまくった際、一番最初にChatGPTに修正依頼したのですが、何度やってもうまくいきませんでした。
なぜなら…私に知識が皆無だったからです。
今思えば、すごい漠然とした、ChatGPT頼みの修正依頼をしていました。
しかし、今の私は違う。
URPモザイクシェーダーを作り出すために色々調べたせいで、初めより知識が備わり、的確な修正依頼をChatGPTに出すことができるようになっていたのです。

そして…
無事!pya1234さんのモザイクシェーダーをURP対応シェーダーに修正することができました!
ChatGPT凄い!!!
いや〜、「もう諦めて旧来のシェーダーに戻すか?」と思ってたので、本当に嬉しいです。

ダウンロード


修正したURP対応のシェーダーは、↓からダウンロードできます。
※大元はpya1234さんのモザイクシェーダーです。(著作権などで)問題がありましたら、取り下げますので、コメントにてご一報ください。
※素人の私がChatGPTで修正したものですので、自己責任でご利用ください。
※このシェーダーに関する質問をされても、素人ですので、何も答えられないです。
※Unity2021.3.28では無事動いてます。

ちなみに、モザイクシェーダーあるあるの「モザイクのセルが長方形になる現象」にも対応してみました。モザイクのセルを正方形にできます。

使い方

  1. ダウンロードした「mosaicURP.shader」をプロジェクトのAssetにドラッグ&ドロップする。

  2. Assetの「mosaicURP.shader」上で、右クリック > 作成 > マテリアルで、マテリアルを作成する。



  3. 「Pya_mosaicURP」というマテリアルが作成されるので、モザイクフィルター化したい2Dオブジェクトのマテリアルに設定する。

    下の図の場合、オブジェクトAとオブジェクトBの手前に、オブジェクトCが配置されているのですが、オブジェクトCのマテリアルに「Pya_mosaicURP」が設定されていて、オブジェクトA・Bそれぞれと重なる部分がモザイクになっています。


    ちなみに、「Pya_mosaicURP」を適用したオブジェクトのZ座標がカメラより手前になってしまうと、ゲーム実行時にモザイクが映らなくなるので、注意してください。(手取り早くモザイクオブジェクトを手前にしたくて、Z座標に大きめのマイナス値を入れるとそうなりがちです。)

  4. 「Pya_mosaicURP」のインスペクターで、モザイクのセルサイズ等を設定します。
    pya1234さんのDLページにも書かれていますが、こちらにもあらためて書いておきます。

    【Cull】
    詳しくないですが、2DだとOffでいいと思います。

    【Type】
    モザイクかブラー(ぼかし)かを選びます。4タイプから選べます。
    以下、pya1234さんのページから転記。
    ・モザイク1(mosaic1_normal) 
     普通のモザイク 
    ・モザイク2(mosaic2_average)
     色を平均化してモザイクを作る。1より色の再現度が高い。 
    ・ぼかし1(blur1_normal)
     周辺ピクセルの色を平均化する。
    ・ぼかし2(blur2_gauss)
     ガウス関数での重み付け。1より画像が平滑化される。


    【AspectRatio】
    モザイクのセルの正方形化に使います。
    作成しているゲームのアスペクト比を入れてください。
    (比率でなくても、そのまま入れても大丈夫です。例えば960×540で作っている場合、そのままX(横)に960、Y(縦)に540と入れて大丈夫です。)
    自動取得させたかったのですが、シェーダーでは本来取得できないらしいのと、代替手段について細々調べるのが面倒くさかったので、手入力にしました。
    長方形のままでいい方は、両方1を入れてください。作ってるゲームの画面比率のモザイクセルになります。(16:9で作っていれば、モザイクセルも16:9の長方形になります。)

    Mosaic
    「Type」でモザイクを選択した場合、ここでモザイクの大小を調節できます。

    Blur
    「Type」でブラー(ぼかし)を選んだ際、ブラーのかかり具合をここで調節します。

あらためて、モザイクシェーダーを作ってくださったpya1234さんに感謝です!
(あと、ChatGPTも!)


ゲームのローカライズ、何語がオススメか?

最初に断っておくと、私は趣味でゲームを作ってるだけの素人なので、確固たるエビデンスがあるわけではないことをご了承ください。
私の経験からいうと、「このへん狙い目だな〜」と思った…ってだけの話です。
(しかも、そんな目新しい話でもないと思います。)

 

私は、趣味でゲームを作ってweb上で無料公開しているのですが、私のサイトはどう言ったわけか日本人の来訪者が少ない(少なかった)です。最小で10%しか日本人がいなかったこともあります。
じゃあ、どこの国が一番多いのか?というと、言わずと知れた、中国です。
40%くらいは中国からの来訪者で、次が台湾。台湾は20%くらいのことが多く、その次に僅差で日本…ということが多かったです。
その他は、アメリカ、ロシア、EUが少量ずつ、あとはいろんな国から1〜3名…といった感じです。
(ちなみに、私は日本語で日本人向けにしか宣伝活動したことがないですが、なぜかこのようになってしまいました。多分、中国人の口コミ力がすごいのだと思います。)

 

そんなある日、来訪者の構成に激変が起きました。
スペイン語圏からのアクセスがうなぎ上りになったのです。
どうやら、メキシコのYouTuberが私のゲームをチャンネル内で取り上げたようで、あの絶対不動だった中国語圏(中国+台湾)からのアクセス数をあっという間に凌駕しました。
話題になったのは素直に嬉しかったのですが、「これもそのうち、すぐ下火になるんだろうな…」と思っていました。(バズりは、沈下も早いので。)
しかし、私の予想に反してスペイン語圏からのアクセスは、3年経った今もそこそこあり、中国(単体)並のアクセスを保っています。

 

なぜそうなるのか?というと、スペイン語を話す国が、思った以上に多いことに要因があります。
調べたところ、スペイン語公用語とする国は、21カ国あるようですね。
スペイン語話者も、中国語に次いで多く、世界2位なのだとか。

スペイン語の世界

21カ国のうち、どこか1つの国に刺されば、残り20カ国に広まる可能性が高いわけです。
これは中々魅力的です。
現在の私のサイトでは、4〜10位までスペイン語の国です。
もちろん、10位以下にも、様々な国に混ざってスペイン語の国が多数エントリーしています。
しかも、アメリカや(スペイン以外の)EUからのアクセスも増えました。
(スペインは10位以内に入っているので、「スペイン以外のEU」の話です。)
これは、言わずもがな、アメリカやEUスペイン語の話者が多いからです。
アメリカは一時、スペイン語話者が増えたことが問題となった時期がありましたし、EUは、EU内でいろんな国の人が移動しているため、スペイン語話者がEU内に散らばっているのだと思います。(ただの推測ですが)

 

それまで私は、「ローカライズするなら、英・中くらいかな…」と漠然と考えていたのですが、この出来事にあってからは「ひょっとしたらスペイン語って、英語より影響力があるのでは?」と思うようになりました。
また、中国は確かに人口は多いですが、広まっても中国1カ国でしかありません。
「いろんな国の人に知ってほしい」と思うなら、スペイン語の方が断然有利です。

 

話は少しそれますが、有料ゲームを作られている方もいらっしゃると思いますので、思い出した話を少し。

↓のページで、DMMの開発者の方が面白いことを書かれていました。

DMMのログイン・会員登録周りの多言語化対応 - DMM inside

中華圏のユーザーは英語圏・日本国内のユーザーに比べて課金率とARPPUが低い状態であることをデータ上で確認できていました。

そんなわけで、より高い精度の英語表記と、新たに中国語(繁体字)の対応をすることになりました。


どうやら、爆買いのイメージとは正反対に、中国人はあまりお金を落とさないようです。
実は、近所の焼き鳥屋(飲み屋)の店主が、「中国人は何も注文しない。4人で来て焼き鳥1本頼んで、あとはこっちが焼き鳥焼いてるのを見てるだけ」(中国人に限らず、外国人にとって、レストランの調理風景を見られるのは珍しいようです)と言っていて信じられなかったのですが、DMMの記事と照らし合わせると「然もありなん…」といった感じなのでしょうか。
(とはいえ、スペイン語の国が多い南米も、そこまで裕福ではないでしょうから、似たり寄ったりの状況かもしれませんが。)

 

ちなみに、今の私のサイトのアクセス構成ですが、無事に日本人が戻ってきて、日本人のアクセス数が50%にまで増えました…!
理由は、ゲームをパソコンだけでなく、スマホでもプレイできるようにしたからです。
噂には聞いていましたが、「パソコンなし、スマホのみ」という層がこんなにもいるのか…!と本当に驚きました。
増える直前は、日本人のアクセスは10%にまで落ち込んでいたので、アクセスが一気に5倍に増えたことになります。
時代はスマホなんですね。
周回遅れですが、いろいろ勉強になりました。

sprite swapを使ったアニメーションがうまくいかない時の対処法まとめ

何かとうまくいかないことが多いsprite swapアニメーション。
うまくいかないときの症状別に、対処法をご紹介します。

 

【A】アニメーションが微動だにしない

 [対処方法]
(1)アニメーションのタイムラインから、Sprite Resolver プロパティの全てのキーフレームをマウスカーソルで囲って選択します。
(2)キーフレーム上を右クリックして出てきたメニューから、「両側の接線 > 一定」を選びます。

f:id:ooo_washi:20210615100935p:plain


[原因]
Unityのマニュアルによると、「両側の接線 > 一定」にした時のみ、キーフレームに割り当てられたスプライトを探しにいく仕様のようです。(それ以外だと、プロパティの数値を計算してフレーム間補完をするみたいです)

 

【B】アニメーション がコマ落ちする。

Unityでは、レイヤーを使うことでアニメーションの部分置換ができます。
sprite swapを使ったアニメーションでは、レイヤーのブレンドの設定が「Additive」だとコマ落ちするようです。

[対処方法]
レイヤーのブレンドの設定を「オーバーライド」にする。 
(ちなみに、アニメーション の置換が反映されない方は、ウェイトが0になってると思いますので、1にしてください。)

f:id:ooo_washi:20210215161751p:plain

 

【C】sprite swapを使用したアニメーションクリップの再生と、通常のアニメーションクリップの再生がずれる。

[対処方法]
(1)通常のアニメーションクリップのサンプルレートを、sprite swapアニメーションのサンプルレートに合わせる。

f:id:ooo_washi:20210615102121p:plain

(2)通常のアニメーションの、キーフレームすべてを選択し、キーフレーム上で右クリック。「両側の接線 > 一定」に設定する。

f:id:ooo_washi:20210615102624p:plain


[原因]
アニメーションがズレる方は、おそらくsprite swapアニメーションのサンプルレートを少なくしていると思います。通常のアニメーションは、updateに合わせて1秒間に60回、アニメーションを更新しています。これは、サンプルレートをいくつに設定しても、60回更新し、滑らかなアニメーションを実現しています。
しかし、sprite swapアニメーションは、例えばサンプルレートを20にしたなら、1秒間に20回しか絵が切り替わりません。
これは、通常のアニメーションが2回更新されるのを待ってから、sprite swapアニメーションを1回更新することになり、このために、常に2フレーム分、アニメーションが遅れるように見えます。
これを解消するために、あえて通常のアニメーションのフレームレートを少なくし、フレーム間補完をなくす「両側の接線 > 一定」に設定します。

 

 【D】sprite swapを使用したアニメーションが小刻みに揺れる。

下記の記事をご参照ください。

ooo-washi.hatenablog.com

sprite swapを使ったアニメーションが小刻みに揺れる(位置がずれる)時の対処法

対処法

swapさせる画像を、縦横ともに【偶数ピクセル × 偶数ピクセル】にする。

例)
口パクさせるために、口の連番画像があるとする。
これは、「人物.psd」の中にレイヤーで入っている。
【偶数ピクセル × 偶数ピクセル】にするのは、「人物.psd」ではなく、口の画像そのもののサイズを【偶数ピクセル × 偶数ピクセル】にする。
おそらく、口レイヤーにおいては、口以外を透過させている人がほとんどと思うが、透過部分を無視した口の実画像部分のサイズが【偶数ピクセル × 偶数ピクセル】になっている必要がある。
(私は、全く同サイズの【偶数ピクセル × 偶数ピクセル】の肌色の下地を、全口画像の背景に合成して解決しました。)

 

なぜ、ずれるのか?

多分ですが、奇数ピクセルだと2で割り切れないために、上下左右どこか1ピクセルずらして配置される。このせいでアニメーションがガタガタと小刻みに揺れてしまう。

 

これで1日潰れた…
Unityホント疲れる…

本来の画像サイズのまま、画像を配置する方法

私は2Dのゲームを作成していますので、Unityのプロジェクトを新規作成する際、「2D」を選んでいます。また、PC用ゲームをメインに考えていますので、ゲームの画面サイズも固定しています。
Unityを始める際に参考にしたサイトでは960×540をオススメされていたので、私も960×540で作成することにしました。

さて、私は、960×540の画面の中に、100×100の画像を、100×100のサイズで配置する必要が出てきました。

「普通に配置すれば、できるんじゃないの?2Dなんだし」

そう思う人は多いと思います。私もそう思いました。
しかし…Unityはそれを許してはくれません。
普通に読み込んでゲームオブジェクトにすると、なんだかすごく小さい…。

「え…ちっさ!何コレ?」

適当に拡大しようにも、現在のサイズがわからないため、何倍に拡大していいのかわかりません。

私は思いました。
「そうだ!2DのくせにZ軸(奥行き)の概念があるからに違いない!
 きっと、めっちゃ遠くに配置されてしまったんだ!」
しかし、これは答えではありませんでした。
いくらZ軸を触ったところで直りません。

さて、100×100の画像を配置したのに、なぜUnityは100×100で表示してくれないのでしょうか?

答えは…

Unity(2D)は、「ユニット」という単位で画面を構成していたからです。
いや〜ビックリ。
そう言われたら、そんな説明を最初の方にチラッと読んだ気もするけど、それがここで活きてくるとはね…!

つまり、1ユニットの設定が10×10ピクセルなのか、50×50ピクセルなのかで、配置された画像の大きさが変わってしまうという仕組みだったのです。

ユニットって何?と思われた方は、Unityの「シーン」を見てみてください。
そこに、うっすらマス目が引かれていると思います。
この1マスが1ユニットです。

対処方法

(1)ヒエラルキーから「Main Camera」を選択し、インスペクターの「Camera」の「サイズ」を確認します。このとき、サイズにこだわりがない場合は、あとの計算が楽なので「5」に変えてしまってもいいと思います。

f:id:ooo_washi:20210109221527p:plain

(2)(1)を元に、1ユニットが何×何ピクセルになっているのか算出します。
「Camera」の「サイズ」は、「シーン」上のマス目の数を設定するものになります。
「5」の場合は、画面の中心から上方向に5マス、下方向に5マスの、合計10マス、マス目を設定することを意味しています。(ちなみに、横方向は成り行きとなります。)
この数で、設定したゲーム画面の縦サイズを割れば、1ユニットが何×何ピクセルなのかがわかります。
(私の場合は、ゲーム画面の縦のサイズが540ピクセルなので、540px ÷(5マス×2)で、1ユニットが54×54ピクセルであることがわかります。)

(3)アセットから、あらかじめ読み込んでおいた画像を選択し、インスペクターの「インポート設定」の「ユニット毎のピクセル数」を、(2)で算出した数に書き換えます。(画像は複数選択して一気に変えることもできます。)あとは、「適用する」を押して完了です。

f:id:ooo_washi:20210109224745p:plain

 

これで、100×100ピクセルの画像を、100×100ピクセルで配置できるようになりました。

 

Dynamic Boneが動かないときの対処法(2Dアニメーション)

Unityでもネイティブの機能で2Dのキャラクターにボーンを入れられるようになりました。
このボーンにDynamic Boneを設定しても動かなかったときの対処法です。

 

 

症状

ボーンも正常に入っていて、Dynamic Boneも正しく設定できている。なのに、「ゲーム」でプレビューするとピクリとも動かない。

f:id:ooo_washi:20210109190157g:plain

Dynamic Boneが正しく設定できているかは、以下の手順でチェックします。

(1)「▷」を押してプレビューする。
(2)画面が「ゲーム」に切り替わったら「シーン」に切り替え直す。
(3)ヒエラルキーから、対象のゲームオブジェクトを選択することで、ボーンの動きが表示される。

上図のように、ボーンは適切に動いているのに、画像がそれに追随できていないことがわかります。(本来、ブルーの横棒もボーンに沿って動く予定)

 

対処法

(1)編集>プロジェクト設定...>スクリプト実行順序(Script Execution Order)を開く。

(2)右下の「+」をクリックして「DynamicBone」を追加する。

f:id:ooo_washi:20210109162419p:plain

(3)追加された「DynamicBone」を「UnityEngine.U2D.CinemachinePixelPerfect」の上にドラッグ&ドロップする。(右の方の「-50」はUnityの方でいい感じの数字にしてくれるので触る必要なし)
f:id:ooo_washi:20210109162609p:plain

 

目論見通り、ブルーの画像も動いてくれるようになりました。

f:id:ooo_washi:20210109200114g:plain

 

補足

ネットを検索すると、3Dアニメーションやspineだと、「デフォルトより下(プラス側)」にするように書かれていますが、Unity 2D Animation だと、デフォルトより上にする必要があるようです。