Nanashi-soft

Nanashi-softの活動状況とか雑談です。 Unity3Dでゲーム作っています。

SpriteAtlasは,透過付きスプライト画像を,指定サイズのテクスチャにまとめるUnity標準機能です
使用しているスプライトだけを,後から1枚にまとめたりできるので便利です

○インストール方法
UnityメニューのWindow→Package Managerを開く
『2D Sprite』がインストールされていれば使用可能

無い場合は,
左上の2つ目のプルダウンをAll packagesにする
2D Spriteを選択して,右下のInstallボタンをクリック

ちなみに私はこの2D Sprite以外の2D~は一つも入れていません

○生成方法
UnityのProjectウィンドウの左上の+をクリックして,Sprite Atlasを生成
できたNew Sprite Atlasファイルは,Resourcesフォルダの下に置く(※Resources.Loadを使用する場合)

Type:Master
Include in Build:オン
Packing
Allow Rotation:オフ(*)
Tight Packing:オフ(*)
Padding:4(*)
Texture
Read/Write Enabled:オフ
Generate Mip Maps:オフ (必要ならオンにする)
sRGB:オン (元画像による)
Filter Mode:Bilinear (等倍表示のみの時はPoint)
(*)を付けている場所は不具合の少ない推奨値で,後で各自変更して検証すること

Max Texture Size:詰め込みたいテクスチャのサイズ
Format:Automatic
Compression:Normal Quality
Use Crunch Compress:オフ (ビルド時にCompression MethodにLZ4を設定した方が良いと思う)

Object for Packingの所に,格納したいスプライトファイルをドロップする
フォルダ毎セットする事も可能なので,それを利用した方が便利

Pack Previewボタンをクリックすると生成されて,下に表示される
表示されない場合は設定がおかしいか,スプライトでは無くテクスチャをドロップしてしまっている場合が多かった

○注意点
・同一のスプライト名があった場合衝突する
 別名に変更するか,別のSpriteAtlasファイルに格納するしかない
 Sprite EditorでSliceしたNameとも衝突します
・透過付きスプライト画像しか入らない
 透過無しの場合も自動的に透過ありに変換されて,他の画像と一緒にパッキングされます
 当然透過無しの方が省メモリですが,1枚テクスチャ化した方がバッチング回数は減るので,設計上悩ましい選択に迫られます
・Padding(余白)を考慮する必要がある
 例えば,1024x1024サイズのSpriteAtlasファイルには,1024x1024のスプライト画像は入りません
 上下左右の余白分を引いたサイズにカットして置くか,2048x2048サイズのSpriteAtlasファイルにする必要があります
・スプライト画像しか入りません
 UIにテクスチャで使用している場合は,スプライトに変更すれば良いでしょう
 Raw Imageを使用している場合は,Imageに変更する
 テクスチャ画像を以下のスプライト画像に設定を変更する
Texture Type:Sprite (2D and UI)
Sprite Mode:Single
Pixcels Per Unit:100 (*)
Mesh Type:Tight
Extrude Edges:1 (*)
Pivot:Center (好みの中心位置で)
Generate Physics Shape:オフ
移行は元の設定のまま継承で良い
右下のApplyボタンをクリックして設定完了
・モバイル機は4096x4096までの機種が多い
対応機種によっては2048x2048にする必要があるかもしれません
フォーマットはASTCが推奨ですが,これも対応機種によります

○プログラムで表示する
//ソースの先頭に宣言が必要
using UnityEngine.U2D; //SpriteAtlasに必要

//SpriteAtlasからスプライトをロードする
try{
  //SpriteAtlasファイルのリソースパスが,~/Resources/spriteatlas/systemだとする
  SpriteAtlas workatlas=Resources.Load<SpriteAtlas>("spriteatlas/system");

  //スプライト名がmap_bgだとする
  //通常はファイル名で,スライスしていたらそこで付けたnameです
  Sprite sprite=workatlas.GetSprite("map_bg");

  //シーン上のUI > Imageオブジェクト名がhyoujiだとする
  GameObject workobj=GameObject.Find("hyouji");
  Image workimage=workobj.GetComponent<Image>();
  workimage.sprite=sprite;

  //シーン上の2D Object > Spriteオブジェクト名がbyougaだとする
  GameObject workobj2=GameObject.Find("byouga");
  SpriteRenderer worksprite2=workobj2.GetComponent<SpriteRenderer>();
  worksprite2.sprite=sprite;

  //CanvasにImageコンポーネントを追加して直接描画とかも可能
  //スプライトが表示可能な場所にはどこにでもロード可能なはずです
  //ただし,RawImageには入りませんので注意のこと

}catch(System.Exception e){
  Debug.LogError(e);
}

