«

""


[Unity] 常にカメラの前にSpriteを出す

Unityでカメラに追従して、前面にSpriteを出す方法

これ、本当は、カメラの子供として指定すればもっと簡単なんですけど…

testScript.transform.parent = Camera.main.transform

この場合、
カメラにアニメーションが付いてる時(メインカメラは固定ポジションのままの時)に
うまく乗せられなかったりして、
面倒だなーと思い、Update毎に自分で位置を更新することにしました
(変に親子関係があるのも、後で何か制限されたらやだなーとかとかもあり…)

以下を参考にしたら、簡単にカメラの前に表示するスプライトを簡単に表現できました

public class TestExecutor : MonoBehaviour
{
    private Texture2D blackTexture;
    private SpriteRenderer testSprite;

    void Start()
    {
        // Create black texture
        blackTexture = new Texture2D(32, 32, TextureFormat.RGB24, false);
        blackTexture.SetPixel(0, 0, Color.white);
        blackTexture.Apply();

        // Create Sprite
        var sprite = Sprite.Create(
          texture: blackTexture,
          rect: new Rect(0, 0, blackTexture.width, blackTexture.height),
          pivot: new Vector2(0.5f, 0.5f)
        );

        // スクリプトからSprite生成
        testSprite = new GameObject("TestSprite").AddComponent<SpriteRenderer>();
        testSprite.sprite = sprite;
    }

    void Update()
    {
        var distance = 10f;

        // カメラの前に置く距離に応じて、ワールド座標でのスクリーンサイズを求める
        // (distance +1f) の意味は、スクリーンサイズよりちょい大きめで画面を覆いたいから
        var worldScreenH = 2.0f * (distance + 1f) * Mathf.Tan(Camera.main.fieldOfView * 0.5f * Mathf.Deg2Rad);
        var worldScreenW = worldScreenH * Camera.main.aspect;

        // Spriteのサイズを調整
        testSprite.transform.localScale = new Vector3(worldScreenW / testSprite.sprite.bounds.size.x, worldScreenH / testSprite.sprite.bounds.size.y);

        // カメラの角度と位置をコピー、前に置くだけならforwardベクトルが便利
        testSprite.transform.position = Camera.main.transform.position + testSprite.transform.forward.normalized * distance;
        testSprite.transform.rotation = Camera.main.transform.rotation;
        
        // フェードとかさせたいなら、ここでαを調整
        testSprite.color = new Color(0, 0, 0, fadingAlpha);
    }
}

Gist - Unity Sprite on front of camera

こんな感じで、Spriteがカメラにくっついてきてくれます

忘れそうな自分へのメモ


[Unity] Unity用YEBISプラグインのお話してきました

たまには、仕事のお話を…
現在、Unityのプラグインを絶賛開発中で、わたしも少し関わらせて頂いてます

なんのプラグインかというと、ポストエフェクト処理がかけられる「YEBIS」というプロダクトのプラグイン化になります

今、ベータ版として期間限定のトライアルを出し中。。

あぁ、なんでUnityのアセットストアじゃないのかって…?

実は、「特濃!ゲーム開発塾5」というイベントでこのプラグインの話をしてきたのですが、ストアの申請が間に合わず…><
とりあえず、GitHub Pagesに置いてます
(なので、アセットストアに公開するまでの、期間限定サイトです)

ちなみに、イベントURLはこれ

岩手県盛岡市はIT支援がとても盛んらしく、こんなゲーム開発者向けのお祭りイベントがあるんですね~

わたしが参加した日程は 8月9日(火)
対象となる人はプログラマー、もしくはプログラムを将来仕事にしたい人向け
現在、DMM.comラボにてプロデューサをされている松本卓也さんがメイン講師をされました

わたしは30分ほどセッション時間を頂き、このUnityプラグインのお話をさせて頂きました
発表に利用した資料はこれです

ベータ版なので動作不安定な点がいくつもあるのですが、人柱的に試しても良いかなーという心優しい方は、トライしてみてくださいm(__)m

ちなみにドキュメントはこちら

トップは英語で書かれてますが、実は日本語のドキュメントしか今は無いです


[Unity] PC実行時のWindowsサイズの設定の仕方&起動時フック

Unityのバグなのか、わたしの使い方が悪いのか?
PC実行時のウィンドウサイズの設定が、思うようにできなかったので
その解決メモです

PCで実行したら全画面…

Unityのプロジェクトファイルを新規作成して

“File” → “Build & Run”

を選択すると、ビルドが走り、実際に exe が実行されます

