20190417のUnityに関する記事は11件です。

UnityでImageを設定しても画像が表示されない時の対処法

こんにちは、ブログ「学生ブロックチェーンエンジニアのブログ」を運営しているアカネヤ(@ToshioAkaneya)です。

UnityでImageを設定しても画像が表示されない時の対処法

「Color」を選択して、「A(透過率)」の値を255にして下さい。
Screen Shot 2019-04-17 at 23.49.06.png
もしも、上のようにAの値が0のままImageを設定しても画像が表示されないので注意してください。

はてなブックマーク・Pocketはこちらから

はてなブックマークに追加
Pocketに追加

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 のものですが)
合わせてご確認お願いします。
ただこちらの記事の方が、普通と何が違うのかわかるのでいい気がします

① カラースペースをリニアにする

1.jpg

2.jpg

② Render Pipeline HD と Visual Effect Graph を Import する

3.PNG

4.jpg

少し待つと表示が増える。

5.jpg

6.jpg

③ Pipeline Asset を作って設定する

6.PNG

デフォルトで「New HDRenderPipelineAsset」というアセットが作成されます

8.PNG

7.jpg

10.PNG

④ ヒエラルキー上に Scene Settings を配置する

12.PNG

⑤ Visual Effect Graph を配置する!

13.PNG

14.jpg

15.jpg

やったー!!!!

16.PNG

あとは
https://youtu.be/uvGX8GPdfTE?t=853
とか見て勉強するだけだー!
わーい!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity、Zバッファとレンダリング順の仕組み

概要

3DCGで透明なオブジェクトを扱う上で抑えておきたいトピックです。
レンダリングの基礎。

透明なメッシュのレンダリング順

MakotoNoMegane.gif

このシーンは 赤・青・透明 の3種類のメッシュで構成されています。
しかし、透明なメッシュを青いメッシュより手前に描画しているにもかかわらず、透明なメッシュの後ろに青いメッシュが描画されてません。何故でしょうか?

CGで奥行きを認識する仕組み

Zバッファ.png
CGでは、オブジェクトの奥行きに関する位置をZバッファ(または深度バッファ)という方法で管理しています。
これはオブジェクトをレンダリングした時に、レンダリング結果とは別にオブジェクトの位置(深度情報)も保存しておきます。
再びスクリーンの同じ個所をレンダリングする時、今からレンダリングするオブジェクトと、前にレンダリングしたオブジェクトの深度を比較して、今からレンダリングオブジェクトが奥であるのならレンダリングをスキップします。
この工程をZテスト(または深度テスト)といいます。
この仕組みによって、オブジェクトの前後関係が正しいレンダリング結果を得る事ができます。

Zバッファ - Wikipedia

半透明の場合どうなるか?

Unity道場 2019.2 シェーダを書けるプログラマになろう #1 シェーダを理解しよう
上記動画の15:45~の解説が分かりやすいです。(そこから再生します)

端的に言うと…
不透明のオブジェクトしか存在しないの場合、Zブァッファの前後関係を比較すれば絵に矛盾は起きません。
しかし、半透明のオブジェクトが混ざってしまうと…半透明のオブジェクトの奥に、不透明のオブジェクトを描画してほしいのに、Zバッファは不透明のオブジェクトが奥になるので描画されないという事が起こりえるのです。

そのため、半透明のオブジェクトと不透明のオブジェクトはそれぞれ分けて管理して、不透明のものを全てレンダリングしてから半透明のものをレンダリングすると順番が決まっており、正しく表示できるわけです。
では、改めて先ほどのプロジェクトを見てみましょう。

RenderQueue.png

RenderQueueの値が若い順にレンダリングされるので、
「2000のred → 2001のMegane → 2002のBlue」の順番でレンダリングされることになります。
そのため、青をレンダリングする時に既にMeganeのZバッファがあるので…Meganeの部分だけBlueがレンダリングされずに、透過して見えてしまう。という仕組みなんですね。
これは、Zバッファの学習用にレンダリング順を変更したプロジェクトなわけです。

RenderQueue
Materialのレンダリング順に関する定義

透明オブジェクトのシェーダー

MakotoNoMegane.Shader
Shader "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バッファとレンダリング順の理解を深めるために、自由にお使いください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CLIでローカルビルドをUnityCloudBuildにアップ