このエントリーをはてなブックマークに追加

GDOCはカメラに設定するだけで,GPUを使用したリアルタイムにカリング処理をしてくれるアセットです
私が使ってみて,問題点と,その回避方法を忘れないようにメモしておこう。という記事です

○GDOCアセット
GDOC — Dynamic GPU Occlusion Culling
https://assetstore.unity.com/packages/tools/utilities/gdoc-dynamic-gpu-occlusion-culling-139079

○メリット
ただカメラにスクリプトをくっつけるだけで使える点
リアルタイム処理なので,Bakeしなくて良い点

○デメリット
まだ Win64bitの D3D11にしか対応していない点

○セットアップ方法
シーン上のMainCameraオブジェクトをクリック
CameraのOcclusion Cullingのチェックを外す
Bearroll/GDOC/Scripts/GDOC/GDOCを,カメラのInspectorに追加する

※using Bearroll;でパスが見つからないエラーが出た場合
一度Unityを終了させてから,エクスプローラでStandard Assetsフォルダに移動する
プロジェクトフォルダ/Assets/Bearroll/GDOC/
↓移動する
プロジェクトフォルダ/Assets/Standard Assets/Bearroll/GDOC/

○カリング対象にしたいオブジェクトをレイヤー分けする
デフォルトでは,オブジェクト全てが対象になっています
そうすると,地面も対象になる為,上に乗っているキャラが落下してしまいます
レイヤー毎に動作分けをする仕組みがある為,それを使います

・レイヤーを追加
メニューのEdit→Project Settings...を選択
左の Tags and Layersをクリック
User Layer XXの適当な所に『Additional props』を追加する(名称は何でも良いです)

・GDOCの設定
カメラにセットしたGDOCの,Object managementの Layers (management)の左の三角をクリックして開く
0:Defaultを Noneにする
XX:Additional propsを Fullにする

・カリング対象にする
オブジェクトをクリックして,Inspectorの右上のLayerプルダウンを Additional propsにする

実行してみて,具合が悪い場合は Defaultに戻せばよいです

●FAQ
○カメラ(プレイヤ)の周囲で,常に表示する範囲を設定したい
Generalにある Player objectに,中心とするオブジェクトを設定する
Minimum distanceに表示したいマス目を設定する

○起動時に非アクティブだったオブジェクトが処理対象にならない
Object managementの Object→Disabled objectsにチェックを入れれば処理対象になる

○非アクティブにしておいたオブジェクトが勝手にアクティブになる
この問題があったので,上のレイヤー分け方法をする
要するにこのアセットは,アクティブのチェックをオン/オフする仕組みの為,このような問題が発生する

×子オブジェクトのみを処理対象から外したい
子も全部処理対象でなければ親も正しく動作しないらしい
いまのところ,対処方法は思い付いていない

親をDefaultレイヤ,子をAdditional propsレイヤに設定して,子のみを処理対象にする事はできる

このエントリーをはてなブックマークに追加

チャット欄の修正
新システムでは,デフォルトで人工無脳チャットが付いています
インプットボックスに文字を入力しても動作しなくなっていたので,それを修正しました
入力欄のところは,TextMesh Proのサンプルそのままコピペです('-'*)

まだ話すキャラが固定されている仮実装レベルのものなので,実際に使用する際には手直しが必要です

このエントリーをはてなブックマークに追加

凄い久しぶりにブログ投稿
本格的にゲーム製作を始める事にしたいので,製作中の様子を晒していこうと思います
完成記事まで続きます('-'*)
目標はシステム・ゴールデン・クローバーの複数エリア版の完成