へぇ、画面解像度( Screen resolution )とか、ここで変えることが出来るんだ~
と思って解像度設定を変更し、”Play!” で起動させると、いちおう思ったサイズで起動することが出来ます

Unityプロジェクトに Plyaer Settings がある

ユーザに毎回ウィンドウサイズを選択させるのも、なんだかねぇ…ということで、ちゃんと設定したいと思います

Unityのメニューの

“File” → “Build Settings”

Build Settings を選択すると、ビルドに関する設定が変更できるようです
下にある、”Player Settings” を選択すると、 インスペクタウィンドウが出ます

ここで、起動時の Player Settings が出来るようですが…

「Resolution」 の 「Default Is Full Screen」 のチェックボックスを外しましょう
ついでに、「Standalone Player Options」 の 「Display Resolution Dialog」 を 「Disable」 にしておきます

これで exe を実行するたびに 「FixSizeWindows Configuration」 は開かなくなります

「Resolution」 には、「Default Screen Width/Height」 がありますが、、、
ここで設定を変えても、ウィンドウサイズは変わりません
(なんでやねん…><)

どうやら、「前回起動したときのウィンドウサイズ」で起動するみたいです…
Development Build にしても、しなくても、結果は一緒でした
初期起動のサイズは、ここじゃないのかな…(´・ω・`)

余談ですが、ここで変えた設定は、

の中に、テキストファイルで保存されます

ウィンドウサイズはプログラムで変更

仕方がないので、スクリプトで記載します

Unityのメニュー Assets > Create > C# Script で新規スクリプトを作ります

わたしは適当に GameInitial と名付けました(Unity の Project 内に、GameInitial の C#ファイルが追加されます)

いーっちばん最初のゲーム起動時をフックしたい?

もちろん、ウィンドウサイズを変更したいためです
解像度が小さい/大きいなど
起動したときに、クライアント端末によってウィンドウサイズを変えたいとかあると思います

たぶん、現状の Unity 5.3系の最速フック方法は、RuntimeInitializeOnLoadMethod ではないかと…

ユーザがアクションを起こす前に動くらしいですが
実際やってみると、ロゴ起動画面の方が先に動くので
ほんとの意味の一番最初のウィンドウサイズは、ここでは遅いみたいです

一応サンプルコード
MonoBehaviour は無くても動くみたいです
あと、オブジェクトなどにスクリプトをアタッチしなくてもOKです

using UnityEngine;

public class GameInitial //: MonoBehaviour
{
    [RuntimeInitializeOnLoadMethod]
    static void OnRuntimeMethodLoad()
    {
        Screen.SetResolution( 640, 960, false, 60);

    }

    //// Use this for initialization
    //void Start()
    //{

    //}

    //// Update is called once per frame
    //void Update()
    //{

    //}
}

自分が知らないだけかもしれませんが、 RuntimeInitializeOnLoadMethodAttribute より早い時点で自分の処理を差し込むことは出来ないみたい…

ウィンドウサイズを指定できるコマンドライン引数がある!

結局、起動時のウィンドウサイズは結局どこで更新するんでしょうか…?

実は、飛び道具的ですが、exe の引数に渡せるみたいです…!(そこか…><

自分で作った exe の引数に

を渡してあげればOKでした

> xxx.exe -screen-width 300 -screen-height 300

小さいスクリーンサイズで起動したのちに…

自分の指定した Screen.SetResolution サイズで起動

つまり、引数に自分で好きな数値を渡せるようになってるので
それと、Screen.SetResolution の指定を同じ大きさにしておけば
最初から自分自身でサイズを調整できますね

なんだろなー
なんで起動時のサイズくらい、すんなり設定できないんでしょうか…謎や~

もしかしたら、無料版では起動時のロゴを外せないようにするために、プログラマは触れないようになってるのかなー?

ともあれ、意図したことは出来るようになっているので、まぁ良しとします!


[Unity] 2D Spriteにシェーダーをかける

今年の初めに、「Game a Week」という開発手法がすごい!っと書きました
とりあえず、週に一度は成果物を公開する、の部分を真似してみようかなと
(やってみて気が付きましたが、実は1週間って、結構長いです)

今をトキメクGame Engine: Unity について、去年から触る機会があり、ポチポチとやっております

そしてこれは既知の情報ですが、先週は2Dスプライトにシンプルなグラデーションのシェーダーを適用してみました

やってみると判るのですが、Unity ではスプライトにシンプルシェーダーだけを適用しようと思っても出来なくて、
先に結論を書いておくと、スプライトとして扱う場合は必ず何かしらのテクスチャアセットが必要でした
そのメモと感想文になります

2016年1月11日現在、Unityのバージョンは 5.3.1 です

Unity のシェーダー言語:ShaderLab

Unity のシェーダーは 「ShaderLab」 という Unity オリジナルのシェーダー言語で記載することになります
といっても HLSL のラッパーのような言語なので、Unity で使うときのお作法であり、Unity と シェーダーの仲介役の言語、と思って良いみたい

最小限の ShaderLab

最小限の ShaderLab の枠組みはこんな感じ
(これより削ると、エラーが出た)

// BG_shader.shader
// 最小限の ShaderLab
Shader "Custom/BG_shader" {
    SubShader
    {
        Pass {}
    }
}

実際に、このカスタムシェーダーをマテリアルに適用するとこんな感じ

何もしないマテリアルを作ることが出来ました

シンプルなグラデーション

今回、ゲーム背景を単純なカラーグラデーションにしようと思ったので、そういうシンプルシェーダーを書いていきます

// BG_shader.shader
// 黄色くグラデーションする
Shader "Custom/BG_shader" {
    SubShader
    {
        Pass{
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            // VS2015のグラフィックデバックON
            #pragma enable_d3d11_debug_symbols

            struct VertexInput {
                float4 pos:  POSITION;    // 3D空間座標
                float2 uv:   TEXCOORD0;   // テクスチャ座標
            };

            struct VertexOutput {
                float4 v:    SV_POSITION; // 2D座標
                float2 uv:   TEXCOORD0;   // テクスチャ座標
            };

            // 頂点 shader
            VertexOutput vert(VertexInput input)
            {
                VertexOutput output;
                output.v = mul(UNITY_MATRIX_MVP, input.pos);
                output.uv = input.uv;

                return output;
            }

            // ピクセル shader
            fixed4 frag( VertexOutput output) : SV_Target
            {
                float2 tex = output.uv;
                // 黄色→白色のグラデーション
                return fixed4( 1.0, 1.0, 1.0 - tex.y, 1.0);
            }

            ENDCG
        }
    }
}

ちょっとマテリアルではわかりにくいですけど、一応、線形にグラデーションされています

2D Sprite に適用する方法

シンプルなシェーダーとマテリアルが出来たので、実際に、Sprite に登録します

Sprite と Material だけでは足りない

ただし、ちょっとここでクセがあって、このマテリアルを Sprite にアタッチしても、何も起こりません
それどころか、ワーニングメッセージが…

Material does not have a _MainTex texture property. It is required for SpriteRenderer.

あら…
Sprite Renderer に登録するマテリアルには、テクスチャが必要ということみたいです
シェーダーに戻って、言われているとおり、 _MainTex にテクスチャを登録します

// BG_shader.shader の Properties を追加
    Properties
    {
        _MainTex( "2D Texture", 2D ) = "white" {}
    }

テクスチャを登録できるし、デフォルトでは white テクスチャを使いますよ。という意味になります
ちなみに、_MainTex() の内蔵テクスチャには

の4種類が用意されています
* ShaderLab: Properties - Unity Documentation
http://docs.unity3d.com/Manual/SL-Properties.html

マテリアルにテクスチャを持つ設定にしました

Sprite には、ベースとしてリアルな Texture が必要

Sprite のワーニングも消えたのですが、やはりシーンに Sprite object が表示されません

どうやら、Sprite はあくまで、テクスチャ画像を表示させるための機能に特化しており、マテリアルだけでは動作しない様です

仕方がないので、Sprite 用のテクスチャを用意します
サイズ感がよくわからなかったのですが、 white.jpg という 8*8 のテクスチャを Assets の下に入れました

Sprite の Inspector にて、Sprite Rendere > Sprite にて white テクスチャを選択します

あぁ…これ、デフォルトで白いテクスチャくらい、システムで用意してほしいなかと思いましたが、まぁしょーがないです

でたー

まとめ

シンプルな 3D model では

という構造なので、

2D Sprite では

なのかなーと思っていたのですが、実際には

という構造が必要でした

これを受けて、

「え、シンプルなシェーダーのみを適用したいなら、
Sprite でなくて 3D Plane Model にしたらいいんでない?」

という疑問が出てきましたが、
実際のゲーム制作においては、シチュエーション依存ですかね…
今回のわたしの場合は、Sprite を採用しました

この記事の Unity プロジェクト(ソース、アセット)を Github に置いておきます
https://github.com/h-sao/UnitySampleCode/tree/master/SpriteGradationalShader

何かの参考になれば幸いです