- 投稿日:2020-05-30T22:35:51+09:00
VRoidの服をVCIで着替える
概要
VRoidの服をVCIで着替えてみました。
inバーチャルキャスト見た目だけは、ぽい感じになった気がします。 pic.twitter.com/WUqeYTXQs1
— 120 (@120byte) May 30, 2020バージョン
Unity : 2019.3.0f6
UniVCI : 0.27
UniVRM : 0.55
バーチャルキャスト : 1.9.2dUnity完結式の手動作成手順
準備
VRM取り込み
VRMのオブジェクトにVCI Objetcを追加
不要メッシュ等の削除or透過(ホントは全て削除したい)
主要ボーンをVCI Objectの直下へ引っ張り出す●主要ボーンのオブジェクトへ以下を追加
・VCI Sub Item
・Rigidbody
・VCI Attachable
・Box Cllider全部位設定
●VCI Sub Item
・GrabbableをOnに設定
・ScalableをOnに設定
・Group Idを1に設定
※VCI Sub Itemは手動だと強制個別なので要気合●Rigidbody
・Use GravityをOffに設定
・Is KinematicをOnに設定●VCI Attachable
・Sizeを1に設定
・Distanceを0.05に設定●Box Cllider
・Sizeを0.1に設定
・Is TriggerをOnに設定個別部位設定
各VCI AttachableのElementを対応する部位ごとに設定
●ChestのBox Clliderだけ
・Centerを0, 0.1, 0に設定
・Sizeを0.2に設定
※この部位の大きさの違いが目立つので、調整しやすいように大きくしておく●HandのBox Clliderだけ
・Sizeを0に設定
※着た後に強制選択状態になってしまうので対策luaコード
VCI ObjetcのScriptsに以下を設定
local Attached = false function onUse(use) local owner = vci.studio.GetOwner() -- 体幹 SetAtt(owner, "Hips", "J_Bip_C_Hips", Attached) SetAtt(owner, "Spine", "J_Bip_C_Spine", Attached) SetAtt(owner, "Chest", "J_Bip_C_Chest", Attached) -- 足 SetAtt(owner, "LeftUpperLeg", "J_Bip_L_UpperLeg", Attached) SetAtt(owner, "RightUpperLeg", "J_Bip_R_UpperLeg", Attached) SetAtt(owner, "LeftLowerLeg", "J_Bip_L_LowerLeg", Attached) SetAtt(owner, "RightLowerLeg", "J_Bip_R_LowerLeg", Attached) SetAtt(owner, "LeftFoot", "J_Bip_L_Foot", Attached) SetAtt(owner, "RightFoot", "J_Bip_R_Foot", Attached) -- 腕 SetAtt(owner, "LeftUpperArm", "J_Bip_L_UpperArm", Attached) SetAtt(owner, "RightUpperArm", "J_Bip_R_UpperArm", Attached) SetAtt(owner, "LeftLowerArm", "J_Bip_L_LowerArm", Attached) SetAtt(owner, "RightLowerArm", "J_Bip_R_LowerArm", Attached) SetAtt(owner, "LeftHand", "J_Bip_L_Hand", Attached) SetAtt(owner, "RightHand", "J_Bip_R_Hand", Attached) Attached = not Attached end function SetAtt(owner, boneName, itemName, attached) local bone = owner.GetBoneTransform(boneName) local item = vci.assets.GetSubItem(itemName) if bone ~= nil and item ~= nil then -- 位置と回転の合わせ item.SetPosition(bone.position) item.SetRotation(bone.rotation) -- 脱着 if attached then item.DetachFromAvatar() else item.AttachToAvatar() end end end備考
VCI Attachableを有効にするには通常のClliderが必須(更にGrabbableOnも必須)
AttachToAvatarする時の位置合わせは同期が必要かと思ったけど、特に何もしなくても良さそう
服のサイズを着るアバターでVRM化してから作業すればサイズは丁度
素体側ではみ出やすい部位は透過すると良いかも
今回のバージョンではGetAvatarsによるゲストのTransform取得が動かない?(ので他の人に着せられない)
変換ツール作成予定→できた(https://120byte.booth.pm/items/2115099)
- 投稿日:2020-05-30T21:32:22+09:00
UnityでGoogle Play Game Services導入する際、あらゆる罠にハマった話
UnityプロジェクトにGoogle Play Game Servicesを導入した際、いろいろ罠にはまって24時間くらい無駄にしたので、ここに何が発生してどうやって解決したかメモしておきます。
私の開発環境
- Unity 2018.4.10f1
- Google Play Game plugin for Unity v 0.10.09
- Android SDK level 28
macで作業しています。
動かしたいコード
Google Play Game Servicesプラグインを使って、プロジェクトにクラウドセーブ機能を導入しようとしています。
動かしたいコードは、サービスの初期化とプレイヤの認証です。var conf = new PlayGamesClientConfiguration.Builder() .EnableSavedGame() .Build(); PlayGamesPlatform.InitializeInstance(conf); PlayGamesPlatform.Activate(); Social.localPlayer.Authenticate( (res, msg) => { Debug.Log($"Result {res} : {msg}"); });ハマった罠たち
■ビルド時、ネームスペースGoogleが見つからない
●現象
Googleというネームスペースが見つからずにエラーになる。
Assets/GooglePlayGames/Editor/GPGSAndroidSetupUI.cs(118,17): error CS0103: The name 'Google' does not exist in the current context
●原因
バッチビルドのオプションでパッケージマネージャを使わないようにしてるのが原因です。
●解決方法
-noUpmオプションを外して、パッケージマネージャを使うようにします。
$UNITY -quit -noUpm -batchmode -logfile ./build.log -username $USERNAME -password $PASSWORD -executeMethod AndroidBuildRelease↓
$UNITY -quit -batchmode -logfile ./build.log -username $USERNAME -password $PASSWORD -executeMethod AndroidBuildRelease■ビルド時、Proguard (R8)でエラーが発生する
●現象
設定ファイルは正しいはずなのに、Proguardが文法エラーで止まる。
/path/to/src/proguard-user.txt:2:2: D8: Expected char '-' at /path/to/src/proguard-user.txt:1:1 -keep class com.google.android.gms.games.multiplayer.** { *; }●原因
progurad-user.txt にBOMがついているためエラーになります。
●解決方法
proguard-user.txtのBOMを取ります。また、AssetImporterでテキストを全てBOM付きに変更しているプロジェクトでは、このファイルを対象外にするように修正を加えます。
■ビルド時、support-v4周りでコンパイルエラーがでる
●現象
ビルドすると
Program type already present: android.support.v4.なんとか
というエラーが発生する。●原因
GPGSではandroidxで提供されているv4サポートを使っているためです。その他のプラグインでandroid.support.v4系のパッケージを利用しているとこのエラーが発生します。
●解決方法
android.support.v4 はバージョン28で終了なので androidxを使うようにします。でも、自分で書いたコードだったら直せますが、外部のライブラリがこの辺を要求しているとなかなか対応が面倒ですね。
■ClassNotFoundExceptionが発生する
●現象
APKを実行するとClassNotFoundExceptionを吐いて止まる。
Exception class not found com.google.android.gms.games.Games
●原因
これには以下の要因があります。
- Assets/Plugins/Android以下にサービス関連のaarファイルが配置されていないと発生します。
- ProguardによってGPGS関連のクラス名が変更されると発生します。
●解決方法
* 1. GPGS関連のaarを配置する
プラグインを導入すると、パッケージマネージャにレジストリを加えてGPGS関連のaarがインストールされるようになっています。
ここで問題がでるのは主に開発環境のjava関連が理由かと思われます。
- javaがインストールされていなければインストールする
- パスを通すか、パスの通ったディレクトリにjavaを置く。 /usr/bin/java があれば問題ないはず
- gradleがインストールされていなければインストールする (未確認)
- Unityエディタで
Assets > External Dependency Manager > Android Resolver > Force Resolve
を実行する* 2. Proguard関連でリネームされないようにする
クラス名が変更されないように、ここらへんに書いてある内容を設定するか、難読しないようにします。
前述しましたが、Proguardの設定を追加する場合はファイルにBOMがつかないようにします。■おかえりポップアップが表示されない
●現象
正式名称を何と言うのか分かりませんが、アプリを実行した際に表示されるはずのおかえりなさいポップアップが表示されない。
●原因
これには以下のような要因があります。
- バンドルIDを間違えている
- app idを間違えている
●解決方法
* 1. バンドルIDを正しいものにする
Google Play Consoleでゲームサービスに登録しているバンドルIDと、APKのものとを合わせるようにします。
* 2. app idを正しいものにする
Unityエディタの
Window > Google Play Games > Android setup
でダイアログを開き、Resource Definitionで登録するXMLを確認します。<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_id" translatable="false">ここにapp idを記述する</string> <string name="package_name" translatable="false">ここにバンドルIDを記述する</string> </resources>app id はGoogle Play Consoleの
ゲームサービス > ゲームの詳細
に書いてある11桁の数値です。■プレイヤー認証に失敗する
●現象
device errorやcancel authentication といったエラーで、Social.localPlayer.Authenticate が常に失敗する。
●原因
これには以下のような要因があります。
- SHA1フィンガープリントが間違っている
- SavedGame の設定がオフになっている
●解決方法
* 1. SHA1フィンガープリントを修正する
アプリのSHA1フィンガープリントを確認します。署名の方法によって2パターンあります。
A) Google Play App Signingを使っている場合
Google Play Consoleのアプリの詳細画面からリリース管理>アプリの署名
で確認します。B) ビルド時にキーストアで署名している場合
下記コマンドで表示されるSHA1フィンガープリントを確認します。keytool -list -keystore キーストアのパス -vつぎに https://console.developers.google.com でゲームサービス側に登録されているフィンガープリントを確認します。
上記サイトからサービスを選び、認証情報>Oauth2.0 クライアント ID
のなかから、アプリを選んで編集画面に入ると確認できます。
アプリとサービスのSHA1フィンガープリントを合わせるように、どちらかもしくは両方を修正します。* 2. SavedGameの設定をオンにする
Google Play Consoleのゲームサービスでアプリを選び、ゲームの詳細を表示します。SavedGameの設定項目があるのでONにします。
保存済みゲームというのはSavedGameの翻訳ですが、これ紛らわしいですね。「SavedGameを有効にする」という感じの表記にしてほしいです。
最後に
iOSのGameCenterは簡単だったのでGPGSも楽勝だろうと思って舐めていたら、これらの罠を全部踏むと言う有様でした。UnityにGoogle Play Game Serviceを導入するための日本語情報は多少ありますが、トラブルシュートのようなものがないんですよね。
ここに書いたのは自分のための備忘録なのですが、もしだれかが同様につまづくことがあったとき、これが参考になればいいなと思います。
- 投稿日:2020-05-30T18:48:25+09:00
Unityでマウスの位置に画像(guiのimage)を表示させる
Unityでマウスの位置に画像(guiのimage)を表示させる
guiのimageを使ってマウスポインターの代わりに画像を表示させる
画像からアニメーションにも応用できるはず
用意するもの
・Windows PC
・Unity (制作時に使用したバージョンは2019)
・マウスの位置に表示させたい画像作りたいもの
黒い丸がマウスポインタ—に追従している。
これはわかりやすくするためにマウスポインターを表示している。作りたかた
1.HierarchyのプラスボタンからUI > ImageからCanvasとImageオブジェクトを作る。
2.Imageに入れる画像をTexture TypeをSprite(2D and UI)にし、ImageのSource Imageに入れる。
3.Imageのオブジェクト名を「MouseImage」に変更する。
4.HierarchyのプラスボタンからCreate Emptyで空のオブジェクトを作る、オブジェクト名を「MouseManager」に変更する。
5.下記のスクリプトをC#のファイルで作り、MouseManagerオブジェクトに入れる。
完成スクリプト
MousePointerpos.C#//画像 public Image Mouse_Image; //Canvasの変数 public Canvas canvas; //キャンバス内のレクトトランスフォーム public RectTransform canvasRect; //マウスの位置の最終的な格納先 public Vector2 MousePos; // Start is called before the first frame update void Start() { //マウスポインター非表示 Cursor.visible = false; //HierarchyにあるCanvasオブジェクトを探してcanvasに入れいる canvas = GameObject.Find("Canvas").GetComponent<Canvas>(); //canvas内にあるRectTransformをcanvasRectに入れる canvasRect = canvas.GetComponent<RectTransform>(); //Canvas内にあるMouseImageを探してMouse_Imageに入れる Mouse_Image = GameObject.Find("MouseImage").GetComponent<Image>(); } // Update is called once per frame void Update() { /* * CanvasのRectTransform内にあるマウスの位置をRectTransformのローカルポジションに変換する * canvas.worldCameraはカメラ * 出力先はMousePos */ RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRect, Input.mousePosition, canvas.worldCamera, out MousePos); /* * Mouse_Imageを表示する位置にMousePosを使う */ Mouse_Image.GetComponent<RectTransform>().anchoredPosition = new Vector2(MousePos.x, MousePos.y); }参考文献
ぐーるらいふ 遊びのunityのメモ帳。敗北者の末路。
【Unity】タッチした位置にuGUI(RectTransform)を表示する
https://ghoul-life.hatenablog.com/entry/2018/11/13/000955
2020年5月30日閲覧Unity DOCUMENTATION
RectTransformUtility .ScreenPointToLocalPointInRectangle
https://docs.unity3d.com/ScriptReference/RectTransformUtility.ScreenPointToLocalPointInRectangle.html
2020年5月30日閲覧
- 投稿日:2020-05-30T18:11:30+09:00
Unityの標準機能だけでTexturePackerを作ってテクスチャアトラスを用意する
動作環境
- Windows10
- Unity2018.4.22f1
記事の作成にあたり使用したアセット(無料)
Asset StoreからSunny Landという2Dのプレイヤー画像を使用させていただきました。
こちらのかわいい複数枚のキツネをUnityの標準機能だけでテクスチャアトラスにします。処理を始める前に…
画像をパックする前に対象となるテクスチャアセットの
Read/Write Enabled
にチェックを入れておく必要があります。
この項目にチェックが入っていないとTexture2D 関数からテクスチャデータにアクセスができないので画像をパックできません。
実装内容
TexturePacker.csprivate static void Pack(string filename, Texture2D[] resources, int maxsize) { // 1.複数枚の画像を1つにパックする var texture = new Texture2D(maxsize, maxsize, TextureFormat.RGBA32, false); var rect = texture.PackTextures(resources, 4, maxsize, false); File.WriteAllBytes(Application.dataPath + filename, texture.EncodeToPNG()); AssetDatabase.ImportAsset("Assets" + filename); // 2.SpriteのMultiple設定をパックした画像から作成 var spritesheets = new List<SpriteMetaData>(); for (var index = 0; index < resources.Length; index++) { var data = new SpriteMetaData(); data.name = resources[index].name; var x = rect[index].x * texture.width; var y = rect[index].y * texture.height; var w = rect[index].width * texture.width; var h = rect[index].height * texture.height; data.rect = new Rect(x, y, w, h); spritesheets.Add(data); } // 3.作成した情報をもとに画像をAtlas化 var importer = AssetImporter.GetAtPath("Assets" + filename) as TextureImporter; importer.textureType = TextureImporterType.Sprite; importer.spriteImportMode = SpriteImportMode.Multiple; importer.spritesheet = spritesheets.ToArray(); AssetDatabase.ImportAsset("Assets" + filename); }解説
1. 複数枚の画像を1つにパックする
動的に画像を生成してPackTextures関数にTexture2D 配列を渡すことで自動的にパックしてくれます。
ただ、ここまでだと1枚の画像を作っただけです。テクスチャアトラスとして使うためには戻り値のRect型が必要になります。
2. SpriteのMultiple設定をパックした画像から作成
画像をMultipleに設定することでパックした画像の配置とサイズを設定できます。
そのためにSpriteMetaDataクラスへPackTextures関数から返ってきたRect型の情報を割り当てて配列を用意しておきます。3. 作成した情報をもとに画像をアトラス化
ここからがパックした画像をアトラス化する方法です。
まずTextureImporterクラスで生成したパック画像をエディターで読み込みます。
※画像を読み込むためにAssetDatabase.ImportAsset関数で画像を生成した後にインポートしておく必要があります。
読み込むことができたらTexture Type
をSpriteに、Sprite Mode
をMultipleにします。
最後に、用意しておいたSpriteMetaData型の配列をspritesheetに設定したら完成です。
おわりに
Unityの標準機能だけでテクスチャアトラスを用意することができました。
ここまでならTexturePackerを使わなくてもいいのでは?とも思われそうですが、Unityで画像を作成するからこそ発生するデメリットがあります。
そのデメリットとはTexture2Dで指定できる最大サイズが限定的なので、必ず画像に余白ができることです。
PackingTexture関数が画像をパッキングするタイミングで自動的に32のべき乗のサイズが設定されます。
その点、TexturePackerを使うと画像サイズは最適化されて余白が生まれません。
Unityを使用しないプロジェクトであればTexturePackerだけでいいのかもしれないですね。
- 投稿日:2020-05-30T11:37:14+09:00
Unityライセンスを3台目以降に登録する手順
Unity Pro/Unity Plusのライセンス 1つにつき「1人」のユーザーが同時に「2台」までのPCにUnityをインストールして使用することができる。
3台目のPCでアクティベーションしたい場合は、他のPCのアクティベーションを解除してから、アクティベートする必要がある。
(PCを買い替えた時のメモです)アクティベーション解除
管理ページに移動
https://unity.com/
My Account > My Seats
該当ライセンスの左にある歯車アイコンをクリック
アクティベーションされているPC一覧が表示されるので、
解除したいPCを選択して「Remove selected activations」をクリック
3台目のPCにてアクティベーションする
- 投稿日:2020-05-30T11:11:36+09:00
【Unity】Destroy()とDestroyImmediate()を使い分けなくていいようにする
はじめに
Unityのエディタ拡張など非再生時に動くものを作ってると
Destroy()
とDestroyImmediate()
を使い分けるのが地味に面倒なので、意識しなくてもいいようにします。拡張メソッドを足す
ObjectExtensions.csusing UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif public static class ObjectExtensions { public static void Destroy(this Object self) { #if UNITY_EDITOR if (EditorApplication.isPlaying == false) { GameObject.DestroyImmediate(self); } else #endif { GameObject.Destroy(self); } } }// Before #if UNITY_EDITOR if (EditorApplication.isPlaying == false) { GameObject.DestroyImmediate(go); } else #endif { GameObject.Destroy(go); } // After go.Destroy();