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

[VRChat]DynamicBoneスカートの私も優雅に裾をつまんでご挨拶(カーテシー)したいですわ

今回のアバター

先日、また新しいアバターを購入しました。
クローシアさんのシルヴィーヌちゃんです。



もともとは以前のDynamicBone吊りスカートを長い丈のスカートで検証するためにと思って買ったのですが、純粋にかわいいです。すぐに使い込みたくなりました。

長い丈のスカートはつまみたくなる

ほぼ時を同じくして、妻がメイドさんになりました。



このメイドさんモデルのAmeliaさんですが、スカートの裾をつまんでご挨拶、いわゆるカーテシーができるようになっています。
その仕組みはどうやら、Clothの網の目のようなコライダーに、ハンドサインで手に出現させたコライダーを引っかけてスカートを持ち上げるというもののようです。
clip_hold8.PNG
いいですねぇ。
シルヴィーヌちゃんも長い丈のスカート、つまんでご挨拶したくなります。

スカートは大抵DynamicBoneですね

ところが、アバターのスカートの揺れはClothではなくDynamicBoneで表現されることが多く、シルヴィーヌちゃんもその1人です。
Clothのような網の目のコライダーはなく、スカートのボーンの粒をどうにかしてつまみ上げるしかありません。それが目標になります。
image.png

スカートのボーンをコライダーで引っかける

こんな形のDynamicBoneColliderを左右の手の先に用意します。
この3つのコライダーの窪みでスカートのボーンを引っかけるという寸法です。
clip_hold2.PNG
clip_hold1.PNG
右手の例ですが、手のボーン(hand.R)の下に空GameObjectを加えて、その下にさらに3つの空GamgeObjectを加え、それぞれDynamicBoneColliderをアタッチして位置調整をします。
今、わかりやすくコライダーに沿ってCylinderモデルも一緒につけていますが、こちらは実際には不要です。
コライダーが出来上がったら、スカートを揺らしているDynamicBoneに設定してください。

特定のハンドサインで出るようにアニメーション設定

しかし、常時コライダーが飛び出していては邪魔になるし、スカートの中に手を入れることもできなくなってしまうので、
普段はコライダーの幹である「holdhand.R」(左手は「holdhand.L」)のscaleを0.001などに縮小しておき、
それを特定のハンドサインで1に戻すようにします。私はRockNRollに設定しました。

ハンドサインの設定方法についてはこちらを参照してください。

アニメーションオーバーライドの設定

AnimationClipにはTransform値も設定することができます。
あと折角なので、つまんだときの指の形を作っておくのもオススメです。

スカートをつまむことができました

これで一応、VRChatでスカートをつまみ上げることができるようになりました。


「たぐり寄せアニメーション」で掴み判定を拡大

ただ、このボーンの1点をコライダーの隙間に挟み込むのは結構難しく、
瞬間でさっとつまんで優雅にご挨拶、とするのはかなりの修練が必要です。

そこで、ハンドサインでつまむとき、コライダーを下からたぐり寄せるようにアニメーション設定しました。

1コマ目。z軸のマイナス方向に少し動いたところから始まります。
clip_hold4.PNG

2コマ目。本来の位置に戻ります。
clip_hold5.PNG

AnimationClipの設定はこのような感じです。
clip_hold7.PNG
clip_hold6.PNG

Position.zを選択してCurves画面を開き、図のように0:00での傾きをゼロを超えてしまわない程度に右肩上がりにします。
スカートをつまんでいる間はこのハンドサイン(RockNRoll)から同じハンドサイン(RockNRoll)へのアニメーション遷移が断続的に発生し、このアニメーションの先頭へループすることが避けられないのですが、
できるだけ素早く0に近づけることによって、コライダーの動きを目立たなくする意図です。
最初の一瞬はまだ遷移割合が低いので、コライダーは殆ど動きません。
この傾きをつけないと、コライダーの動きが目立ってスカートがプルプルします。

あと、忘れそうになりますが、
AnimationClipのLoopTimeのチェックを外しておいてください。
image.png
これにチェックがついていると、否応なくコライダーがブルブルします。

しっかりスカートをつかめました

ちゃんと動きの中でスカートをつまめていますね。
たまに失敗しますが、成功率は格段に上がりました。

【アーカイブ】当初のアニメーション設定

以上ですが、初稿からアニメーションの設定が改善されています。
最初に記載していた内容を参考までにアーカイブとして残しておきます。

 :
 :
 :

clip_hold7.PNG
clip_hold6.PNG
0:00~0:01の間で移動して、0:01~0:03はキープしています。
これは、必ずしもベストかどうかはわかりません。VRChatの悩ましい仕様の私なりの妥協点です。

VRChatのハンドサインアニメーションには

  • 設定されているアニメーションの長さの4倍の時間で次のアニメーションに遷移する
  • その遷移中は、さらに他のアニメーションに遷移することができない

