2018年7月20日金曜日

UnityでスクリーンショットをSNSにシェアする簡単なやり方

無料で、自分の中では一番簡単にできると思ってる方法です。

まず、NatShare APIをアセットストアからダウンロードしてインポートします。
https://assetstore.unity.com/packages/tools/integration/natshare-mobile-sharing-api-117705

Assets/NatShare/Plugin/iOS/libNatShareというiOS用ライブラリのImportSettingが
現時点では何故かAnyPlatformにチェックが付いてるので
Any Platformのチェックを外し、iOSだけをオンにします。
(将来的にアセットの方で修正されるかと思います。)




次のスクリプトをScreenShotShare.csという名前で保存し
スクリーンショットを撮るボタンにAddComponent(スクリプトからでもエディタからでもOK)しておきます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

// RequireComponentは、このMonoBehaviourはButtonを必須としますよ、という意味
[RequireComponent(typeof(Button))]
public class ScreenShotShare : MonoBehaviour {
    Button button;

    private void Start()
    {
        button = gameObject.GetComponent<Button>();

        // クリックしたらコルーチンを実行するようイベントに追加する
        button.onClick.AddListener(StartScreenShot);
    }

    void StartScreenShot()
    {
        // コルーチンを実行
        StartCoroutine(Screenshot());
    }

    IEnumerator Screenshot()
    {
        // 連続でボタンが押されないようにボタンを無効化しておく
        button.interactable = false;

        // レンダリングが全部終わるまで待つ(待つとはいっても、1フレーム以内の話だけど)
        yield return new WaitForEndOfFrame();

        // スクリーンと同じ大きさでTexture2Dを作る
        var texture = new Texture2D(Screen.width, Screen.height);

        // スクリーンのレンダリング結果を全部Texture2Dで読み取る
        texture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);

        // Applyは、Texture2Dへの変更を適用するためのメソッド
        texture.Apply();

        // NatShare APiのシェアメソッドを、今撮影したテクスチャと、テキストと一緒に呼び出す
        NatShareU.NatShare.Share(texture, "Share Text");

        // もうtextureはいらないので消す
        GameObject.Destroy(texture);

        // ボタンを再度有効化しておく
        button.interactable = true;
    }
}

スクリーンショットを撮るのにApplication.CaptureScreenshotを使う方法もあるのですが
それをシェアするとなると、色々と面倒なことが増えるので、個人的にはあまりおすすめできません。


ここに示したのはサンプルで、実際の自分のゲームではシェア前に
ゲームプレイに必要だけど、シェア時に必要じゃなさそうなUIは消す
などの処理をしてからスクショ撮影するなどしてます。

2018年7月4日水曜日

UTS2を超シンプルなインスペクターに変更するエディタ拡張

概要


ユニティちゃんトゥーンシェーダーを使いたいけど、パラメータ多い!
影色テクスチャとか作るのめんどくさい!
既存の3Dモデルをぱぱっとユニティちゃんシェーダーに変更したい!


という、めんどくさがりな自分用に
マテリアルの変換機能、影色テクスチャ生成機能
自分が必要なパラメータだけ抜き出したカスタムインスペクタ拡張を作りました。

これを使うと下のgif画像のように、とんでもなく長いインスペクタが、とてもコンパクトになります。


自分用に作ったのですが、せっかくなので公開します。
エディタ拡張のソースも入ってるので、好きなように改造も出来ます。

注意事項


この拡張は、マテリアルを直接変更し、テクスチャも自動生成されます。
バックアップをとっておくか、最初はテスト用プロジェクトで実験してみましょう。


インストール方法


ここからUnityパッケージをダウンロードしてください。
https://www.dropbox.com/s/v8jl4t5d06vcoja/uts2easyinspector.zip?dl=0
(2018/7/5 15:40追記 一度生成された影色テクスチャがある場合に二度目が生成されないバグを修正いたしました)

ダウンロードしたらzipを解凍後、使いたいプロジェクトにパッケージを導入しましょう。

ユニティちゃんシェーダーでカスタムマテリアルインスペクタを使えるようにするには、シェーダーの書き換えが少し必要になります。
メニューの「Tools/UTS2簡単マテリアルインスペクタ/インストールする」を実行すると、自動で書き換えてくれます。

