【Unity】【エディタ拡張】中身のない空フォルダがないか調べるエディタ拡張

Unityでは、フォルダを作るとmetaファイルが作られる。 もしそのフォルダの中身が空なら、意味のないmetaファイルが作られていることになるので、それを検知するエディタ拡張を作りました。

using UnityEditor;
using System.Linq;
using UnityEngine;

public static class CheckEmptyFolderMenu
{
    [MenuItem("Tools/Check Empty Folder")]
    public static void CheckEmptyFolder()
    {
        // Assetsフォルダ以下に空フォルダがあるかチェック
        var emptyFolders = AssetDatabase.FindAssets("t:DefaultAsset")
            .Select(AssetDatabase.GUIDToAssetPath)
            .Where(AssetDatabase.IsValidFolder)
            .Where(path => AssetDatabase.GetSubFolders(path).Length == 0)
            .Where(path => AssetDatabase.FindAssets("t:Object", new[] { path }).Length == 0)
            .ToArray();
        
        // 空フォルダがあればログ出力
        if (emptyFolders.Length > 0)
        {
            Debug.Log("Empty Folder:");
            foreach (var folder in emptyFolders)
            {
                Debug.Log(folder);
            }
        }
        else
        {
            Debug.Log("Empty Folder: None");
        }
    }
}

ゲーム会社に就職するための最短経路

そんなものはない。そんなに就職したければひたすら手を動かしていろ

「ゲーム会社に就職するためには」論

近頃、Twitterで「ゲーム会社に就職するためには」という話題をよく見かける

具体的な引用は避けるが、見かけた意見はこうだ。

  • ゲーム系の専門学校はやめておけ。大学に行け
  • 一度落ちたくらいで諦めず、何度も応募しろ
  • 最初から大手を狙うな。落ちたら中小に応募するって心構えじゃ間に合わない
  • 個人でゲームを作れ
  • 最新ゲームについていくためにPS5くらいは買っておけ

いろいろな意見があるが、今本気でゲーム業界を目指している人は、すべて聞き流してもらっていいと思っている。これらの意見は、自分はたまたまそれでうまく行ったという生存者バイアスであったり、自分の会社にはこういう人がほしいという意思表明だったりするからだ。まあ、特定の会社しか狙っていないというなら、その会社に所属する人あるいは社長の意見には従えばいいと思う。

ただ、一つ間違いないと思うことはある。「ゲーム会社に就職したかったのにできなかった者は、手を動かしていなかった」ということだ。

(なお、筆者はゲームプログラマであることから、以後本記事中での「ゲーム開発者」はプログラマのことだけを指すこととする。アーティストやプランナーとしての就職を考えている人は、その職種の人の話を聞いてもらいたい)

私が見てきた新人ゲーム開発者

私は四年制大学を卒業したあと、運良くゲーム開発会社に採用していただき、それから計2つのゲーム会社で、併せて4年働いている。ジュニアクラスを脱した程度の経験しか積んではいない。そんな短い業界歴ではあるが、ゲーム開発の最前線に新卒で就職してくる人の中に、全く何もできないという新人はみたことがない。

業界内の知人から聞くところによると、ごく稀にからっきし駄目な新卒が入ってくることはあるらしい。が、それはごく少数の例だ。

(なお中途は別。業界に入って以降全く努力せずなんの戦力にもなれないのに、転職活動は上手で転職成功する人はそこそこいる)

ゲーム業界しかしらない自分がこんなことを言うのはおこがましいが、ゲーム業界に入ってくる新人の平均値は、他の業界と比べてとても高い方だと思う。

ゲーム専門学校の存在

ゲームクリエイターという職業は現在とても人気がある。人気があるということは、業界を志望するライバルも自然と増える。競合が激しくなればなるほど、生き残り就職できる人らのレベルが上がるのは当然だろう。ただ、業界の新人のレベルが高いのは、他にも理由があると考えている。

一つはゲーム専門学校の存在。専門学生は就活の一環として、年に数度開かれる発表会で現役社員を前に自分の作ったゲームをプレゼンする。ここで発表される作品の大半は箸にも棒にもかからないクソゲー、あるいはゲームにすらなっていない、発表に間に合わせただけのダメ作品なのだそうだ。

ただ、そんな中でも光る作品はある。1学校1クラスあたり、5-10%はプロが唸るような作品を提出してくる。そんな数%の優秀な学生と、一部の、作品の出来はイマイチでも他で光るモノがあり将来性を買われた学生が、ゲーム業界に就職している。新卒就活でよく聞かれる、「学生時代頑張ったこと」を具体的な作品として仕上げられた人だけが、業界の門をくぐることができる。

大学生には、そのような作品発表会の場が設けられることは少ない。だが、先述した優秀な専門学生と比べても、採用するに足ると判断された人が就職できている。