という特徴があります。
要するに、設定するアニメーションが長いほど、その後の動作が鈍くなります。
通常は動きなどつけず、0:01で固定しておくべきです。

今回も0:01で留めておくべきなのですが、
一方でこのハンドサイン(RockNRoll)から同じハンドサイン(RockNRoll)への遷移も当然発生していて、
このアニメーションの先頭へループ、すなわちコライダーが動いてスカートが小刻みにプルプル動くことになります。
もちろん、この設定でも同じことが言えますが、0:03までアニメーション設定していることでその周期を下げているんですね。

  • アニメーションを長くするとその後の遷移が鈍くなる
  • アニメーションを短くするとスカートのプルプルが小刻みになる

この2つの問題に挟まれた中で、比較的どちらも不自然にならないバランスだと考えた長さが0:03です。

 :
 :
 :

とまぁ、そんな話でしたが、
カーブの傾きをつけることによって、0:01のアニメーションでもプルプルが目立たなくなったという次第です。

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

Live2DでVRコンテンツを作りたい

はじめに

Live2DでVTuberをやっている方も多いと思いますのでLive2D × VRでコンテンツが作れないかと思い調べてみました。

Live2D SDKのダウンロード

https://live2d.github.io/
こちらのページからLive2DSDKをダウンロードできます。

SDKにはサンプルモデルがいくつか入っていますが、自分のオリジナルのモデルを使用するのも非常に簡単です。

Unityにインポート

ダウンロードしたunitypackageを実行しunityに導入します。

1556789862672 (2).jpg

com.Company.live2d-20190502-195110.jpg

Roomのアセットは下記を使用させて頂きました。
https://assetstore.unity.com/packages/3d/environments/free-medieval-room-131004
モデルにはLive2DSDKのSampleに入っているkohakuちゃんを使用させて頂きました。

ヒエラルキーにモデル等を配置してHMDにBuildすれば360度見渡すことができます。

ライブ配信

facebookの360-Capture-SDKを使用すればそのままライブ配信もできそうです。
https://github.com/facebook/360-Capture-SDK/releases

終わりに

Live2DとFaceRigで手軽にVTuberを始めることができますが3Dと比べて自由度に限界があるのでVRと組み合わせてなにか面白いことできないかな~と思って調べてみました。

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

UnityのAnimation Eventで関数定義と関数選択が分かりにくかった

はじめに

アニメーションイベントの使用 - Unity マニュアル[Unity] Animation Eventを使いこなそう!を参考に自作アニメーションにAnimation Eventをつけようとしたのですがインスペクターの挙動が分かりにくいのでまとめました。

Animation Eventの関数定義

  1. プロジェクトタブでAnimationファイルを選択します。
  2. アニメーションタブでAnimation Eventを選択します。
  3. インスペクターに関数定義が出てきます。

image.png

Animation Eventの関数選択

  1. ヒエラルキーで上記Animationを含むAnimation Controllerを関連付けたゲームオブジェクトを選択します。
  2. アニメーションタブでAnimation Eventを選択します。
  3. インスペクターに関数選択が出てきます。

image.png

まとめ

何でこんな挙動なのか考えてみると分かったのですが、関数定義はAnimation Eventの定義はAnimation自体にあるのでファイルを選択してから、関数選択は同じゲームオブジェクトにアタッチしたスクリプトから選ぶのでヒエラルキーのゲームオブジェクトを選択してからなので納得できます。とは言え直前に選択したもので挙動が変わるのは分かりづらい…

参考リンク

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

【GooglePlay】AdMob広告を入れた場合の設定「コンテンツの不適切なレーティング」

AdMob側の設定で、「デリケートなカテゴリ」で広告の種類が設定できる。
Google Playの「コンテンツのレーディング」とAdMobの「デリケートなカテゴリ」を、矛盾なく設定する必要がある。

コンテンツのレーディングを「3歳以上」の場合は、AdMobの「デリケートなカテゴリ」を
許可→ブロック
に設定する。

↓AdMob側
スクリーンショット 2019-05-02 17.55.37.png

スクリーンショット 2019-05-02 17.56.13.png

↓Google Play側
スクリーンショット 2019-05-02 18.04.24.png




↓↓Google Play 無料Free
CherryCocktailGlassチェリーカクテルグラス〜無料簡単ミニゲームFree games
googleStoreLink.png

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

Azure Spatial Anchors v1.1.0 Unity iOS版をビルドしてみる

はじめに

Azure Spatial Anchors v1.1.0 Unity Android版をビルドしてみる の次にiOS版もビルドしてみる。公式ドキュメントはこちら

やってみる

Azure Portalでの設定と、azure-spatial-anchors-samplesをcloneしてUnityフォルダを開くところまではAndroid版と同じ

Unity ARKit Plugin version 2.0.0 をダウンロードしておく

ファイル -> ビルド設定 を選択する

スクリーンショット 2019-05-02 15.01.32.png