※この記事を書いてる途中(2019/4/17)に ふとググったら去年10月公式に… :innocent:

それはさておき、2017年12月15日に

Unity Cloud Buildがローカル環境で作ったビルド成果物をアップロードできるようになった

という記事を見かけました。

しかし、WebからじゃなくCLIからアップロードしたいと思い、
きっと誰かが良い記事書いてくれるのでは…と思ってましたが
びっくりするくらい簡単なDeployGate1があるせいか、
はたまた そもそも興味持たれないのか 待てど暮らせど見つからず2
CloudBuildのページあたりを見ていましたらAPIドキュメント発見

CloudBuild API Document (v1.0.0時点)
https://build-api.cloud.unity3d.com/

 よし作ってみるか!

 …なるほど、まったくわからん :innocent:

とまでは行きませんでしたが
ChromeDeveloperで挙動やログを追いかけて なんとか出来ました 3
どれだけの方が利用するかわかりませんが、とりあえず公開

前提

  • 私の環境: MacOSX10.14.4(iMac4K)
  • 成果物は apk / ipa のみしかアップロードチェックしていません
  • unity DashBoard にて アプリ名登録まで済んでいるものとします
  • bashシェルスクリプトで順番に説明
  • json解析にjqを使用
  • 置換にgsedを使用
  • curl等、色々間違ってたらすいません…
  • ですので最低限のみ記載

以下スクショの文字列は例ですので DashBoard眺めてメモってください。
スクリーンショット 0031-04-17 18.06.45.png PROJECT_ID(ここではTest)と UPID(ここでは3dc…)をメモ

スクリーンショット 0031-04-17 18.06.20.png 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からダウンロード・インストール・実行出来ました。

みんな幸せにな〜れ :beers:

規約違反とかありましたら記事消します…。


  1. iOSのみならTestFlight、apkのみならGooglePlayテスト配信とかもありますね 

  2. (1週間待っただけですが) 

  3. 実際作ったのは2017年12月28日。1年以上寝かしてました。 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VRMモデル作成についての手順

はじめに

この公式ドキュメントを読むことを強く推奨します。
このスライドは、とりあえずVRMモデルをセットアップしたいという人向けに、纏めたものになっています。 MToonの項目は所々省いているので注意。
できるだけUnity初学者にも分かるように、書いているつもりです。
そもそも私が初学者
エグい長いので右のリンクを上手く使ってください。
※昔書いたサークル向けの記事を移植しています。 最新版は時間があるときに更新します。

説明で使用する環境

Unity 2017.4.18
UniVRM 0.48

使用できるモデル条件

  • Humanoidモデル
  • 各種Shapeキーが設定済みであること(表情・口パクを付ける場合)
  • 揺らしたい物にボーンが入っている(揺れものがある場合)
  • 瞳を動かすボーン、もしくは瞳に上下左右動かすShapeキーがある(視線移動したい場合)

準備

UnityとUniVRMの準備

まずはUnityで空のプロジェクトを作成します。
リリースページからUniVRMをダウンロードしてきます。基本的に最新版で構いません。
一番上のUniVRM-(バージョン).unitypackageをダウンロードしてください。
image.png
Assetウインドウで左クリックし、先程ダウンロードしたUniVRMのUnitypackageをインポートします。image.png
インポートするAssetの選択画面が出てくるのですべてチェックを入れimportを押します。
image.png

モデル配置

FBXモデルをAssetウインドウにD&Dで読み込ませます。今回は量産型マスキャットのモデルを使用します。
モデルを読み込んだらInspectorウインドウでRig設定をHumanoidに切り替えてApplyを押します。
image.png
AssetウインドウからHierarchyウインドウにD&Dでsceneに配置しましょう
image.png

Shaderについて

Shaderの設定をします
オブジェクトを選択し、InspectorウインドウからShaderを変更します
image.png
VRMではShaderを

  • Standard
  • VRM/UnlitTexture
  • VRM/UnlitCutout
  • VRM/UnlitTransparent
  • VRM/UnlitTransparentZWrite
  • VRM/MToon