最初にダイアログが出てきますので、ユニティちゃんトゥーンシェーダーのあるフォルダを指定してください。

使い方


非UTS2マテリアルから、UTS2マテリアルへの変換


Mainテクスチャやノーマルマップが設定されているマテリアルに対し
プロジェクトフォルダでマテリアルを右クリック
メニューのTools/UTS2マテリアルに変換する、を実行します。
(複数同時でも大丈夫です)

マテリアルを直接変換し、影色テクスチャもメインテクスチャと同じフォルダに自動生成します。
(この機能だけでいいなら先程のUTS2簡単マテリアルインスペクタ/インストールする、は実行しなくてもいいです)



シェーダーはとりあえず、UnityChanToonShader/Toon_DoubleShadeWithFeatherが割り当てられるので、必要に応じて種類を差し替えてください。


簡単マテリアルインスペクタ


ユニティちゃんトゥーンシェーダーが割り当てられてるマテリアルは、次のようによく使いそうな項目だけを表示するようになります。


メインテクスチャの設定


メインのテクスチャは必ず指定してください。
メインのテクスチャがあれば、影色テクスチャを生成することができます。

影色テクスチャの設定


影色テクスチャの再生成ができます。
「一つ目の影色テスクチャを生成するボタン」を押してください。


このような、影色テクスチャ生成ダイアログが出てきます。
左がメインテクスチャ、右が変換された影用テクスチャです。

下の色相、彩度、明度をどのようにずらすか、を指定できます。

影色は、色相を少しずらし、彩度を高め、明度を少し落とすと、いい感じの影色になる気がします。
色々試してみていい影色を見つけてください。

いい影色になったら、下の「生成ボタン」を押します。
そうすると、無事影色テクスチャが生成され、マテリアルに割り当てられます。
(テクスチャはメインテクスチャと同じフォルダに生成されます)


他に影の大きさスライダーや、影のぼかし具合スライダーも表示してるので、これで影をどれくらいの面積、くっきりさせるかどうかを調節してください。

二つ目の影色テクスチャも同様の手順で割り当ててください。

アウトラインの設定


アウトラインの太さと色だけを設定できます。

ハイライトの設定


ハイライトの強さと色だけを設定できます。

リムライトの設定


リムライトの強さと色だけを設定できます。

その他の設定


簡単インスペクタは上に書かれた項目以外は設定できません。
これ以外に手を入れたい場合、インスペクタ一番上の「オリジナルのインスペクタに変更ボタン」を押して、値を調整してください。

アンインストール方法


メニューのTools/UTS2簡単マテリアルインスペクタ/アンインストールする、を実行してください。
インストール時に行ったシェーダーの一部書き換えを消去します。

その後はUTS2EasyInspectorフォルダを消去してください。


連絡先


何かあればTwitterまでどうぞ

2018年6月22日金曜日

UnityのGameViewのScaleを1に強制的に戻すエディタ拡張

UnityのGame Viewが勝手に拡大されるというMASAさんのツイートを見ました


そう言われてみると、思い返せば確かにプレイ時に手動でスケールを戻すことをよくしてる気がします。



非プレイ時にマウスのセンターホイールをスクロールするとここのスケールが変わるので、多分プレイボタンを押す際に間違ってセンターホイールに触れてるんじゃないかと推測してます。

プレイ時にスケールが拡大されてて戸惑うことはあってもうれしいことはほぼありません。
そこで、プレイ時に強制的にスケールを1に戻すエディタ拡張を書くことにしました。


UnityEditor.GameViewは公開されてないので、リフレクションを使ってアクセスします。
 
                var asm = typeof(Editor).Assembly;
                var type = asm.GetType("UnityEditor.GameView");
                EditorWindow gameView = EditorWindow.GetWindow(type);

というコードで、GameViewのインスタンスにアクセスできます。

問題は、GameViewのどの内部関数を呼べばスケールを1に出来るかです。

それを調べるために、GameViewのソースを見てみましょう
 https://github.com/Unity-Technologies/UnityCsReference/blob/master/Editor/Mono/GameView/GameView.cs