ビルドに含まれるシーン はデフォルトのまま全選択。プラットフォームiOSを選択しSwitch Platformボタンをクリックする

スクリーンショット 2019-05-02 15.01.50.png

設定が完了したらビルド設定 を閉じる

先ほどダウンロードしておいたUnity ARKit Plugin version 2.0.0を展開し、展開したフォルダのAssetsフォルダの中身をUnityのAssetsフォルダにコピーする

プロジェクトからAssets -> AzureSpatialAnchorsPlugin -> Examples -> Resources とフォルダを選択して、AzureSpatialAnchorsDemoConfig アセットを選択する

2d171c2b-34d5-4c57-819e-ad376fc49790.png

インスペクターで控えておいたSpatial Anchor AccountのAccount IDPrimary Keyを入力してプロジェクトを保存する

fc56cf5a-f9bd-42f8-95d1-2765fd6e5504.png

ビルド前にアセットの再インポートをやっておいたほうがいいのはAndroid版と同じ。アセット -> すべてを再インポートを選択してアセットを再構成する

ファイル -> ビルド設定 を選択する

スクリーンショット 2019-05-02 15.01.32.png

ビルド ボタンをクリックしてプロジェクト名を入力しSaveボタンをクリックする。ここではプロジェクト名をSpatialAnchorsDemo-iOSとする

スクリーンショット 2019-05-02 15.53.51.png

エクスポートされたプロジェクトに移動して、依存パッケージをインストールする

cd SpatialAnchorsDemo-iOS

pod install --repo-update

XCodeでUnity-iPhone.xcworkspaceを開く。.xcodeprojでないことに注意

open ./Unity-iPhone.xcworkspace

Bundle Identifierを適当な名称に変更して、Teamに有効なアカウントを設定する

スクリーンショット 2019-05-02 16.45.21.png

iPhoneをMacに接続して、ビルドボタンをクリックし、iPhoneにアプリケーションをインストーする

アプリがインストールされるのでデモを実行する。デモの操作方法はAndroid版と同じ

iOSdemo.png

まとめ

Android版との違いはUnity ARKit Plugin version 2.0.0のインポートくらいであとは普通にiOS用にビルドすればできる。次はAndroid版とこのiOS版のデモを使ってシェアリングをやってみたいと思う

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

UnityでiPhoneX系による表情取得について

自己紹介

こんにちはゆずです。@Yuzu_Unity
自分はUnityエンジニア・3DCGデザイナーの学生です。(軸はエンジニア 4年ほど…)
※自分は現在どこの企業にも所属していませんので技術周りなら色々言っちゃおうかと
      インターンとか行きたいです…(切実(3回目))

オリジナルのVtuberですのでチャンネル登録お願いします…
藤田りあ@Ria_fujita  自己紹介動画
上記のリンクの映像を作るための技術紹介記事です。

はじめに

これを使います…これで記事は終わりです。
https://github.com/Unity-Technologies/facial-ar-remote
キズナアイが使ってるらしい?ZIPで紹介されていたみたいです(自分は見ていないので…)
にじさんじの3Dはこれを使っていのかな?

準備物

iPhoneX/XR/XS
Mac(iOSビルドを行うため)
最終的にiPhoneの表情データを取得させたい!
Windows/Mac

使い方

https://github.com/Unity-Technologies/facial-ar-remote/releases
releasesから使いたいところですが
iPhoneXS/XRで使える記述がver1.1ではないみたいです。
なので最新版をクローンします!!
zipでダウンロードするといろんなデータが死んでしまうみたいなので
LFSが使えるGit等でクローンしましょう。

Githubに使い方等が書いています。
iOS Build Setup
Editor Animation Setup
の欄です。

iOSビルドを行った後
Win/MacのローカルLan内での接続です。
ファイアーウォールの設定を行わないと接続できないので注意

インストールTips

ARKit pluginの場所 BitBucket

7.Enable "ARKit Uses Facetracking" on UnityARKitPlugin > Resources > UnityARKitPlugIn > ARKitSettingsの場所
unknown.png

自分のキャラクターを動かしたい…

可愛くないし…
image.png

このアセットに含まれている自分のメッシュへの適用なのですがセットアップがめんどくさい…
image.png

なのでそこは触れず自分は

tmp[i]=Mathf.Clamp(skin.GetBlendShapeWeight(i),0,100);

を用い
狸?のブレンドシェイプをそのままコピーすることにしました。
あとは自分の使いたいキャラクターにSetBlendShapeWeightを行うだけです。

 //目線制御 こちらもブレンドシェイプから取得しボーンに回転値を割り当てします。
    void Update()
    {
        debugRotL = EyeRot(tmp[1], tmp[4], tmp[3], tmp[2]);
        debugRotR = EyeRot(tmp[8], tmp[11], tmp[9], tmp[10]);
        eyeL.localRotation = Quaternion.Euler(debugRotL);
        eyeR.localRotation = Quaternion.Euler(debugRotR);
    }

    Vector3 EyeRot(float valueL,float valueR,float valueUp,float valueDown)
    {
        float left = (valueL - valueR) * 45/100/4;
        float up = (valueDown - valueUp) * 45/100/4;
        return new Vector3(left, up, 0);
    }