就職するのに専用の免許がいるわけでもない、そんなゲーム業界に就職するための専門学校の存在は、間違いなく業界のレベルを引き上げている。

ゲーム会社に就職する人らは皆どうかしている

商業ラインで売るに足りうるゲームを開発するには、高く幅広い技術を要する。だからこそゲーム開発は楽しいし、そんな開発の一部に携われていることに誇りを感じている。

だが、所詮ゲーム開発はゲーム開発なのだ。ゲームは人生を豊かにするが人類に不可欠なモノではない。

ゲーム大好きでゲームクリエイターに憧れた子供は大人になるまでに多くのことを学ぶ。我々が生活するのに欠かせない仕事があり、ゲーム開発よりももっと直接的に人の生活を良くする仕事があることを知る。それでもなお、ゲーム開発がしたいと思う人が今ゲーム業界で働いている。

加えて、ゲーム会社の給料は低い。もうほんと低い。ここ10年で急速に改善されてはいるが、求められるスキルに対してもらえる給料は少ない。一緒に働いていて、これだけのスキルがあるなら、他の業界に転職すれば何百万も給料が増えるだろうに、と思う優秀な方を沢山見てきた。

ゲームのビジネスモデルの特異性故、給料が少なくなりがちなのは仕方ない。それでも僕らはゲーム会社で働いている。損得勘定よりも、ゲームが好き、あるいはゲーム開発が好きなどといった理由を優先して、ゲーム会社で働いている。

それでもゲーム会社の就職を目指すなら

強力なライバルと競い、安月給は覚悟の上で、なおゲーム業界を志望する人には、是非手を動かし続けてほしい。面接までに、具体的な、一定ラインの品質を超えた「○○を作った」といえるようなものを用意すれば、どこかには引っかかると思う。学生時代に凄まじいゲーム作品を作ってしまうようなスーパー専門学生と戦うのなら、自分もスーパー専門学生になるか、それに対抗できるだけの別の何かを作るしかないのだ。

ただ、健康第一でね。

GameTech Weekly 004

一週間サボった上、火曜更新に間に合わず…… ただ、しばらくやめるつもりはないので、更新を気ままにお待ちください。 ネタが少ない週は無告知で更新しないかもです。

その週に読んで面白かった記事をまとめて詳解しています。 紹介する記事は、その週に公開されたものに限りません。

C#】string-interpolation(文字列補間)がC#10.0からboxingが発生しないようになる修正が入ったらしい(DefaultInterpolatedStringHandler) - はなちるのマイノート

https://www.hanachiru-blog.com/entry/2023/07/13/120000

個人的激アツの更新。早くUnityにほしい。

Unity ECS で高速化!とりあえずキャラを 5,000 体出してみよう! - YouTube

https://www.youtube.com/watch?v=zn3m6ZFppdQ

Unity Japan公式が送る、ECSについての実例動画。現存する世界で一番わかりやすい資料なのではないか

7分で理解するPrefabの変更点 - YouTube

https://www.youtube.com/watch?v=LTXnCc3pg6k

Unity 2022で登場したUnityのPrefabシステムの変更についてまとめた動画。安心の公式。

Unityチームでの輪読会の取り組み紹介とUniRx/UniTaskクイズ - Mirrativ Tech Blog

https://tech.mirrativ.stream/entry/2023/07/19/111524

neueccさん(UniRx/UniTaskの作者)が全問解けないって言ってて面白かった

いろいろな円を描く by Processing|おかず

https://note.com/outburst/n/n631a3845186c

シェーダー芸するときに役立ちそう。

Rendering "God Of War :Ragnarok (pdf)

https://sms.playstation.com/media/documents/GOWR_Stephen_Mcauley_RenderingGOWR_GDC23.pdf

God Of War最新作の講演資料。全編英語の骨太資料。全部は読めてない……

きれいなコードを書けという話について - Software Transactional Memo

https://kumagi.hatenablog.com/entry/write-beautiful-code

かなり話題になっていた記事。「デザインドキュメントをたくさん書くこと」「blameをわかりやすい粒度にすること」「不要なコードとテストをどんどん消すこと」どれも良く言語化されている。

「ITエンジニアこそ筋トレをやるべき理由 徹底解説(With Google Cloud)」というタイトルで登壇しました。 #devio2023 | DevelopersIO

https://dev.classmethod.jp/articles/it-musles-google-cloud/

先週話題になっていた発表スライドの補足記事。科学的根拠に基づいているので、信用ができる。

【Unity】【インポーター】ドット絵のテクスチャのインポート設定を自動化するインポータークラス

Unityにドット絵(Pixelアート)をインポートするとき、画像のようなお決まりの設定をしないと、せっかくのドット絵がボケボケになってしまいます。