の中から選ぶことが強く推奨されています。
今回はこの中からMToonとStandardを使用します。
image.png
デフォルトのライトは色がついているので、色を白にしましょう。そのままだと、ライトの色でルックが変わるので変えておきます。
image.png
今回はメカ部分をStandard、それ以外をMToonに設定します。
メカ部分は金属っぽさを出すためにStandardを選択しています。
もし、テクスチャに影が書かれている場合はUnlitTextureでも良いと思います。Unlitですのでライトの影響を受けません。
image.png

MToonの設定

今回はMToonのみ説明します。StandardやUnlit系のShaderはUnity標準と変わらないので。

Rendering

RenderingType

RenderingTypeは基本的にOpaqueでOKです。
テクスチャに透明部分があればCutoutやTransparentを使用しましょう。TransparentWithZWriteは奥行き情報のある半透明のオブジェクトに使用するといいでしょう
image.png

CullMode

CullModeは描画の設定ができます
Off==裏表描画
Front==表を描画しない
Back==裏を描画しない
image.png
左からOff、Front、Back
image.png

color

Lit Color, Alphaはベースカラーになります。
基本的に白でOK
Shade Colorは影の色です。
自分で調整しながら馴染む色に設定しましょう。大体はピンクの入ったグレーで良いと思います。
image.png

Lighting

Shading Shift

Shading Shiftは影をどこから付けるかの調整ができます。
-1は影なし 1はすべて影ありという感じです。
顔等は影が落ちすぎると暗い印象を与えてしまうため少し-値にするのがおすすめ。
左から-1 0 1
分かりやすいように影色を黒にしています。
image.png

ShadingToony

ShadingToonyは影の境界線の設定です。
値を上げればパリッとしたセル画調の影の付き方、下げればぼやけた感じになります。
値0(左)値1(右)
image.png

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 スクリーンに対して一定の幅の輪郭線を描画します(右) image.png

モデルデータの正規化

Materialの設定が終わったら一旦VRMで書き出します。
Hierarchyでモデルを選択した状態で、ツールバーのUniVRM-(バージョン)からExport humanoidをクリック。
Authorに製作者の名前を入れExportをクリック。export先をAssetのフォルダに指定します。
image.png
exportが終わると自動的にPrefabが生成されるので、元々Hierarchyにあったモデルを排除しPrefabをD&Dで配置します。
image.png

VRM独自の設定を行う

ライセンス周りを設定していきます。VRMの必要性に関わる大事な部分なので、しっかり設定してください。
少なくとも、タイトル・作者・ライセンス情報は埋めましょう。
注意として、A person who can perform with this avatarの項目をOnly Authorにすると、VirtualCastでは配信しない状態で使えなくなります。
項目は読めばわかると思うので、四角く囲っている部分を埋めていきましょう。
Texture2D部分はサムネイルですので自由に決めてください。
image.png

口パク・表情の設定

口パク・表情の設定に入ります。設定しなくても今の段階でVRMファイルとして出力できますが、表情がないです。
設置してあるPrefabを選択し、InspectorのVRM Blend Shape ProxyにあるBlend Shape Avatarをダブルクリックします。
image.png

表情の設定

表情を割り当てます。

項目 表情
NEUTRAL 標準
A
I
U
E
O
BLINK 目をつむる
JOY
ANGRY
SORROW
FUN
BLINK_L 左目を閉じる
BLINK_R 右目を閉じる

~視線制御がShapeキーの場合に設定~

項目 表情
LOOKUP 上を見る
LOOKDOWN 下を見る
LOOKLEFT 左を見る
LOOKRIGHT 右を見る

プルダウンを開くと設定しておいたShapeキーの一覧が表示されます。
それぞれのShapeキーを混ぜて表情を作ることもできます。
Inspectorの下に表情のプレビューがありますので見ながら設定しましょう。
image.png

表情の例

image.png

独自表情の追加

デフォルトの表情以外の表情を追加するにはAdd BlendShapeClipをクリック。
image.png
今回は例でキス顔を追加していきます。
開かれたフォルダ場所で【表情の名前.asset】と名前を編集し保存します。
あとは追加された項目を選択し、表情を作るだけです。簡単。
image.png
めっちゃかわいいすき

瞳の移動制御