Unityの地味な便利機能Constraintでコード書かずボーンに割り当て…
Mayaとの連帯機能ですが便利です。
首や頭の傾き等もこれを用い設定します。
image.png
【Unity】複数のオブジェクトの位置を元にオブジェクトを動かす、○○○Constraint系というオモシロ機能

表情レコード機能

このアセットにはレコード機能など含まれていますが
自分はこちらを使うため使わないことにします。
https://qiita.com/Yuzu_Unity/items/d891ecee64a164149167

結果

リップシンクはOVRLipSyncを用いたので今回は瞬きのみ適用しました。
iPhoneで取得するとリアル差がかなり上がります。
人間の瞬きは奥が深いものですね…
OpenCV×Dlibで行うより簡単で高精度なのでおすすめかと…
image.png

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

UnityでAdMobやFirebaseを入れた時のgradleファイルを晒す

はじめに

UnityのAndroidビルド時に巻き起こる謎のビルドエラー
だいたいはライブラリの不足や競合だったりするのですが、エラーメッセージが分かりにくい為に解決するのに時間がかかるんですよねー。
ので、自分がビルド通った時のgradleファイルを晒して少しでも参考になればと...
(自分自身Androidやgradleについてあまり詳しくないので、ちょっとずつ加筆修正していくと思います)

実装環境

  • Unity 2019.1.0f2
  • gradle 3.2.0

使用ライブラリ

  • Firebase Analytics
  • Firebase Remote Config
  • AdMob
  • nend(AdMob Mediation)
  • AppLovin(AdMob Mediation)

gradleファイル

mainTemplate.gradle
// GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN

buildscript {
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.0'
**BUILD_SCRIPT_DEPS**}
}

allprojects {
    repositories {
        google()
        jcenter()
        flatDir {
            dirs 'libs'
        }
    }
}

apply plugin: 'com.android.application'
**APPLY_PLUGINS**

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    // AndroidSupport
    compile group: 'com.android.support', name: 'customtabs', version: '26.1.0'
    compile group: 'com.android.support', name: 'support-annotations', version: '26.1.0'
    compile group: 'com.android.support', name: 'support-compat', version: '26.1.0'
    compile group: 'com.android.support', name: 'support-core-ui', version: '26.1.0'
    compile group: 'com.android.support', name: 'support-core-utils', version: '26.1.0'
    compile group: 'com.android.support', name: 'support-fragment', version: '26.1.0'
    compile group: 'com.android.support', name: 'support-media-compat', version: '26.1.0'
    compile group: 'com.android.support', name: 'support-v4', version: '26.1.0'
    compile group: 'com.android.support', name: 'recyclerview-v7', version: '26.1.0'
    compile group: 'com.android.support', name: 'appcompat-v7', version: '26.1.0'
    compile group: 'com.android.support', name: 'cardview-v7', version: '26.1.0'
    compile group: 'com.android.support.constraint', name: 'constraint-layout-solver', version: '1.1.3'
    compile group: 'com.android.support.constraint', name: 'constraint-layout', version: '1.1.3'

    // gms
    compile group: 'com.google.android.gms', name: 'play-services-ads', version: '17.2.0'
    compile group: 'com.google.android.gms', name: 'play-services-ads-base', version: '17.2.0'
    compile group: 'com.google.android.gms', name: 'play-services-ads-identifier', version: '16.0.0'
    compile group: 'com.google.android.gms', name: 'play-services-ads-lite', version: '17.2.0'
    compile group: 'com.google.android.gms', name: 'play-services-base', version: '16.0.1'
    compile group: 'com.google.android.gms', name: 'play-services-basement', version: '16.2.0'
    compile group: 'com.google.android.gms', name: 'play-services-gass', version: '17.2.0'
    compile group: 'com.google.android.gms', name: 'play-services-measurement', version: '16.4.0'
    compile group: 'com.google.android.gms', name: 'play-services-measurement-api', version: '16.4.0'
    compile group: 'com.google.android.gms', name: 'play-services-measurement-base', version: '16.4.0'
    compile group: 'com.google.android.gms', name: 'play-services-measurement-impl', version: '16.4.0'
    compile group: 'com.google.android.gms', name: 'play-services-measurement-sdk', version: '16.4.0'
    compile group: 'com.google.android.gms', name: 'play-services-measurement-sdk-api', version: '16.4.0'
    compile group: 'com.google.android.gms', name: 'play-services-stats', version: '16.0.1'
    compile group: 'com.google.android.gms', name: 'play-services-tasks', version: '16.0.1'

    // Firebase
    compile group: 'com.google.firebase', name: 'firebase-abt', version: '17.1.0'
    compile group: 'com.google.firebase', name: 'firebase-analytics', version: '16.4.0'
    compile group: 'com.google.firebase', name: 'firebase-common', version: '16.1.0'
    compile group: 'com.google.firebase', name: 'firebase-config', version: '16.4.1'
    compile group: 'com.google.firebase', name: 'firebase-core', version: '16.0.8'
    compile group: 'com.google.firebase', name: 'firebase-iid', version: '17.1.0'
    compile group: 'com.google.firebase', name: 'firebase-iid-interop', version: '16.0.1'
    compile group: 'com.google.firebase', name: 'firebase-measurement-connector', version: '17.0.1'

    // Other
    compile 'com.google.ads.mediation:nend:5.1.0.1'
    compile 'com.applovin:applovin-sdk:+'
    compile group: 'com.google.auto.value', name: 'auto-value-annotations', version: '1.6.3'

    // internal
    compile(name: 'com.google.firebase.firebase-app-unity-5.6.0', ext: 'aar')
    compile(name: 'com.google.firebase.firebase-config-unity-5.6.0', ext: 'aar')