以下のクラスを Editorフォルダ以下に置けば、ドット絵テクスチャをSpritesフォルダ以下に入れるだけで、勝手に画像のような設定に変えてくれます。

using UnityEditor;  
using UnityEngine;  
  
public class SpriteImporter : AssetPostprocessor  
{  
    private const string PixelSpritePath = "/Sprites/";  
 
    private void OnPreprocessTexture()  
    {  
        if (assetPath.Contains(PixelSpritePath))  
        {  
        TextureImporter textureImporter = (TextureImporter)assetImporter;  
        // Spriteとしてインポートする  
        textureImporter.textureType = TextureImporterType.Sprite;  
        // Single Spriteにする  
        textureImporter.spriteImportMode = SpriteImportMode.Single;  
        // 16pixelを1unitとして扱う  
        textureImporter.spritePixelsPerUnit = 16;  
        // ポイントフィルタリング  
        textureImporter.filterMode = FilterMode.Point;  
        // 非圧縮  
        textureImporter.textureCompression = TextureImporterCompression.Uncompressed;  
        // テクスチャサイズは最大1024x1024  
        textureImporter.maxTextureSize = 1024;  
    }  
}  

AssetPostProcessorはこういった特定のフォルダ以下に入れたアセットに、指定のルールを与えることができるので、手動の面倒な作業を減らすことができます。

Texture2D.GetPixelData()で直接ピクセルデータを書き換えるとアセットも変更されてしまう

Unity 2020.1から Texture2D.GetPixelData()というAPIが追加されています。 このメソッドを使えば、CPU上にあるテクスチャ色情報を直接参照することができるため、GetPixels()と比較して、テクスチャ色情報を配列にコピーするコストを下げることができます。

しかし、このAPIを使ってアセットとしてインポートしたTexture2Dを直接書き換えてしまうと、アセットそのものも変更されてしまいます。

実例

Texture2Dを受け取って、ネガポジ変換するコードを書きました。

(画像は先日秋葉原に行った時の写真です)

using UnityEngine;

namespace Clay.ImageProcessor
{
    public class NegativeConverter : MonoBehaviour
    {
        [SerializeField] private Texture2D inputTexture;
        
        public void Start()
        {
            var pixels = inputTexture.GetPixelData<Color32>(0);
            for (var i = 0; i < pixels.Length; i++)
            {
                var color = pixels[i];
                color.r = (byte)(255 - color.r);
                color.g = (byte)(255 - color.g);
                color.b = (byte)(255 - color.b);
                pixels[i] = color;
            }
            // 変更を適応する
            inputTexture.Apply();
        }
    }
}

このコードを実行すると……

なんと、元の画像アセットごとネガポジ変換されてしまいました。 また、このスクリプトを再度実行すると、元の画像に戻りました。

改善方法