VRMには瞳の追従機能が付いています。瞳が動きすぎないように設定しましょう。
瞳の設定を行うために瞳の追従先を生成します。
Hierarchyで3Dモデルを生成。なんでも良いですが今回はcubeにします。
image.png
設置したら手頃な大きさにして顔の前に配置します。
image.png
PrefabのInspectorにあるVRM Look At HeadのTargetに、先のcubeをD&Dします。HeadにHeadのボーンを設定します。
Headの位置は、Prefabのプルダウンを開いて、Armature\Hips\Spine\Chest\Neck\Headに大体あると思います。
ゲームを起動(▶を押す)しGameビューからSceneビューに切り替えします。
image.png

Targetに設定したオブジェクトを上下左右に動かし、瞳が動きすぎないかを確認。動きすぎたり、動きが少ない場合はVRM Look At Bone Applyerにあるスライダーで値を調整しましょう。
簡単にいうとXの値が動き方、Yの値が移動量です。
みゅみゅ教授曰く、Yは15~23ぐらいがいい。「大げさなぐらいが面白い」
※目の動きの制御をブレンドシェイプで行ってる場合は、VRMLookAtBoneApplyerを排除しVRMLookAtBlendShapeApplyerを追加します。
詳しくはこちらを参照。
image.png

揺れもの設定

HierarchyにあるPrefabの最下層にsecondaryがあります。こいつのInspectorにVRM Spring Boneがあります。
一つのVRM Spring Boneに複数のゆれものを設定できますが、重力設定等も共有されます。 同じで構わなければまとめて設定してしまいましょう。
image.png
今回は髪の揺れものを設定します。スカート等も同様の設定でいけます。
RootBonesのSizeに設定したい揺れものの数を入れます。今回は16です。
image.png
Elementに揺らしたいボーンの一番親のボーンをD&Dで入れます。これで一応は揺れます。
今回は16個ありますが、揺れものが多いと重くなり、動作が不安定になる原因ですのでなるべく減らしましょう。
image.png
設定が違う揺れものを追加する場合は、AddComponentからScripts\VRM\VRM Spring Boneをクリックします。
image.png

VRMSpringBoneの設定

image.png

項目 意味
Stiffness Force やわらかさ
GravityPower 重力
GravityDir 重力方向
Drag Force 揺れの減衰

当たり判定

当たり判定を入れたいボーンのInspectorからAdd Componentをクリック。
Scripts\VRM\VRMSpringBoneColliderGroupをクリックして追加します。
image.png
ワイヤーの球体が現れます これが当たり判定です
image.png
sizeは当たり判定の数です。Elementのプルダウンを開くと座標や大きさが変更できるので、当たり判定を入れたい位置に入れていきましょう。
image.png
当たり判定の位置や大きさが決まったら、先程設定したVRM Spring Boneを開きます。
下部にあるCollider Groupsをプルダウンで開き、Elementの横にある⦿をクリック。設定した当たり判定を適用させます。
sizeを増やすことで、当たり判定群を追加していけます。
image.png

VRMファイルのエクスポート

image.png
VRMファイルをエクスポートします。正規化の時と同じようにPrefabを選択し、ツールバーのUniVRM-(バージョン)からExport humanoidをクリック。
正規化のときにAuthor設定等してあるため、そのままExportをクリック。
今回はUnityProject内にexportする必要はありませんので、任意の場所にexportしましょう。

さいごに

お疲れ様でした。VRM化は終了です。
あとはVirtualCastやバーチャルモーションキャプチャーなどのVRM対応アプリでやりたいことをやりましょう。
ここまでの工程が頭に入っていれば、VRoid等のVRMモデル制作ツールで作ったモデルを、手直しすることも可能です。

追記

ボーンの子にモデルを配置すればこんな事もできる。
image.png
このままVRMで出力できます。

参考

VRM-dowango on GitHub
バーチャルキャストで使えるVRM作成講座!-youtube
VRM 標準シェーダMToonの使い方

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VSTUを使わずに、Unityから生成されたsln / csprojファイルをスクリプトから変更する

やりたいこと

Unityが生成するslnファイルは、手動で外部のcsprojを足しても勝手に巻き戻されてしまいます。
そこで、スクリプトからslnファイルにcsprojを追加するようにします。