**DEPS**
}

android {
    compileSdkVersion **APIVERSION**
    buildToolsVersion '**BUILDTOOLS**'

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
        minSdkVersion **MINSDKVERSION**
        targetSdkVersion **TARGETSDKVERSION**
        applicationId '**APPLICATIONID**'
        ndk {
            abiFilters **ABIFILTERS**
        }
        versionCode **VERSIONCODE**
        versionName '**VERSIONNAME**'
    }

    lintOptions {
        abortOnError false
    }

    aaptOptions {
        noCompress = ['.unity3d', '.ress', '.resource', '.obb'**STREAMING_ASSETS**]
    }**SIGN**

    buildTypes {
        debug {
            minifyEnabled **MINIFY_DEBUG**
            useProguard **PROGUARD_DEBUG**
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'**USER_PROGUARD**
            jniDebuggable true
        }
        release {
            minifyEnabled **MINIFY_RELEASE**
            useProguard **PROGUARD_RELEASE**
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'**USER_PROGUARD****SIGNCONFIG**
        }
    }**PACKAGING_OPTIONS****SPLITS**
**BUILT_APK_LOCATION**
    bundle {
        language {
            enableSplit = false
        }
        density {
            enableSplit = false
        }
        abi {
            enableSplit = true
        }
    }
}**SPLITS_VERSION_CODE****REPOSITORIES****SOURCE_BUILD_SETUP**

補足

  • gradleへ記載するライブラリ名は https://mvnrepository.com/ で調べました
  • 現在のSDKのバージョンに合わせる必要があります(新しければいいという訳ではないので注意を)
  • // internal の項目のライブラリはファイルをダウンロードしておく必要があります。それ以外はライブラリ競合を起こすので削除 or Androidのビルド対象から外してください
  • AdMobやFirebaseのUnitySDKインポート時に Play Services Resolverがインストールされ、ライブラリが自動的にインポートされます。これはgradleのライブラリと競合を起こすので、以下の手順で自動インポートを解除する必要があります
  1. Settingsへ遷移
    スクリーンショット 2019-05-02 13.12.26.png

  2. Enable Auto-Resolutionのチェックを外しOK
    スクリーンショット 2019-05-02 13.12.37.png

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

UnityのスマホネイティブプラグインをKotlin/Nativeで共通化する

Unityのスマホネイティブプラグインを言語統一できないか?

昨今のスマホネイティブプラグインの言語の選択肢としてはJava, Kotlin, Objective-c, Swiftがあげられるかと思います。
たまに自分も趣味などでプラグインを使うことがあるのですが同じような処理を別で書かないといけないのが手間だと思っていました。
そこで昨年くらいからスマホのネイティブ界隈で話題になっていたKotlin/Nativeに目をつけてUnityで実行させてみたという記事です。

そもそもKotlin/Nativeとは…?
まとめている記事もありましたので参照させて頂きます。

基本的にはスマホネイティブの共通化できるロジックをKotlinで書いて共通化させようぜ!ってことなのですがAndroidでは.jarとしても吐き出せますし、iOSは.frameworkとして吐き出せるのでネイティブにとって扱いやすいものになっています。

さて、今回検証に使用したリポジトリです。動かして見たい人は是非ご活用ください。

実行した結果

Android iOS
Screenshot_20190502-040341.jpg Simulator Screen Shot - iPhone Xʀ - 2019-05-02 at 10.31.23.png

文字列をOS毎に変えるという処理ですが呼び出すメソッドは1つにしてあります。

準備

Kotlin/Native自体の作成方法は既にわかりやすい記事がありますのでそちらを参照させていただきます。
Kotlin/Nativeチュートリアル Android, iOS編
自分はここを参考にさせて頂きました。そのため今回上記の記事をベースに進めます。