Scaleに関することなので適当にScaleで文字列検索してソースを読むと、SnapZoomの引数を1で呼べばスケールが1に戻りそうな気がします。

試してみましょう。

#if UNITY_EDITOR

using UnityEditor;

static class GameViewUtil
{   
[InitializeOnLoadMethod]
    static void CheckPlaymodeState()
    {
        // プレイモードが変わったときのコールバックに登録する
        EditorApplication.playModeStateChanged += x =>
        {
            // Playモードに変わったときに処理する
            if (x == PlayModeStateChange.EnteredPlayMode)
            {
                var asm = typeof(Editor).Assembly;
                var type = asm.GetType("UnityEditor.GameView");
                EditorWindow gameView = EditorWindow.GetWindow(type);

                // GameViewクラスのSnapZoomプライベートインスタンスメソッドを引数1で呼び出す
                var flag = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;
                type.GetMethod("SnapZoom", flag, null, new System.Type[] { typeof(float) }, null).Invoke(gameView, new object[] { 1 });
            }
        };
    }
}

#endif
このコードをファイルに保存し、どこでもいいので配置します。
(Editorフォルダの中に入れるならば、#ifdef UNITY_EDITORは必要ありません)

そして実行してみると、Unity 2018.1では無事実行するたびにスケールが1に戻ることがわかります。

ただし、リフレクションで公開されてない内部関数にアクセスしてるため、バージョンが違うと動作しなくなることも十分ありえます。

おわり

2018年6月18日月曜日

Unity1week GameJamに参加しました


最近Unity 1週間ゲームジャムに参加しました

完成した作品がこちらです。



ゲームのネタについて

何かを薄く切っていくゲームを考えていたところ
ちょうどこちらのバズっていたとても面白いツイートを見て、題材はパンの薄切りゲームにすることにしました。

使用したアセットについて

Mesh Cut

このゲームで一番大事なメッシュを切り刻むことができるアセットです。
アセットストアにあるものをいくつか見て回ったのですが、どれも$30以上しました。
$30するアセットは、その値段に見合う豊富な機能を持ってることが多く、使い方の学習に多くの時間を取られがちです。
今回はこちらのMIT Licenseのコードを使わせていただくことにしました。
ソースが公開されてるおかげで、改造も可能で助かりました。

Realistic Bread

パンです。$2.69でナイフとまな板がついてきます。

ファンシーハートフォント

とてもかわいいフォントです。これをTextMeshProで使ってます。

効果音

かわせるかしら?などの掛け声も効果音ラボサイトのアセットを使わせていただきました。

音楽

タイトル画面とゲームオーバー時の音楽です。

実装について

パンを切る部分を光らせた


どこがどう切れるのか明示しないと納得感が薄かったので、パンに切られラインを表示しました。
このラインはパンのシェーダーに「シェーダーパラメーターで与えた面との距離を調べて、近いほど光らせる」という処理を入れて実現してます。

もっといい方法はあるはずですが、自分が一番手っ取り早くできそうな方法でやってます。
ゲームジャムですからね。

背景はスカイボックス

パン包丁まな板以外は普通にUnity標準の青空だったのですが、クッキング感を出すために背景をチッキンにすることにしました。
ただ、キッチンのモデルを本当に配置したら、容量、実行速度などに大きな影響がでます。
そこで、テラシュールブログさんの「背景をスカイボックスで表示する」と同じ手法を使いました。

別プロジェクトにキッチンモデルアセットをインポートし、そこでライトを焼き、キューブマップを撮影し、それをパン切りプロジェクトに移行してます。

キューブマップのサイズを256ぐらいにすると、なんか被写界深度っぽくなる上、サイズも大幅削減できました。



容量12MBまで削減

WebGLで実行するものは、やはり容量が少なければ少ないほどサーバーにもユーザーにも優しいはずです。

何が容量を占めているのか、勘で闇雲に作業してはコスパが悪いです。
そこで役に立つのがビルド後レポートツールです。
アセットストアにはそれ系のツールはいくつかありますが、自分はこれを使用してます。

Better Build Info - Report Tool



何が容量を占めているのか?を一覧で見たり、2次元の面積図で見れたりと、一気にわかりやすくなります。

自分のプロジェクトで大きかったファイルは「日中韓すべての文字が入ったフォント」
「パンモデルなどのテクスチャ」が多かったです。

フォントは、漢字などが出ないのはもう切り捨てて、「ふぁんしーはーとフォント」で全部表示するようにし、大きいフォントファイルは削除しました。
ランキングで登録する人も、アルファベットかひらがなカタカナ登録が多いようでしたので。
ゲームジャム作品ですし、ランキングで漢字が使えることより、容量が軽いほうがいいでしょう。

テクスチャは、問題がないレベルまで解像度を下げたり、無駄にアルファを使う設定になってるものはアルファを使わないように設定し直すなどしました。
無駄にアルファを使う設定になってると、圧縮フォーマットの関係でサイズが大きくなることがあります。

なぜ?実際にブラウザで実行したらメモリ不足で落ちちゃう

Editorでは落ちないのですが、クローム上で実際に動かすとパンを数枚切ったところで落ちたり落ちなかったりしてました。

Build時に使用メモリを指定することができるので、それを増やせばいい
というような安易な解決はせず、ちゃんと原因を探りました。

容量12MBまで削減して、メモリにのるアセットも少ないはずなのになぜ落ちるのか?
勘で調べるのは大変なので、もちろんUnity備え付けのプロファイラを使いました。

プロファイラをつけて実行してみると、パンを切った瞬間に60MB以上アロケートされ、即座に開放されてました。

Deep Profileをonにして実行すると、どの関数でメモリを消費してるのかもわかります。
ずばり、MeshCut.Cut関数の中でした。

ソースを読むと

_leftSide.AddTriangle(
 new Vector3[]{ _victim_mesh.vertices[p1], _victim_mesh.vertices[p2], _victim_mesh.vertices[p3] },
 new Vector3[]{ _victim_mesh.normals[p1], _victim_mesh.normals[p2], _victim_mesh.normals[p3] },
 new Vector2[]{ _victim_mesh.uv[p1], _victim_mesh.uv[p2], _victim_mesh.uv[p3] },
 new Vector4[]{ _victim_mesh.tangents[p1], _victim_mesh.tangents[p2], _victim_mesh.tangents[p3] },
 sub);

というコードがありました。

_victim_meshはUnityのMeshクラスです。
Meshクラスのverticesプロパティは、その見た目の印象と違い、内部の配列に直接アクセスしてるわけではなく、コピーした配列を作って返します。
そのため、「_victim_mesh.vertices[p1], _victim_mesh.vertices[p2], _victim_mesh.vertices[p3]」の部分だけでも3回配列がコピーされて即座に捨てられるということになっています。

悪いことにこれがfor文の中にあったので、メッシュ自体は数キロバイトでも、そのコピーが1フレーム中に1000回近く生成されていました。

そこで
            var mesh_vertices = _victim_mesh.vertices;
            var mesh_normals = _victim_mesh.normals;
            var mesh_uv = _victim_mesh.uv;
            var mesh_tangents = _victim_mesh.tangents;
というように、for文の外で変数に配列を代入して、mesh_verticesを使うよう置き換えました。
これだけでほとんど切った際にメモリを使わなくなりました。
MeshCutがオープンソースでありがたいところでした。

Unityのプロファイラはとても簡単で便利なので、それもとても助かりました。

最後に

今回は結構苦労することもなくサックり作れたのが良かったです。
こういうイベントに参加するのはいろいろと楽しいので、都合がよかったらまた出てみたいと思います。

2018年5月30日水曜日

クロンとゼリーをiOSとAndroidで公開いたしました




クロンとゼリーというスマホゲームをリリースいたしました。

かわいいクロンというなの猫の主人公がゼリーを吸いまくる
異色カワイイアクションパズルゲームです。

ネコが水に落ちないギリギリまでゼリーを吸いつくすのを競います。

簡単なルールでどなたでも遊べます。

縦画面、横画面でもプレイ可能です。

綺麗なグラフィック、着せ替え要素、オンライン対戦バトル、写真フィルタ機能など
色々な楽しさを詰め込んでいます。

基本無料ですのでお気軽にお試しください。





Get it on Google Play