  1. スクリプト内でTexture2DやRenderTextureとして複製し、それらが持つピクセルデータを書き換える
  2. 一度書き換えてしまった後でも、アセットを右クリックしてReimportすれば元に戻る
    • これで直るのは、Unityが書き換えたのは「元の画像ファイルをエンジン内部で読み取って作ったデータ」であって、大元のJPGファイルは変更されていないからです。

まとめ

UnityのAPIには、不意にアセットそのものを破壊してしまうモノが多数あります。注意して開発を進めましょう。

GameTech Weekly 003

今週は忙しかったので、タイトルとURLだけで…

Unity / C

Rain Effects Breakdown | Cyanilux

https://www.cyanilux.com/tutorials/rain-effects-breakdown/

【Unity】Unityでマーシャリングを利用してDLLの関数を呼び出してみよう! 株式会社ロジカルビー

https://logicalbeat.jp/blog/15418/

【Unity】正式リリースされたばかりのECS Graphicsを触ってみた DOTS Instancing とは? 株式会社ロジカルビー

https://logicalbeat.jp/blog/15417/

URPを使用した12種類のビジュアルエフェクトを解説した電子書籍をUnity Technologiesが無料公開。使用例がわかるサンプルプロジェクトも配布! | ゲームメーカーズ

https://gamemakers.jp/article/2023_07_03_42877/

『Unity 2022 LTS』用のサンプルとして作られた2D農業シミュレーションゲーム『Happy Harvest』、Unity Asset Storeで無料公開 | ゲームメーカーズ

https://gamemakers.jp/article/2023_07_07_43332/

はじめての Unity ECS - Entity Component System を使ってみよう! - YouTube

https://www.youtube.com/watch?v=vzF00Wb6wNY

Understanding vtable And Unity’s Memory Layout — Mechanisms for Polymorphism in Unity

https://rossam.medium.com/understanding-vtable-and-unitys-memory-layout-mechanisms-for-polymorphism-in-unity-14eeab0f4c1a

【Unity】エンジニアも知っておくべき「ダイアログ」と「モーダル」の違い - LIGHT11

https://light11.hatenadiary.com/entry/2023/07/10/192928

基本的には同じだけどちょっと違うマテリアルが欲しい時に便利なMaterial Variant【Unity】 - (:3[kanのメモ帳]

https://kan-kikuchi.hatenablog.com/entry/Material_Variant

jiaozi158/UnitySSReflectionURP: Screen Space Reflection for Unity URP (Universal Render Pipeline).

https://github.com/jiaozi158/UnitySSReflectionURP?

T[](配列)・Memory・Span・ポインタ・参照変数(ref)の使い分けと相互変換 - Qiita

https://qiita.com/Funny_Silkie/items/ea21dd1e3d06d48ffdad?utm_campaign=popular_items&utm_medium=feed&utm_source=popular_items

Unreal Engine / C++

facebook/igl

https://github.com/facebook/igl

ゲーム開発技術記事

Fake Liquid - Blender 3.6のSimulation Nodesを使用した容器内の疑似流体を構築する方法を解説したチュートリアル動画!

https://3dnchu.com/archives/fake-liquid-blender-3-6-erindale/

そのほか一般記事

【ACADEMY】魅力的なオープンワールドの作り方 - GamesIndustry.biz Japan Edition

https://jp.gamesindustry.biz/article/2307/23070701/

ゲームのテストプレイをAIで自動化するツール『Playable!』リリース。自然言語で指示するだけでテストプレイしてくれる機能も年内に実装予定 | ゲームメーカーズ

https://gamemakers.jp/article/2023_07_05_43174/

ChatGPT Code Interpreterの活用方法を片っ端から試していく

https://zenn.dev/karaage0703/articles/5df61d446684f9

インプットを太く、アウトプットも太く 【仕事の姿勢】 - YouTube

https://www.youtube.com/watch?v=ckXWpIC0Xzg

[最初の一歩]OSSにチョット🤏だけコントリビュートできるようになってきて見えてきた個人的コツを書きます

https://zenn.dev/uyas/articles/77fe54072ce0ce

GameTech Weekly 002

ゲージをテクスチャで増減させる - みつまめ杏仁

https://limesode.hatenablog.com/entry/2023/07/01/152130

  • Unreal Engineにおいて、atan2関数とグラデーションテクスチャを使って円グラフゲージを実装する例を紹介しています
  • グラデーションテクスチャ生成には、Processingを利用しています

I Tried Making a Stronger Chess Engine - YouTube

https://www.youtube.com/watch?v=_vqlIPDR2TU

  • Coding Adventureシリーズ最新作。Unity実装のチェスAIを強化する試行錯誤を学べるようです

The new Water System in Unity 2022 LTS and 2023.1 | Unity Blog

https://blog.unity.com/engine-platform/new-hdrp-water-system-in-2022-lts-and-2023-1

  • Unity公式記事。Unity 2022 LTS以降で使えるようになった「new Water System」について紹介しています
  • 記事で紹介している機能を試せるサンプルプロジェクトは、Unityエディタで取得できるようです

最新の「Blender」に搭載された「シミュレーションノード」で表現力をアップ! - Blender ウォッチング - 窓の杜

https://forest.watch.impress.co.jp/docs/serial/blenderwthing/1512319.html

  • 6/27に正式リリースされたBlender 3.6で追加された、シミュレーションノードについて紹介しています。

Blenderブロック崩しを作る|Melville

https://note.com/melville/n/ne58ad13a7db2

[Unity - URP] ステンシルでだまし絵っぽい表現を作る - YouTube

https://www.youtube.com/watch?v=xtNqn5WW7EQ

  • 10行ほどのコードで、Unity URPでだまし絵のような表現を作る実装例を示しています

【Unityにおける大量描画のテクニック】ライフゲームタワーを使ったパフォーマンス比較 | QualiArtsエンジニアブログ

https://technote.qualiarts.jp/article/56

  • Unityの3D空間でライフゲームを可視化するシステムを使って、GPUインスタンシングを使うとどれだけパフォーマンスが向上するのかを調べた記事です
  • DrawMeshInstanced / DrawMeshInstancedProceduralを使うと、描画パフォーマンスが劇的に向上することを学べます。

実はあったSerializedDictionary - Qiita

https://qiita.com/shirokuma1101/items/4a1bb6ea4038cd2f540c

Accessing texture data efficiently | Unity Blog

https://blog.unity.com/engine-platform/accessing-texture-data-efficiently

  • Unityが提供する様々なテクスチャにアクセスするAPIのパフォーマンス比較をしています。