Androidのネイティブが自分はよくわからなかったので、最初は基本的にコピペで作って必要な箇所を変えていきました。

今回、上記記事の「Common moduleの解説」の章まで出来たら一旦は大丈夫です。
上記の記事ほぼそのままですがソースコードを載せておきます。

共通

common.kt
package com.sample.mizotake.kotlinnativeforunity

expect fun platformName(): String

public class common {
    public fun createApplicationScreenMessage(): String {
        return "Call Kotlin Native on ${platformName()}"
    }
}

Android

actual.kt
package com.sample.mizotake.kotlinnativeforunity

actual fun platformName(): String {
    return "Android"
}

iOS

actual.kt
package com.sample.mizotake.kotlinnativeforunity

import platform.UIKit.UIDevice

actual fun platformName(): String {
    return UIDevice.currentDevice.systemName() +
            " " +
            UIDevice.currentDevice.systemVersion
}

共通処理にUnityで呼び出すクラスとメソッドを定義します。OS毎に変える処理はexpect actual処理でinterfaceのように切り出して呼べるようです。

Unityへの導入

Android

自分もよく把握できていませんがGradle Syncをするとbuildというディレクトリができて
スクリーンショット 2019-05-02 11.06.40.png

プロジェクト名 + android.jarができていました。
もし出来ていない場合は
スクリーンショット 2019-05-02 11.04.44.png
右端にGradleというタブがあるのでそこからbuildの項目を見るとbuildの詳細一覧があるのでandroidJarをダブルクリックすれば走り出してjarができるかと思います。

吐き出されたjarをUnityのPlugin/Androidに放り入れるだけです。
これでUnityへの導入は完了です。

iOS

こちらは先ほどのKotlin/Nativeチュートリアル Android, iOS編の「iOSアプリ」の章にあるbuild.gradleの追記だけ行いましょう。

/common/build.gradle
...

task packForXCode(type: Sync) {
    final File frameworkDir = new File(buildDir, "xcode-frameworks")
    final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG'

    inputs.property "mode", mode
    dependsOn kotlin.targets.iOS.compilations.main.linkTaskName("FRAMEWORK", mode)

    from { kotlin.targets.iOS.compilations.main.getBinary("FRAMEWORK", mode).parentFile }
    into frameworkDir

    doLast {
        new File(frameworkDir, 'gradlew').with {
            text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n"
            setExecutable(true)
        }
    }
}

tasks.build.dependsOn packForXCode

ここの部分ですね。これを追記して./gradlew buildすることで
スクリーンショット 2019-05-02 11.17.06.png
main.frameworkができます。これをUnityのPlugin/iOSに放り込めばframeworkの導入は大丈夫ですが、iOSの場合もう一手間必要です。
externの実装がないとC#では呼び出せませんそのためPlugin/iOSフォルダに

common.mm
#import <main/main.h>

extern "C" {
    const char* createApplicationScreenMessage() {
        NSString *message = [[Maincommon alloc] init].createApplicationScreenMessage;
        return strdup([message UTF8String]);
    }
}

を追加しましょう。これを追加することで先ほど作ったKotlinで書いたコードのframeworkを参照できます。
ここでcommonというkotlinファイルを作ったがMaincommonって何だろう?ってなると思います。どうやらframeworkに吐き出す時に変換されているようです。
それを確認するにはAndroidStudioでframeworkのHeaderを見ると一番下の行に自分で実装した処理が追記されていると思います。
スクリーンショット 2019-05-02 11.22.16.png

これを参考にしてObjective-c++でインターフェースを定義する必要があります。
ちなみにSwiftだとMaincommonという変換名ではなくcommonで呼び出せそうですがSwiftを使うために手間をかけるよりObjective-c++を書いた方が早いと自分は思うのでこのまま進めます。

C#で呼び出す

事前準備は終わりました。
UnityではuGUIのTextにネイティブで呼び出した文字列を表示させます。

CallKotlinNative.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;

public class CallKotlinNative : MonoBehaviour
{

#if UNITY_IOS
    [DllImport("__Internal")]
    private static extern string createApplicationScreenMessage();
#endif

    private Text viewableText;

    void Start()
    {
        var pluginMessage = "";
#if UNITY_ANDROID
        using (var plugin = new AndroidJavaObject("com.sample.mizotake.kotlinnativeforunity.common"))
        {
            pluginMessage = plugin.Call<string>("createApplicationScreenMessage");
            Debug.Log(pluginMessage);
        }
#elif UNITY_IOS
        pluginMessage = createApplicationScreenMessage();
#endif
        viewableText = GetComponent<Text>();
        viewableText.text = pluginMessage;
    }
}

C#側は普通にネイティブプラグインを呼び出すだけですね。
これを実機ビルドまたはシミュレータービルドすることで動作の確認ができると思います。

終わりに

