20200530のUnityに関する記事は6件です。

VRoidの服をVCIで着替える

概要

VRoidの服をVCIで着替えてみました。
inバーチャルキャスト

バージョン

Unity : 2019.3.0f6
UniVCI : 0.27
UniVRM : 0.55
バーチャルキャスト : 1.9.2d

Unity完結式の手動作成手順

image.png

準備

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)

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

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

●原因

これには以下の要因があります。

  1. Assets/Plugins/Android以下にサービス関連のaarファイルが配置されていないと発生します。
  2. 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がつかないようにします。

■おかえりポップアップが表示されない

●現象

正式名称を何と言うのか分かりませんが、アプリを実行した際に表示されるはずのおかえりなさいポップアップが表示されない。

●原因

これには以下のような要因があります。

  1. バンドルIDを間違えている
  2. 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 が常に失敗する。

●原因

これには以下のような要因があります。

  1. SHA1フィンガープリントが間違っている
  2. 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にします。

スクリーンショット 2020-05-30 20.29.35.png

保存済みゲームというのはSavedGameの翻訳ですが、これ紛らわしいですね。「SavedGameを有効にする」という感じの表記にしてほしいです。

最後に

iOSのGameCenterは簡単だったのでGPGSも楽勝だろうと思って舐めていたら、これらの罠を全部踏むと言う有様でした。UnityにGoogle Play Game Serviceを導入するための日本語情報は多少ありますが、トラブルシュートのようなものがないんですよね。
ここに書いたのは自分のための備忘録なのですが、もしだれかが同様につまづくことがあったとき、これが参考になればいいなと思います。

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

Unityでマウスの位置に画像(guiのimage)を表示させる

Unityでマウスの位置に画像(guiのimage)を表示させる

guiのimageを使ってマウスポインターの代わりに画像を表示させる

画像からアニメーションにも応用できるはず

用意するもの

・Windows PC
・Unity (制作時に使用したバージョンは2019)
・マウスの位置に表示させたい画像

作りたいもの

Rec_20181224_181408_20200530_175000.gif
黒い丸がマウスポインタ—に追従している。
これはわかりやすくするためにマウスポインターを表示している。

作りたかた

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オブジェクトに入れる。
完成

image.PNG
manager.PNG

スクリプト

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日閲覧

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

Unityの標準機能だけでTexturePackerを作ってテクスチャアトラスを用意する

動作環境

  • Windows10
  • Unity2018.4.22f1

記事の作成にあたり使用したアセット(無料)

Asset StoreからSunny Landという2Dのプレイヤー画像を使用させていただきました。
0.PackingTargets.jpg
こちらのかわいい複数枚のキツネをUnityの標準機能だけでテクスチャアトラスにします。

処理を始める前に…

画像をパックする前に対象となるテクスチャアセットのRead/Write Enabledにチェックを入れておく必要があります。
この項目にチェックが入っていないとTexture2D 関数からテクスチャデータにアクセスができないので画像をパックできません。
2.Checkit.jpg

実装内容

TexturePacker.cs
    private 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型が必要になります。
1.PackingTexture.jpg

2. SpriteのMultiple設定をパックした画像から作成

画像をMultipleに設定することでパックした画像の配置とサイズを設定できます。
そのためにSpriteMetaDataクラスへPackTextures関数から返ってきたRect型の情報を割り当てて配列を用意しておきます。

3. 作成した情報をもとに画像をアトラス化

ここからがパックした画像をアトラス化する方法です。
まずTextureImporterクラスで生成したパック画像をエディターで読み込みます。
※画像を読み込むためにAssetDatabase.ImportAsset関数で画像を生成した後にインポートしておく必要があります。
読み込むことができたらTexture TypeをSpriteに、Sprite ModeをMultipleにします。
最後に、用意しておいたSpriteMetaData型の配列をspritesheetに設定したら完成です。
3.TextureAtlas.jpg

おわりに

Unityの標準機能だけでテクスチャアトラスを用意することができました。
ここまでならTexturePackerを使わなくてもいいのでは?とも思われそうですが、Unityで画像を作成するからこそ発生するデメリットがあります。
そのデメリットとはTexture2Dで指定できる最大サイズが限定的なので、必ず画像に余白ができることです。
x32.jpg
PackingTexture関数が画像をパッキングするタイミングで自動的に32のべき乗のサイズが設定されます。
その点、TexturePackerを使うと画像サイズは最適化されて余白が生まれません。
Unityを使用しないプロジェクトであればTexturePackerだけでいいのかもしれないですね。

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

Unityライセンスを3台目以降に登録する手順

Unity Pro/Unity Plusのライセンス 1つにつき「1人」のユーザーが同時に「2台」までのPCにUnityをインストールして使用することができる。
3台目のPCでアクティベーションしたい場合は、他のPCのアクティベーションを解除してから、アクティベートする必要がある。
(PCを買い替えた時のメモです)

アクティベーション解除

管理ページに移動
https://unity.com/
0.png

My Account > My Seats
該当ライセンスの左にある歯車アイコンをクリック
1.png

Serial key 部分をクリック
2.png

アクティベーションされているPC一覧が表示されるので、
解除したいPCを選択して「Remove selected activations」をクリック
3.png

3台目のPCにてアクティベーションする

Unity Hub を起動して、画面下の「ライセンスを管理」をクリック
4.png

「新規ライセンスの認証」をクリック
5.png

シリアル番号を入力して実行をクリック
6.png

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

【Unity】Destroy()とDestroyImmediate()を使い分けなくていいようにする

はじめに

Unityのエディタ拡張など非再生時に動くものを作ってるとDestroy()DestroyImmediate()を使い分けるのが地味に面倒なので、意識しなくてもいいようにします。

拡張メソッドを足す

ObjectExtensions.cs
using 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();
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む