読者です 読者をやめる 読者になる 読者になる

太郎Work

Unityとかで困ったこと等を残しておきます

Unityステンシルでポストエフェクト

前回の記事ではステンシル情報を用いてアウトラインを表現しましたが、
せっかくステンシル情報を書き込んだのでポストエフェクトにも応用してみました

f:id:tarowork:20140803012110p:plain
キャラクターだけモザイク処理

f:id:tarowork:20140803012144p:plain
ステージのみモノクロ

Terrainの草にシェーダを指定する方法が分からなかったのでその部分にステンシルをかけられませんでした。

WebPlayer版
右側にあるボタンでモザイク、モノクロ、通常と前回の記事のアウトラインが切り替えられます。
Stencil Test

続きを読む

Unityでステンシルを用いたアウトライン表現

f:id:tarowork:20140725005608p:plain
最終的にこんな感じになります。
WebPlayer版 Windowsで見ると表示がおかしい可能性があります
Stencil Test

はじめに

なぜ急にアウトラインかというときっかけは白猫プロジェクトでした。
遊んでいて真っ先に気になったのがタイトルにもあるキャラクターのアウトライン表現でした。
f:id:tarowork:20140724004610p:plain
プレイ画面のキャプチャ

続きを読む

NGUIではないオブジェクトをNGUIの手前に描画するスクリプト作ってみた

以前の投稿で

NGUIではないオブジェクトをNGUIの手前に描画する方法 - 太郎Work

このような記事を書きましたが、ParticleSystemやメッシュを手前に持ってきたい場合や任意の場所に挟みたい場合は非常にめんどうでした。

やはりNGUIのdepthで管理したくなったのでコンポーネントを作成しました。

注意!:NGUI3.x用です
tarob19/UIUnityRenderer · GitHub

実行例

後ろからdepth0, depth2, depth4で指定したUITextureにParticleSystemを入れた場合の実行結果です
直感的に任意のレイヤーにParticleが表示できているのがわかると思います。
コンポーネントに最終的なRenderQueueの確認もできるようにしました。
もちろんNGUIのDrawCallToolでも見られます。

f:id:tarowork:20140608214334p:plain
depth = -1 一番裏側

f:id:tarowork:20140608214438p:plain
depth = 1

f:id:tarowork:20140608214505p:plain
depth = 3

f:id:tarowork:20140608214532p:plain
depth = 5 最前面

ParticleSystemと同じGameObjectにアタッチしてUIPanel以下に入れるとUIWidgetのdepthで管理できるようになります。
使いたい方はどうぞ。ただし使ったことによる責任は一切負えません

以下詳細

GetComponentでRendererを取得してNGUIにWidgetとして登録しています。

OnFillで画面外にダミーのメッシュ情報をセットしておくことで、かならず1drawCall発生するようにしています。
ただし、画面外に描画されるためUnityの方でカリングされるので無駄なDrawCallは発生せずRendererのDrawCallのみなのでご安心下さい。

depthを操作するとUIDrawCallが書き換わるのでその値をコピーしたMaterialにセットしています。

しかし、デフォルトではこれは実行時のみ適用するようにしています。
これは、SharedMaterialを書き換えるとProjectのマテリアル情報が随時書き換わるためバージョン管理をしている場合UIPanelを操作する度に変更点として上がってしまうためです。

そんなことは気にしないor実行前に確認したいという方はUseSharedMaterialにチェックを入れるとRendererのマテリアルを直接操作するようになります。

とりあえず複数マテリアルに対応しましたが本当に動くかは分かりません。
UIWidgetのmPlayModeがうまく取れなかったので毎フレームチェックになってしまいました。。。

試行錯誤で結構苦労したけど最終的に良い感じになってよかった。

WWWクラスでBASIC認証

WWWを用いてBasic認証をする場合少しつまずいたのでメモ
https://docs.unity3d.com/Documentation/ScriptReference/WWWForm-headers.html

ここにまさにBasic認証の方法が書かれているがこのまま書くとPOSTリクエストになってしまう
GETでリクエストを送る場合はWWWの第2引数のbyte[]をnullに指定すればOK

いくらなんでも低機能すぎるだろう…WWWクラス

ノイズエフェクト作ってみた

とある理由で思い立ったので勉強も兼ねてモニターノイズ風エフェクトを実装してみました