Kotlin/NativeのUnityProjectへの導入は手間が必要かと思っていましたが思った以上に簡単でした。ただ、iOSの導入のexternだけどうにかならなかいとAndroidProject内に.mm入れてみて.frameworkだけ吐き出して更新させるなどをしようと思いましたがうまく行きませんでした…Androidネイティブのディレクトリ構成やtaskのカスタムに詳しければどうにかできるのかな?と思っています。
Kotlin/Nativeを使えば基本的に言語はKotlinひとつに統一できますし、共通処理やOS依存処理も問題ないのではない気がしています。個人的にKotlinでUIKitなどもimportして使えることに驚きました。
何にせよ扱う言語は少ないに限ると思っていますのでKotlin/Nativeは良いものだと思います。ただ現在betaなので書き方や吐き出し方が変わる可能性は高いです。

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

UnityでのVSCodeの導入手順とおすすめ設定、拡張機能(Mac)

はじめに

Unityを使う際、デフォルトではスクリプトエディタとしてVisual Studioが設定されていますが、「VSCode便利だよ」と先輩エンジニアの方に勧めて頂いたので導入してみました。結果、色々カスタマイズできて便利だったので、備忘録として導入手順とおすすめ設定をまとめてみました。

VSCodeのインストール

下のリンクからダウンロードし、インストールする。
Download Visual Studio Code

Unityの設定

デフォルトのスクリプトエディタをVSCodeに変更する

[Unity] → [Preferences] → [External Tools] → [External Script Editor] → [Browse]
finderが開くので「Visual Studio Code.app」を探してきて選択する。

[External Script Editor]に「Code」と表示されていればOK。
スクリーンショット 2019-05-02 3.27.56.png

VSCodeのおすすめ設定と拡張機能

設定

自動保存

[File] → [Auto Save]にチェックをつける。

自動整形

[Code] → [Prefarences] → [Settings]
で設定画面を開く
下記3つの項目にチェックをつける。

・Format On Paste
→ペースト時に自動でフォーマット
・Format On Save
→ファイル保存時に自動でフォーマット(自動保存では整形してくれないので、手動で「cmd+S」する必要あり)
・Format On Type
→入力した行を自動でフォーマット

また、後述の拡張機能「C# FixFormat」をインストールする。
これを入れて置かないと自動整形が働かないので注意。

ミニマップを非表示

横に出てくるやつです。個人的にいらなかったので非表示にしました。

[Code] → [Prefarences] → [Settings]
で設定画面を開く。
以下の項目のチェックを外す
・Editor › Minimap: Enabled


VS Codeのミニマップの表示/非表示を切り替えるには

.metaファイルを非表示

デフォルトだと.metaファイルが表示されて邪魔なので非表示にします。

[Code] → [Prefarences] → [Settings]
で設定画面を開く。

・Files:Exclude

の項目に以下を追加してOKを押す。