既存のやり方としてVSTUのイベントにHookさせる方法がありますが、この方法はIDEにRiderを使っている場合は利用できませんでした。

やり方

AssetPostprocessorOnGeneratedSlnSolutionを使います。
(ドキュメントには書いてないですが、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;
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【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に代入することでサイズを変更する。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MeshColliderで穴が塞がってしまう話

筒状になっているモデルの穴の部分にまでColliderがついてしまった

こんな感じで筒状のモデルにMeshColliderをアタッチしました。
これで穴を作ろうとしたら中の部分にまでColliderが詰まってて、オブジェクトが何もない空間の上に乗ってしまいました。

スクリーンショット 2019-04-17 11.27.15.png

問題点と解決法

MeshColliderのConvexがオンになっていることが問題でした。
ConvexはMeshCollider同士での衝突判定が行える設定らしい(間違っているかも)のですが、これをオンにすると中身までColliderが詰まってしまうみたいです。

これをオフにすることで無事、筒状のモデルとしてCollisionの判定を行えました。

スクリーンショット 2019-04-17 11.35.39.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Shaderの_Timeをスクリプトで制御する際に気を付けること

Scriptを使ってShaderのPropertyを変更することはよくあるが、_Timeの速さを変更する際にガクガクになる問題があったので、それの解決記録として残しておく。

ガクガクする原因

今回例に挙げるのは、Shaderで縦にUVScrollしているが、Spaceキーを押している間だけ10倍速でUVScrollをするという仕組みを作ろうとしている。
そのために、今回用意したShaderとScriptは以下の通りである。

Scroll.shader
Shader "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.cs
using 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;
        }
    }
}

これを実装すると次のような動き方をしてしまう。
Before
どうして画像がガクガクしてしまうのかというと、普通の_Timeの時間軸と10倍の_Timeの時間軸をSpaceキーを押すことで、瞬間移動のように行ったり来たりしてしまうためにこの現象が起こる。
特に、Spaceキーを離したとき、時間が巻き戻るという異質な現象が起きるために余計にガクつきが発生する。

解決策(素案)

この問題を解決するために、スクリプトのTime関数を使ってその値をShaderに流し込むという方法をとる。
ただ、これだけだとシェーダーの_Timeに倍率をかけている前の発想と同様な仕組みとなるため、ガクつきを抑えるためにLerp関数を用いてみるとする。
そして、Lerpの第三変数の遷移をAnimatorを使ってアナログにアニメーションすれば綺麗に行きそうではと試してみる。
ということで検証してみたが、やっぱりLerpの第三変数が0から1に行く過程で10倍の時間軸に移動するため、結局uvが早送りになってしまった。

解決策(結論)

なので、どうしようと沼にはまる。
そこでUnityの公式のスクリプトリファレンスのTime関数とにらめっこしてみた。
すると、timeScaleという便利な関数があるではないか!ということでこれに倍率を代入してみることとする。
ということで、完成版のコードは以下の通りとなった。

scroll1.shader
Shader "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.cs
using 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;
    }
}

これを実行すると、この動画のようにうまく連続的に倍率をかけられるようになった。
After

おまけ(宣伝)

今回のシェーダーのベースとなっているシンプルなUVScrollに透過機能を備えたシェーダーを売っているので、よければこちらからどうぞ!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity ML-Agents Toolkit v0.7でブロック崩し

社内の発表で、Unity ML-Agents Toolkitを使ってブロック崩しをするAgentを書いてみました。最近v0.8がリリースされましたが、使用したバージョンはv0.7になります。

Cap.2019-04-15 23_36_12.gif
左が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は想像よりも簡単に強化学習を体験できるので、是非おすすめです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity2019 Visual Studio2019のメモ

Unity2019 Visual Studio2019のメモ

Androidへのビルドに成功
PackageManagerにGoogleVRが追加された
Visual StudioでUnityのプログラムとして認識されないことがある
新たなスクリプトを作れないことがある(再起動で直る)
ProbuilderのMaterialが変わった

Windows MRについて

Scripting Backendの変更が必要なくなった
HMDを接続していない状態で実行してもWindows MRは起動しなくなった
Unityでのビルドに成功
Visual Studioでのビルドに失敗

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む