- 投稿日:2019-04-17T23:51:34+09:00
UnityでImageを設定しても画像が表示されない時の対処法
こんにちは、ブログ「学生ブロックチェーンエンジニアのブログ」を運営しているアカネヤ(@ToshioAkaneya)です。
UnityでImageを設定しても画像が表示されない時の対処法
「Color」を選択して、「A(透過率)」の値を255にして下さい。
もしも、上のようにAの値が0のままImageを設定しても画像が表示されないので注意してください。はてなブックマーク・Pocketはこちらから
- 投稿日:2019-04-17T22:39:12+09:00
Unityの Visual Effect Graph (VFXGraph) で遊べるようになるまでの備忘録(2019.1.0f2)
Unityの Visual Effect Graph (VFXGraph) で遊べるようになるまでの備忘録(2019.1.0f2)
GPUパーティクルを使うことで、膨大な表示が出来る強力な機能です。
2019.1.0f2 です。
自分がいじれる状況になるまでにやったすべてのことを記載します。注
この記事に書いてることですが、プロジェクトの新規作成時の設定次第で半分くらいとばせます。
そちらについては
Unity の Visual Effect Graph (VFXGraph) を弄れるようになるまでの備忘録(別バージョン)
に記載しました(2018.3.7f1 のものですが)
合わせてご確認お願いします。
ただこちらの記事の方が、普通と何が違うのかわかるのでいい気がします① カラースペースをリニアにする
② Render Pipeline HD と Visual Effect Graph を Import する
少し待つと表示が増える。
③ Pipeline Asset を作って設定する
デフォルトで「New HDRenderPipelineAsset」というアセットが作成されます
④ ヒエラルキー上に Scene Settings を配置する
⑤ Visual Effect Graph を配置する!
やったー!!!!
あとは
https://youtu.be/uvGX8GPdfTE?t=853
とか見て勉強するだけだー!
わーい!!
- 投稿日:2019-04-17T19:36:17+09:00
Unity、Zバッファとレンダリング順の仕組み
概要
3DCGで透明なオブジェクトを扱う上で抑えておきたいトピックです。
レンダリングの基礎。透明なメッシュのレンダリング順
このシーンは 赤・青・透明 の3種類のメッシュで構成されています。
しかし、透明なメッシュを青いメッシュより手前に描画しているにもかかわらず、透明なメッシュの後ろに青いメッシュが描画されてません。何故でしょうか?CGで奥行きを認識する仕組み
CGでは、オブジェクトの奥行きに関する位置をZバッファ(または深度バッファ)という方法で管理しています。
これはオブジェクトをレンダリングした時に、レンダリング結果とは別にオブジェクトの位置(深度情報)も保存しておきます。
再びスクリーンの同じ個所をレンダリングする時、今からレンダリングするオブジェクトと、前にレンダリングしたオブジェクトの深度を比較して、今からレンダリングオブジェクトが奥であるのならレンダリングをスキップします。
この工程をZテスト(または深度テスト)といいます。
この仕組みによって、オブジェクトの前後関係が正しいレンダリング結果を得る事ができます。半透明の場合どうなるか?
Unity道場 2019.2 シェーダを書けるプログラマになろう #1 シェーダを理解しよう
上記動画の15:45~の解説が分かりやすいです。(そこから再生します)端的に言うと…
不透明のオブジェクトしか存在しないの場合、Zブァッファの前後関係を比較すれば絵に矛盾は起きません。
しかし、半透明のオブジェクトが混ざってしまうと…半透明のオブジェクトの奥に、不透明のオブジェクトを描画してほしいのに、Zバッファは不透明のオブジェクトが奥になるので描画されないという事が起こりえるのです。そのため、半透明のオブジェクトと不透明のオブジェクトはそれぞれ分けて管理して、不透明のものを全てレンダリングしてから半透明のものをレンダリングすると順番が決まっており、正しく表示できるわけです。
では、改めて先ほどのプロジェクトを見てみましょう。RenderQueueの値が若い順にレンダリングされるので、
「2000のred → 2001のMegane → 2002のBlue」の順番でレンダリングされることになります。
そのため、青をレンダリングする時に既にMeganeのZバッファがあるので…Meganeの部分だけBlueがレンダリングされずに、透過して見えてしまう。という仕組みなんですね。
これは、Zバッファの学習用にレンダリング順を変更したプロジェクトなわけです。RenderQueue
Materialのレンダリング順に関する定義透明オブジェクトのシェーダー
MakotoNoMegane.ShaderShader "Custom/MakotoNoMegane" { Properties { _LensColor("Color", Color) = (0, 0, 0, 0.1) } SubShader { Tags { "RenderType" = "Opaque" "Queue" = "Geometry+1" } LOD 100 Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" fixed4 _LensColor; struct appdata { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; }; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); return o; } fixed4 frag(v2f i) : SV_Target { return _LensColor; } ENDCG } } }こちらが、透明オブジェクトのShaderです。色が設定できます。
実際にプロジェクトを再現してみて、よりZバッファとレンダリング順の理解を深めるために、自由にお使いください。
- 投稿日:2019-04-17T19:01:55+09:00
CLIでローカルビルドをUnityCloudBuildにアップ
※この記事を書いてる途中(2019/4/17)に ふとググったら去年10月公式に…
それはさておき、2017年12月15日に
Unity Cloud Buildがローカル環境で作ったビルド成果物をアップロードできるようになった
という記事を見かけました。
しかし、WebからじゃなくCLIからアップロードしたいと思い、
きっと誰かが良い記事書いてくれるのでは…と思ってましたが
びっくりするくらい簡単なDeployGate1があるせいか、
はたまた そもそも興味持たれないのか 待てど暮らせど見つからず2
CloudBuildのページあたりを見ていましたらAPIドキュメント発見CloudBuild API Document (v1.0.0時点)
https://build-api.cloud.unity3d.com/よし作ってみるか!
…なるほど、まったくわからん
とまでは行きませんでしたが
ChromeDeveloperで挙動やログを追いかけて なんとか出来ました 3
どれだけの方が利用するかわかりませんが、とりあえず公開前提
- 私の環境: MacOSX10.14.4(iMac4K)
- 成果物は apk / ipa のみしかアップロードチェックしていません
- unity DashBoard にて アプリ名登録まで済んでいるものとします
- bashシェルスクリプトで順番に説明
- json解析にjqを使用
- 置換にgsedを使用
- curl等、色々間違ってたらすいません…
- ですので最低限のみ記載
以下スクショの文字列は例ですので DashBoard眺めてメモってください。
PROJECT_ID(ここではTest)と UPID(ここでは3dc…)をメモ
Testの下の ORG_ID(ここではdeveloper…)をメモ
成果物ファイル名は アスキーコード 0x20〜0x40 辺りを使ってましたら
%20〜%40 に変換してください(URLEncode?)初期設定
API_KEY= #DashBoard - プロジェクト - Develop - Settings - Cloud Build - APIキーに書いてある PROJECT_ID= #DashBoard - プロジェクト名 ORG_ID= #DashBoard - プロジェクト名の下に書いてある UP_ID= #DashBoard - プロジェクト - プロジェクト名の横に書いてあるUPID FILE_NAME= #成果物ファイル名 xxxx.ipa 等をURLEncode EXT= #成果物の拡張子(つまりapkかipa) FILE_SIZE= #成果物のファイルサイズ `wc -c < 成果物ファイル名` とか if [ "${EXT}" = "apk" ]; then PLATFORM=android TYPE_NAME=".APK file" TYPE_NAMEe=".APK%20file" elif [ "${EXT}" = "ipa" ]; then PLATFORM=ios TYPE_NAME=".IPA file" TYPE_NAMEe=".IPA%20file" else exit 1 fi BUILD_API_DOMAIN="https://build-api.cloud.unity3d.com/api/v1" ARTIFACT_API_DOMAIN="https://build-artifact-api.cloud.unity3d.com/api/v1" BUILD_TARGET_ID="_local" LOG=`mktemp --tmpdir=./` function endJob { echo $1 rm ${LOG} }ビルドエリア生成して ビルド番号取得
curl -X POST -H "Content-Type: application/json" -H "Authorization: Basic ${API_KEY}" --data-binary "{\"platform\": \"${PLATFORM}\", \"label\": \"${COMMENT}\"}" ${BUILD_API_DOMAIN}/orgs/${ORG_ID}/projects/${PROJECT_ID}/buildtargets/${BUILD_TARGET_ID}/builds -o ${LOG} -s BUILD_NO=`cat ${LOG} | jq .[0].build` STAT=`cat ${LOG} | jq .[0].buildStatus` if [ "${STAT}" != "\"success\"" ]; then endJob "BuildArea - Error: ${STAT}" exit 1 fiアーティファクト生成
curl -X POST -H "Content-Type: application/json" -H "Authorization: Basic ${API_KEY}" --data-binary "{\"name\":\"${TYPE_NAME}\",\"primary\":true,\"public\":false,\"files\":[{\"filename\":\"${FILE_NAME}\",\"size\":${FILE_SIZE}}]}" ${ARTIFACT_API_DOMAIN}/projects/${UP_ID}/buildtargets/${BUILD_TARGET_ID}/builds/${BUILD_NO}/artifacts -o ${LOG} -s STAT=`cat ${LOG}` if [ "${STAT}" != "Created" ]; then endJob "Generate Artifact - Error: ${STAT}" exit 1 fiアップロード
hc=$( curl -d "" -X POST -H "Upload-Length: ${FILE_SIZE}" -H 'Tus-Resumable: 1.0.0' -H 'Content-Type: application/offset+octet-stream' -H "Authorization: Basic ${API_KEY}" ${ARTIFACT_API_DOMAIN}/projects/${UP_ID}/buildtargets/${BUILD_TARGET_ID}/builds/${BUILD_NO}/artifacts/${TYPE_NAMEe}/upload/${FILE_NAME} -o ${LOG} -w '%{http_code}\n' -s ) if [ $hc != 201 ]; then STAT=`cat ${LOG}` endJob "Upload Post - Error: $hc\n${STAT}" exit 1 fi hc=$( curl -X PATCH -H 'Upload-Offset: 0' -H "Content-Length: ${FILE_SIZE}" -H 'Tus-Resumable: 1.0.0' -H 'Content-Type: application/offset+octet-stream' -H "Authorization: Basic ${API_KEY}" --data-binary @"${1}" ${ARTIFACT_API_DOMAIN}/projects/${UP_ID}/buildtargets/${BUILD_TARGET_ID}/builds/${BUILD_NO}/artifacts/${TYPE_NAMEe}/upload/${FILE_NAME} -o ${LOG} -w '%{http_code}\n' -s) if [ $hc != 204 ]; then STAT=`cat ${LOG}` endJob "Upload Patch - Error: $hc\n${STAT}" exit 1 fiシェアリンク作成
# GET:既に生成済みのShareID取得、POST:ShareID生成、DELETE:ShareID削除 curl -d "" -X POST -H "Content-Type: application/json" -H "Authorization: Basic ${API_KEY}" ${BUILD_API_DOMAIN}/orgs/${ORG_ID}/projects/${PROJECT_ID}/buildtargets/${BUILD_TARGET_ID}/builds/${BUILD_NO}/share -o ${LOG} -s STAT=`cat ${LOG} | jq .shareid | gsed 's/"//g'` if [ "${STAT}" == "null" ]; then cat ${LOG} endJob "ShareLink - failed" exit 1 fi SHARE_URL="https://developer.cloud.unity3d.com/share/${STAT}" #ここらへんで SHARE_URL をチャット等に送る endJob "success"出来上がったSHARE_URLをチャットやメール等に流せばOKかと。
Android・iOSからダウンロード・インストール・実行出来ました。みんな幸せにな〜れ
規約違反とかありましたら記事消します…。
- 投稿日:2019-04-17T15:22:53+09:00
VRMモデル作成についての手順
はじめに
この公式ドキュメントを読むことを強く推奨します。
このスライドは、とりあえずVRMモデルをセットアップしたいという人向けに、纏めたものになっています。 MToonの項目は所々省いているので注意。
できるだけUnity初学者にも分かるように、書いているつもりです。
そもそも私が初学者
エグい長いので右のリンクを上手く使ってください。
※昔書いたサークル向けの記事を移植しています。 最新版は時間があるときに更新します。説明で使用する環境
Unity 2017.4.18
UniVRM 0.48使用できるモデル条件
- Humanoidモデル
- 各種Shapeキーが設定済みであること(表情・口パクを付ける場合)
- 揺らしたい物にボーンが入っている(揺れものがある場合)
- 瞳を動かすボーン、もしくは瞳に上下左右動かすShapeキーがある(視線移動したい場合)
準備
UnityとUniVRMの準備
まずはUnityで空のプロジェクトを作成します。
リリースページからUniVRMをダウンロードしてきます。基本的に最新版で構いません。
一番上のUniVRM-(バージョン).unitypackageをダウンロードしてください。
Assetウインドウで左クリックし、先程ダウンロードしたUniVRMのUnitypackageをインポートします。
インポートするAssetの選択画面が出てくるのですべてチェックを入れimportを押します。
モデル配置
FBXモデルをAssetウインドウにD&Dで読み込ませます。今回は量産型マスキャットのモデルを使用します。
モデルを読み込んだらInspectorウインドウでRig設定をHumanoidに切り替えてApplyを押します。
AssetウインドウからHierarchyウインドウにD&Dでsceneに配置しましょう
Shaderについて
Shaderの設定をします
オブジェクトを選択し、InspectorウインドウからShaderを変更します
VRMではShaderを
- Standard
- VRM/UnlitTexture
- VRM/UnlitCutout
- VRM/UnlitTransparent
- VRM/UnlitTransparentZWrite
- VRM/MToon
の中から選ぶことが強く推奨されています。
今回はこの中からMToonとStandardを使用します。
デフォルトのライトは色がついているので、色を白にしましょう。そのままだと、ライトの色でルックが変わるので変えておきます。
今回はメカ部分をStandard、それ以外をMToonに設定します。
メカ部分は金属っぽさを出すためにStandardを選択しています。
もし、テクスチャに影が書かれている場合はUnlitTextureでも良いと思います。Unlitですのでライトの影響を受けません。
MToonの設定
今回はMToonのみ説明します。StandardやUnlit系のShaderはUnity標準と変わらないので。
Rendering
RenderingType
RenderingTypeは基本的にOpaqueでOKです。
テクスチャに透明部分があればCutoutやTransparentを使用しましょう。TransparentWithZWriteは奥行き情報のある半透明のオブジェクトに使用するといいでしょう
CullMode
CullModeは描画の設定ができます
Off==裏表描画
Front==表を描画しない
Back==裏を描画しない
左からOff、Front、Back
color
Lit Color, Alphaはベースカラーになります。
基本的に白でOK
Shade Colorは影の色です。
自分で調整しながら馴染む色に設定しましょう。大体はピンクの入ったグレーで良いと思います。
Lighting
Shading Shift
Shading Shiftは影をどこから付けるかの調整ができます。
-1は影なし 1はすべて影ありという感じです。
顔等は影が落ちすぎると暗い印象を与えてしまうため少し-値にするのがおすすめ。
左から-1 0 1
分かりやすいように影色を黒にしています。
ShadingToony
ShadingToonyは影の境界線の設定です。
値を上げればパリッとしたセル画調の影の付き方、下げればぼやけた感じになります。
値0(左)値1(右)
Shadow Receive Multiplier
セルフシャドウの設定です。顔等の影があまり落ちてほしくない箇所は0それ以外は1でいいと思います。
LightColor Attenuation
LightColor Attenuationはライトの色の影響度を設定できるパラメーターです。
0が影響を受けて1に設定すると影響を全く受けなくなります。基本的に0でOKです。
変に1にすると、場合によっては周りから浮きます。Emission&Normal Map
Emissionは特に設定しなくて大丈夫です。
簡単に説明すると光源に関係なく一色に塗りつぶす設定です。利用用途はマスクに使うんだと思います。しらんけど。
Normal Mapはその名の通り、あったらここで設定しましょう。Outline
Outlineは特に設定しなくても大丈夫です。その名の通り輪郭線を描写します。
この機能を使えば髪のテクスチャをベタ塗りでも良いかもしれませんね。
- None 輪郭線を描画しません(左)
- WorldCoordinates 世界に対して一定の幅の輪郭線を描画します(真ん中)
- ScreenCoordinates スクリーンに対して一定の幅の輪郭線を描画します(右)
![]()
モデルデータの正規化
Materialの設定が終わったら一旦VRMで書き出します。
Hierarchyでモデルを選択した状態で、ツールバーのUniVRM-(バージョン)からExport humanoidをクリック。
Authorに製作者の名前を入れExportをクリック。export先をAssetのフォルダに指定します。
exportが終わると自動的にPrefabが生成されるので、元々Hierarchyにあったモデルを排除しPrefabをD&Dで配置します。
VRM独自の設定を行う
ライセンス周りを設定していきます。VRMの必要性に関わる大事な部分なので、しっかり設定してください。
少なくとも、タイトル・作者・ライセンス情報は埋めましょう。
注意として、A person who can perform with this avatarの項目をOnly Authorにすると、VirtualCastでは配信しない状態で使えなくなります。
項目は読めばわかると思うので、四角く囲っている部分を埋めていきましょう。
Texture2D部分はサムネイルですので自由に決めてください。
口パク・表情の設定
口パク・表情の設定に入ります。設定しなくても今の段階でVRMファイルとして出力できますが、表情がないです。
設置してあるPrefabを選択し、InspectorのVRM Blend Shape ProxyにあるBlend Shape Avatarをダブルクリックします。
表情の設定
表情を割り当てます。
項目 表情 NEUTRAL 標準 A あ I い U う E え O お BLINK 目をつむる JOY 喜 ANGRY 怒 SORROW 哀 FUN 楽 BLINK_L 左目を閉じる BLINK_R 右目を閉じる ~視線制御がShapeキーの場合に設定~
項目 表情 LOOKUP 上を見る LOOKDOWN 下を見る LOOKLEFT 左を見る LOOKRIGHT 右を見る プルダウンを開くと設定しておいたShapeキーの一覧が表示されます。
それぞれのShapeキーを混ぜて表情を作ることもできます。
Inspectorの下に表情のプレビューがありますので見ながら設定しましょう。
表情の例
独自表情の追加
デフォルトの表情以外の表情を追加するにはAdd BlendShapeClipをクリック。
今回は例でキス顔を追加していきます。
開かれたフォルダ場所で【表情の名前.asset】と名前を編集し保存します。
あとは追加された項目を選択し、表情を作るだけです。簡単。
めっちゃかわいいすき瞳の移動制御
VRMには瞳の追従機能が付いています。瞳が動きすぎないように設定しましょう。
瞳の設定を行うために瞳の追従先を生成します。
Hierarchyで3Dモデルを生成。なんでも良いですが今回はcubeにします。
設置したら手頃な大きさにして顔の前に配置します。
PrefabのInspectorにあるVRM Look At HeadのTargetに、先のcubeをD&Dします。HeadにHeadのボーンを設定します。
Headの位置は、Prefabのプルダウンを開いて、Armature\Hips\Spine\Chest\Neck\Headに大体あると思います。
ゲームを起動(▶を押す)しGameビューからSceneビューに切り替えします。
Targetに設定したオブジェクトを上下左右に動かし、瞳が動きすぎないかを確認。動きすぎたり、動きが少ない場合はVRM Look At Bone Applyerにあるスライダーで値を調整しましょう。
簡単にいうとXの値が動き方、Yの値が移動量です。
みゅみゅ教授曰く、Yは15~23ぐらいがいい。「大げさなぐらいが面白い」
※目の動きの制御をブレンドシェイプで行ってる場合は、VRMLookAtBoneApplyerを排除しVRMLookAtBlendShapeApplyerを追加します。
詳しくはこちらを参照。
揺れもの設定
HierarchyにあるPrefabの最下層にsecondaryがあります。こいつのInspectorにVRM Spring Boneがあります。
一つのVRM Spring Boneに複数のゆれものを設定できますが、重力設定等も共有されます。 同じで構わなければまとめて設定してしまいましょう。
今回は髪の揺れものを設定します。スカート等も同様の設定でいけます。
RootBonesのSizeに設定したい揺れものの数を入れます。今回は16です。
Elementに揺らしたいボーンの一番親のボーンをD&Dで入れます。これで一応は揺れます。
今回は16個ありますが、揺れものが多いと重くなり、動作が不安定になる原因ですのでなるべく減らしましょう。
設定が違う揺れものを追加する場合は、AddComponentからScripts\VRM\VRM Spring Boneをクリックします。
VRMSpringBoneの設定
項目 意味 Stiffness Force やわらかさ GravityPower 重力 GravityDir 重力方向 Drag Force 揺れの減衰 当たり判定
当たり判定を入れたいボーンのInspectorからAdd Componentをクリック。
Scripts\VRM\VRMSpringBoneColliderGroupをクリックして追加します。
ワイヤーの球体が現れます これが当たり判定です
sizeは当たり判定の数です。Elementのプルダウンを開くと座標や大きさが変更できるので、当たり判定を入れたい位置に入れていきましょう。
当たり判定の位置や大きさが決まったら、先程設定したVRM Spring Boneを開きます。
下部にあるCollider Groupsをプルダウンで開き、Elementの横にある⦿をクリック。設定した当たり判定を適用させます。
sizeを増やすことで、当たり判定群を追加していけます。
VRMファイルのエクスポート
VRMファイルをエクスポートします。正規化の時と同じようにPrefabを選択し、ツールバーのUniVRM-(バージョン)からExport humanoidをクリック。
正規化のときにAuthor設定等してあるため、そのままExportをクリック。
今回はUnityProject内にexportする必要はありませんので、任意の場所にexportしましょう。さいごに
お疲れ様でした。VRM化は終了です。
あとはVirtualCastやバーチャルモーションキャプチャーなどのVRM対応アプリでやりたいことをやりましょう。
ここまでの工程が頭に入っていれば、VRoid等のVRMモデル制作ツールで作ったモデルを、手直しすることも可能です。追記
ボーンの子にモデルを配置すればこんな事もできる。
このままVRMで出力できます。参考
VRM-dowango on GitHub
バーチャルキャストで使えるVRM作成講座!-youtube
VRM 標準シェーダMToonの使い方
- 投稿日:2019-04-17T14:09:29+09:00
VSTUを使わずに、Unityから生成されたsln / csprojファイルをスクリプトから変更する
やりたいこと
Unityが生成するslnファイルは、手動で外部のcsprojを足しても勝手に巻き戻されてしまいます。
そこで、スクリプトからslnファイルにcsprojを追加するようにします。既存のやり方としてVSTUのイベントにHookさせる方法がありますが、この方法はIDEにRiderを使っている場合は利用できませんでした。
やり方
AssetPostprocessorの
OnGeneratedSlnSolution
を使います。
(ドキュメントには書いてないですが、2018.2からこのイベント関数が追加されています。)そこで、次のようなエディタ拡張を配置すれば自動的にslnファイルにcsprojが追加されるようになります。
using UnityEditor; public class SolutionFileFixer : AssetPostprocessor { private static string OnGeneratedSlnSolution(string path, string content) { var solutionGuid = "solutionのGUID"; var projectGuid = "projectのGUID"; var projectName = "プロジェクト名"; var projectPath = "csprojへのパス"; var add = $"Project(\"{solutionGuid}\") = \"{projectName}\", \"{projectPath}\", \"{projectGuid}\",\"{Environment.NewLine}EndProject"; // 最後に追加 var newContent = content.Replace($"EndProject{Environment.NewLine}Global", $"EndProject{Environment.NewLine}{add}{Environment.NewLine}Global"); return newContent; } }おまけ
を参考に、Boo.Langも消し去るようにしてみます。
使うものは
OnGeneratedCSProject
イベントです。using UnityEditor; public class SolutionFileFixer : AssetPostprocessor { private static string OnGeneratedSlnSolution(string path, string content) { var solutionGuid = "solutionのGUID"; var projectGuid = "projectのGUID"; var projectName = "プロジェクト名"; var projectPath = "csprojへのパス"; var add = $"Project(\"{solutionGuid}\") = \"{projectName}\", \"{projectPath}\", \"{projectGuid}\",\"{Environment.NewLine}EndProject"; // 最後に追加 var newContent = content.Replace($"EndProject{Environment.NewLine}Global", $"EndProject{Environment.NewLine}{add}{Environment.NewLine}Global"); return newContent; } private static string OnGeneratedCSProject(string path, string content) { var document = XDocument.Parse(content); document.Root.Descendants() .Where(x => x.Name.LocalName == "Reference") .Where(x => (string) x.Attribute("Include") == "Boo.Lang") .Remove(); return document.Declaration + Environment.NewLine + document.Root; } }
- 投稿日:2019-04-17T12:32:58+09:00
【Unity2018.3】画面サイズに合わせてオブジェクトのサイズを調整する方法(2D)
概要
ゲームを様々な解像度に対応させるのに使用する。
ゲーム画面右上のワールド座標の取得
下記のコードによって画面右上のワールド座標を取得することができる。
取得したワールド座標を使って、オブジェクトサイズを調整する。Vector2 point = Camera.main.ViewportToWorldPoint(new Vector2(1, 1));使用例
マインスイーパのようなm * nのタイルを生成するときの使用例。
縦長画面を想定。
画面の横幅を基準にしてサイズを調整する。
調整するオブジェクトの元のサイズは、ワールド空間1ユニットに設定。int mapWidth = 8 //横のタイル数 int mapHeight = 8 //縦のタイル数 //画面右上の座標を取得 Vector2 point = Camera.main.ViewportToWorldPoint(new Vector2(1, 1)); //取得した座標は画面中心からの位置なので、2倍にして横の長さにする float screenWidth = point.x * 2f; //画面横の長さをタイル数で割って、タイル一個分の辺の長さを求める float tileUnit = screenWidth / MapWidth; //タイルサイズをベクトル型で作成 vector2 tileSize = new Vector2(tileUnit, tileUnit);最後に作成した変数を生成したオブジェクトのScaleに代入することでサイズを変更する。
- 投稿日:2019-04-17T11:38:09+09:00
MeshColliderで穴が塞がってしまう話
筒状になっているモデルの穴の部分にまでColliderがついてしまった
こんな感じで筒状のモデルにMeshColliderをアタッチしました。
これで穴を作ろうとしたら中の部分にまでColliderが詰まってて、オブジェクトが何もない空間の上に乗ってしまいました。問題点と解決法
MeshColliderのConvexがオンになっていることが問題でした。
ConvexはMeshCollider同士での衝突判定が行える設定らしい(間違っているかも)のですが、これをオンにすると中身までColliderが詰まってしまうみたいです。これをオフにすることで無事、筒状のモデルとしてCollisionの判定を行えました。
- 投稿日:2019-04-17T02:23:38+09:00
Shaderの_Timeをスクリプトで制御する際に気を付けること
Scriptを使ってShaderのPropertyを変更することはよくあるが、_Timeの速さを変更する際にガクガクになる問題があったので、それの解決記録として残しておく。
ガクガクする原因
今回例に挙げるのは、Shaderで縦にUVScrollしているが、Spaceキーを押している間だけ10倍速でUVScrollをするという仕組みを作ろうとしている。
そのために、今回用意したShaderとScriptは以下の通りである。Scroll.shaderShader "HC/Scroll" { Properties { _MainTex ("MainTexture", 2D) = "white" {} _Speed("VerticalSpeed", Range(-20, 20)) = 1 } SubShader { Tags { "Queue" = "Geometry" "RenderType" = "Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" uniform sampler2D _MainTex; uniform float4 _MainTex_ST; uniform float _Speed; struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float4 pos : SV_POSITION; float2 uvTex : TEXCOORD0; }; v2f vert (appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uvTex = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { float2 uv = i.uvTex; uv.y += _Time.y*_Speed; fixed4 color = tex2D(_MainTex, uv); return color; } ENDCG } } }uvscroll.csusing System.Collections; using System.Collections.Generic; using UnityEngine; public class uvscroll : MonoBehaviour { private Renderer renderer; private float speed { get{ return GetComponent<Renderer>().material.GetFloat("_Speed"); } set{ GetComponent<Renderer>().material.SetFloat("_Speed", value); } } void Start () { renderer = GetComponent<Renderer>(); } void Update () { if(Input.GetKeyDown(KeyCode.Space)) { speed = 10.0f; } if(Input.GetKeyUp(KeyCode.Space)) { speed = 1.0f; } } }これを実装すると次のような動き方をしてしまう。
どうして画像がガクガクしてしまうのかというと、普通の_Timeの時間軸と10倍の_Timeの時間軸をSpaceキーを押すことで、瞬間移動のように行ったり来たりしてしまうためにこの現象が起こる。
特に、Spaceキーを離したとき、時間が巻き戻るという異質な現象が起きるために余計にガクつきが発生する。解決策(素案)
この問題を解決するために、スクリプトのTime関数を使ってその値をShaderに流し込むという方法をとる。
ただ、これだけだとシェーダーの_Timeに倍率をかけている前の発想と同様な仕組みとなるため、ガクつきを抑えるためにLerp関数を用いてみるとする。
そして、Lerpの第三変数の遷移をAnimatorを使ってアナログにアニメーションすれば綺麗に行きそうではと試してみる。
ということで検証してみたが、やっぱりLerpの第三変数が0から1に行く過程で10倍の時間軸に移動するため、結局uvが早送りになってしまった。解決策(結論)
なので、どうしようと沼にはまる。
そこでUnityの公式のスクリプトリファレンスのTime関数とにらめっこしてみた。
すると、timeScaleという便利な関数があるではないか!ということでこれに倍率を代入してみることとする。
ということで、完成版のコードは以下の通りとなった。scroll1.shaderShader "HC/Scroll1" { Properties { _MainTex("MainTexture", 2D) = "white" {} _Speed("VerticalSpeed", Range(-20, 20)) = 1 } SubShader { Tags { "Queue" = "Geometry" "RenderType" = "Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" uniform sampler2D _MainTex; uniform float4 _MainTex_ST; uniform float _Speed; struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float4 pos : SV_POSITION; float2 uvTex : TEXCOORD0; }; v2f vert(appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uvTex = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag(v2f i) : SV_Target { float2 uv = i.uvTex; uv.y = _Speed; fixed4 color = tex2D(_MainTex, uv); return color; } ENDCG } } }uvscroll1.csusing System.Collections; using System.Collections.Generic; using UnityEngine; public class uvscroll1 : MonoBehaviour { private Renderer renderer; private float speed { get { return GetComponent<Renderer>().material.GetFloat("_Speed"); } set { GetComponent<Renderer>().material.SetFloat("_Speed", value); } } void Start() { renderer = GetComponent<Renderer>(); } void Update() { float time = Time.time; if (Input.GetKeyDown(KeyCode.Space)) { Time.timeScale = 10.0f; } if (Input.GetKeyUp(KeyCode.Space)) { Time.timeScale = 1.0f; } speed = time; } }これを実行すると、この動画のようにうまく連続的に倍率をかけられるようになった。
おまけ(宣伝)
今回のシェーダーのベースとなっているシンプルなUVScrollに透過機能を備えたシェーダーを売っているので、よければこちらからどうぞ!
- 投稿日:2019-04-17T01:01:12+09:00
Unity ML-Agents Toolkit v0.7でブロック崩し
社内の発表で、
Unity ML-Agents Toolkit
を使ってブロック崩しをするAgentを書いてみました。最近v0.8がリリースされましたが、使用したバージョンはv0.7になります。
左が10,000ステップのトレーニングで、右が800,000ステップになります。Source Code
https://github.com/fullcorder/BlockGame実装自体はできたものの、なかなか期待したとうり動いてくれずに苦労しました。
試行錯誤をメモとして残します。Agent実装クラスのDecision Interval
Decision Interval
を1でトレーニングを行っていたのですが、一向に動く気配がなく、試行錯誤したところこの値を10にした途端、期待するように動くようになりました。
Decision Interval
はドキュメントによるとDecision Interval - The number of steps between decision requests. Not used if On Demand Decision, is true.
なかなか理解が難しいですが、何回単位で方策を評価するといったところでしょうか。
トレーニング中のログからも、1ゲームプレイして判断ではなく、10ゲームプレイした結果で評価しているといったように見受けられました。失敗時AddReward(-1)をする
ブロック崩しで言うところの、ボールを空振りしてしまったときマイナスの報酬を与えると、同じステップのトレーニングでよりよい結果になりました。これをしばらく忘れていました。
感想
Unityのドキュメントが充実しているので、非常に助かりました。(ただし英語)
ただ学習がうまくいかないと割と途方にくれます。Qiitaの記事が非常に参考になりました。
Unity ML-Agentsは想像よりも簡単に強化学習を体験できるので、是非おすすめです。
- 投稿日:2019-04-17T00:42:59+09:00