**/*.meta

スクリーンショット 2019-05-04 21.34.17.png

拡張機能

C#

必須。C#が使えるようになる。

C# FixFormat

C#の自動整形ができるようになる。

Japanese Language Pack for Visual Studio Code

VSCodeの日本語化。

vscode-icons

ファイルとかフォルダにアイコンがついて見やすくなる。

Bracket Pair Colorizer

メソッドとかの{}を階層毎に色分けしてくれる。

zenkaku

コードに混ざった全角をわかりやすくしてくれる。

Debugger for Unity

デバッガー機能が使えるようになる。
image.png

C# XML Documentation Comments

sammaryを一瞬で表示できるようになる。

MonoBehaviour Snippets

Startメソッドとかを一瞬で書けるようになる。

Classy Naming

変数を新しく作るときに、変数名の候補を表示してくれる。

C# Extensions

C#のクラスを作れたりとか色々できる。

Rainbow CSV

csvを列ごとに色分けしてくれる。

参考

今日からUnity + Visual Studio Codeを用いた快適な開発生活(随時更新中)
VSCodeのオススメ拡張機能 24 選 (とTipsをいくつか)
VS CodeでUnityプログラミングしてる僕が入れてる拡張機能

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

ml-agents 0.8.0 で自分のプロジェクトで機械学習させる (Windows)(Tensorflow-GPU導入編)

前段

Macでのml-agents導入はこちらを参照してほしい。

今回はWindows用、それもtensorflow-gpu を使ってやりたい。基本的に以下の本家のページの通りだが

https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Installation-Windows.md

ハマリポイントがいくつかあったので、それには注意を促したい、というのがこの記事の趣旨だ。
あと1年後は100%忘れる自信がある私自身のためのものでもある。

環境設定

1、 ml-agents をダウンロード

  https://github.com/Unity-Technologies/ml-agents/tags/0.8.0
  をダウンロードして、適当なところに配置

2、 anaconda をインストール

  ターミナルで「conda」と打って反応があれば既にインストール済み

3、 仮想環境を作る

conda info -e

 で[ml-agents]があれば良い。なければ↓でつくる。

conda create -n ml-agents python=3.6

 で仮想環境を作る(なんか聞かれたら「y」と入力)

conda activate ml-agents

 で仮想環境切り替え。

4、 CUDA toolkit のインストール

  Unity ML-agentsドキュメントによると、CUDA toolkitのバージョンは「9.0.176」限定であるらしいので、それをダウンロードする。ダウンロードサイト直リンク

5、cuDNN library のインストール

  • NVIDIAサイトでcuDNNのサイトに行って、ダウンロードの手続きをする。ディベロッパー登録やらアンケートやらをやる必要がある。(こちらもCUDA toolkit 同様、バージョンが限定されているので要注意。「7.0.5」らしい。ダウンロードサイト直リンク )
  • ダウンロードしたzipを展開すると「bin」「include」「lib」フォルダができるので、それをCUDA toolkitのインストール先であるC:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0に配置する。

6、環境変数の設定

  CUDA_HOME という環境変数を新規に作り、

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0

  を設定する。
  次に、Path 環境変数に、以下の二つを追加する。

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\lib\x64
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\extras\CUPTI\libx64

(Unity ML-agentsドキュメントには「関連するパスを置き換えろ」と書いてあるが、CUDA toolkit インストール時に書き加えられたパスを消してはいけないので注意が必要)
以下の感じにパスが張っていればOK。
スクリーンショット_2019-05-02_00_34_12.png

7、tensorflow-gpu のインストール

 3で作った仮想環境で

pip install tensorflow-gpu==1.7.1

とやって tensorflow-gpu を仮想環境にインストール。
確認のために、

python

とやって、pythonを起動後、

import tensorflow as tf
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))

で、tensorflow-gpu が起動するのを試してみる。

Found device 0 with properties ...

とかなんとか出れば成功。出てなければ、tensorflow-gpu がインストールできていない可能性がある。

8、ML-Agents が使うライブラリをインストール

  ★★★ここで注意★★★
  このままML-Agents の使うライブラリをインストールしようとすると、せっかくいれたtensorflow-gpu に 通常のCPUを使う tensorflow が上書きインストールされてしまう。
なので、ml-agents/setup.py を以下のように編集する必要がある。

setup.py
      :
    packages=['mlagents.trainers'],  # Required
    zip_safe=False,

    install_requires=[
        'mlagents_envs==0.8.0',
#        'tensorflow>=1.7,<1.8', # ←ここをコメントをしておく
        'Pillow>=4.2.1',
        'matplotlib',
        'numpy>=1.13.3,<=1.14.5',
        'jupyter',
      :

そして、改めて以下を実行して ml-agents のライブラリをインストールする。

cd ml-agents-envs
pip install -e .
cd ..
cd ml-agents
pip install -e .
cd ..

確認のために

mlagents-learn

とやってみてちゃんとUnityロゴのアスキーアートが出ていれば成功。
スクリーンショット_2019-05-02_00_56_21.png

念の為、先ほどのPythonを動かしてみて

import tensorflow as tf
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))

で、tensorflow-gpu が正常に動いていることを確認する。(たまにCPUに切り替わってたりするので要注意)

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

Substance Painter で読み込んだNormal mapの上下が逆転している際の対処法

Substance Painter のNormal map読み込みについて

Substance Painterでは外部で作成したNormal mapをインポートして使う事ができます。しかし、しばしば読み込んだNormal mapのY方向が逆転していることがあったので、この対処方法を共有します。
SP_nor_06.jpg

Normal mapの上下が逆転する原因

Normal mapにはOpenGL方式DirectX方式があり、Y方向を示すGチャンネルの表現が逆となっています。なおUnityのNormal mapはOpenGL方式です。
Substance Painterでは外部から読み込んだNormal mapをレイヤーにアサインした場合にこの方式を自動で判別しますが、これが間違っている場合に上下が逆に表示されてしまうようです。
SP_nor_07.jpg

Substance Painter での修正方法

Substance Painterでの修正は簡単ですが、設定場所が少しわかりにくいかもしれません。
1.Normal mapイメージを適用したレイヤーのPROPERTIESを開きます
2.Normal欄の右下にある小さな▽をクリックします
3.開いた小ウインドウの二段目右をクリックします(これ以外の設定項目はありません)
4.開いたリストからOpenGL normalDirect3D Normalの正しく表示される方を選択します
SP_nor_08.jpg

Photoshopでの修正方法

Substance Painterを使わずに単にNormal mapの上下を反転させたい場合は、PhotoshopでNormal map画像のGチャンネルを選択し、イメージ>色調補正>階調の反転とする事で修正できます。Photoshopの場合は画像の上書きが必要ですが、Substance Painterは非破壊で修正できるところが利点です。

まとめ

Normal方向の反転はSubstance Painterのごく基本機能ですが、少しわかりにくい場所にあると感じたので記事にしました。

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