f:id:tarowork:20140428011714p:plain
https://googledrive.com/host/0BzRQHdfTLNehbVRHaF9DVElDYzA/NoiseWeb.html

手順
RenderTextureなのでPro必須

まずはユニティちゃんに登場してもらいます
f:id:tarowork:20140426231718p:plain

  • OnRenderImageでEdgeDetectを処理

Unityの用意しているEdgeDetectShaderに実装されているものから3D空間向けに
TriangleDepthNormals、画像系向けにTriangleLuminanceのfragmentシェーダをベースにして背景と線画の色を切り替えられるシェーダを実装

f:id:tarowork:20140426235633p:plain
この後更にエフェクトをかけるので黒に白線画で描画

  • Mathf.PerlinNoiseで生成した画像を用いて一部水平領域を除去

f:id:tarowork:20140427023158p:plain

  • Blurエフェクトをカスタマイズしたシェーダを実行する

f:id:tarowork:20140427023519p:plain
これにより横にこすった感じになる

  • 出来上がったピクセル移動量を定義したテクスチャを用いて元画像に適用

f:id:tarowork:20140427023745p:plain

  • 上部を横にスライドさせるシェーダ適用、ついでにUnityのノイズエフェクト

f:id:tarowork:20140428001424p:plain

特に調べたりせずにイメージでノイズっぽいものを作ってみましたが案外それっぽく見える?
何か動画を参考にしながら作ればもっといい感じになったかも

作ってて思ったけど線画抽出はあまり意味がなかった。
Texture全体に処理をかけているのでPostProcess負荷は結構あがってしまいました。モバイルでは無理かな?

作っている間にいろいろとシェーダの勉強ができたのでやってよかったと思う。
シェーダ面白い

PlayerSettingsのアイコンをEditorから変える

dev版とrelease版で切り替えるEditorを作っていたのですが、アイコンも変えようと思ったら簡単に変えられたのでメモ

var icons = PlayerSettings.GetIconsForTargetGroup (BuildTargetGroup.Unknown);
if (icons != null && icons.Length > 0) {
    player.icon = icons [0];
}

if (player.icon != null) {
    PlayerSettings.SetIconsForTargetGroup (BuildTargetGroup.Unknown, new Texture2D[]{ player.icon });
}

ScriptableObjectのクラスで値を書き換えてAssetDatabase.SaveAssetsで保存しています。
Texture参照を保存できるので便利です。

UnityiOSのdevelopment build の場合スプラッシュスクリーンで止まる

UnityのiOS書き出しの際development buildにチェックを入れて出力すると
スプラッシュスクリーン表示中に停止してしまう問題が有り、解決に時間がかかったのでメモ

XCodeのLogを確認すると別スレッドからアクセス出来ない的な文章が出ているのみで
空のシーンを起動しても変わらず。

結局MonoBehaviourを継承していない普通のクラスのstaticフィールドでUnityのメソッドを呼んでいることが原因だった。

public static readonly Dictionary<eTest, string> dic = new Dictionary<eTest,string>() {
  {eTest.TEST1, Localization.Localize("test1")},
  {eTest.TEST2, Localization.Localize("test2")},
};

初期化時にローカライズのテキストをenumで取得できるようにしたかったがこの記述があるだけで呼んでいなくても停止してしまった。

挙動をまとめました。

non develop develop
Editor 動作 動作
iOS Localizationが初期化されずに動作 スプラッシュスクリーンで停止

Editor上だと何も問題なく動作してしまうため発見が遅れました。

なので必要になった時取得するように変更しました。

private static readonly Dictionary<eTest, string> _dic;
public static Dictionary<eTest,string> dic {
  if(_dic == null) {
    _dic = new Dictionary<eTest,string>() {
      {eTest.TEST1, Localization.Localize("test1")},
      {eTest.TEST2, Localization.Localize("test2")},
    };
  }
  return _dic;
}

Logを出してみるとUnityのAwake等よりも先にUnityでない通常クラスのstaticフィールドのコンストラクタが呼ばれるようです。

Editor上だと再生時にエラーは出ないが一度失敗してからUnityのAwake等のタイミングでまた呼ばれていることが確認できました。

なので、iOSのdevelopmentだと何か挙動が挟まるせいでUnity起動の前にクラスの初期化が呼ばれてるようです。

皆様もiOSのdevelopmentビルドのみ起動出来なくなった場合はこういったコードがどこかに埋まってないか確認してみてください。