今は,新システム製作途中で,動作しなくなってしまったUI部分を修正中です
メニュー周りとかも全然動かなくなってしまっていたので……
ついでにスプライト化して,ゲーム毎に差し替えを容易にしようと試行錯誤ちゅう
メニューを作り直している



このエントリーをはてなブックマークに追加

うちで制作しているゲームには,背景全般に Unity標準シェーダー,キャラ全般にこの人形シェーダーを使用しています
Unity2018でプロジェクトを開くと,この人形シェーダーの一行にエラーが出てしまい。動作しなくなっていることがわかりました
たった一行の問題なので,なんとか自力で修正できないものか? という話です

エラーが出るのは,NINGYOU_INC.cgincファイルの,以下の行です
float attenuation = saturate(LIGHT_ATTENUATION( i ));

この LIGHT_ATTENUATIONマクロが削除されてしまったことが原因です
マクロならそのまま残しとけやボヶェと思うのは私だけでしょうか?(´・ω・`)
しかもUnityCG.cgincのマニュアルがありません。説明しろやボ(ry

海外掲示板を見ると,UNITY_LIGHT_ATTENUATIONになったらしい事がわかります
ただし,引数が異なり,第三引数がわかりません
UNITY_LIGHT_ATTENUATION(attenuation, i, 『ここに書く内容がわからない』);

マニュアルも無いので,世界中のシェーダーソースを手当たり次第に眺めていくと言う,自前ディープラーニングをした結果
頂点シェーダーからワールド座標のベクトルを引き回して来て突っ込まばいいのだろうという結論に至りました(合っているかどうかは不明。なにせマニュアルが無いので)

恐らく vert内にある,worldPosが演算内容的にそうだろうと予想
この内容を引き回す為に,struct v2fに変数を追加します
なぜか2つあるのですが,
・上側
float3 worldPosition : TEXCOORD6; //Unity2018対応
・下側
float3 worldPosition : TEXCOORD8; //Unity2018対応(未検証)
をそれぞれ追記します。この下側は未検証です

で,vertメソッド内に
o.worldPosition = worldPos; //Unity2018対応
を追記します

最後に,この引き回した値を使って,LIGHT_ATTENUATIONをUNITY_LIGHT_ATTENUATIONに置き換えます
// float attenuation = saturate(LIGHT_ATTENUATION( i )); //Unity2018対応
UNITY_LIGHT_ATTENUATION(attenuation, i, i.worldPosition); //Unity2018対応
attenuation=saturate(attenuation); //Unity2018対応

これで一応Unity2018.1で動作を確認しました(他にも色々問題があって2017.4に戻しましたが)


●NINGYOU_INC.cginc変更箇所まとめ
変更する箇所の前後数行を書いていきます
//Unity2018対応 とある行を修正して下さい

・構造体変更箇所
#ifndef BUMP_SET
struct v2f
{
~~省略~~
float3 lightDir : TEXCOORD5;
float3 worldPosition : TEXCOORD6; //Unity2018対応
};
#else
sampler2D _BumpMap;
struct v2f
{
~~省略~~
float3 binormal : TEXCOORD7;
float3 worldPosition : TEXCOORD8; //Unity2018対応(未検証)
};
#endif

・頂点シェーダー変更箇所
#ifndef BUMP_SET
v2f vert( appdata_base v )
#else
v2f vert( appdata_tan v )
#endif
{
~~省略~~
float4 worldPos =  mul( unity_ObjectToWorld, v.vertex );
o.eyeDir = normalize( _WorldSpaceCameraPos - worldPos );
o.lightDir = WorldSpaceLightDir( v.vertex );

o.worldPosition = worldPos; //Unity2018対応

・フラグメントシェーダー変更箇所
float4 frag( v2f i ) : COLOR
{
~~省略~~
float3 shadowColor = _ShadowColor.rgb * texcol2.rgb;
// float attenuation = saturate(LIGHT_ATTENUATION( i )); //Unity2018対応
UNITY_LIGHT_ATTENUATION(attenuation, i, i.worldPosition); //Unity2018対応
attenuation=saturate(attenuation); //Unity2018対応
float sint = pow(saturate(dot(reflect(-ltDir, n), i.eyeDir)), _Sharpness);

このエントリーをはてなブックマークに追加

↑このページのトップヘ