質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.38%

  • Android

    7510questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

  • Unity3D

    1926questions

    Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

  • MRTK(Mixed Reality Toolkit)

    2questions

UnityをAndroidデバイスで実行したが3Dモデルが動かない

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 79

misimaso

score 2

実機にBuild and Run すると動作しなくなる

Unity内でplayしたら正常に動作するのものが、Miragesolo with Daydream というデバイスにBuild and Run すると動かなくなります。
私と同じ症状になって解決された方はございませんか。

 実行したいこと

3Dモデルを躍らせることです。
しかし、アニメーションコントローラーなどは使わない特殊なやり方になっています。

①OpenPoseによって人物が映っている動画から腕や足の関節座標データを収集、可視化。
②3d-pose-baselineによってOpenPoseの関節座標をテキストファイル化します。
③できたテキストファイルをUnity内でテキストアセットとし、以下のscriptで読み込んで3Dモデルに関節座標を反映させる。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;

// pos.txtのデータ
// https://github.com/miu200521358/3d-pose-baseline-vmd/blob/master/doc/Output.md
// 0 :Hip
// 1 :RHip
// 2 :RKnee
// 3 :RFoot
// 4 :LHip
// 5 :LKnee
// 6 :LFoot
// 7 :Spine
// 8 :Thorax
// 9 :Neck/Nose
// 10:Head
// 11:LShoulder
// 12:LElbow
// 13:LWrist
// 14:RShoulder
// 15:RElbow
// 16:RWrist

public class Pos_txt_Reader : MonoBehaviour
{
    float scale_ratio = 0.001f;  // pos.txtとUnityモデルのスケール比率
                                 // pos.txtの単位はmmでUnityはmのため、0.001に近い値を指定。モデルの大きさによって調整する
    float heal_position = 0.05f; // 足の沈みの補正値(単位:m)。プラス値で体全体が上へ移動する
    float head_angle = 15f; // 顔の向きの調整 顔を15度上げる

    public String pos_filename; // pos.txtのファイル名
    public Boolean debug_cube; // デバッグ用Cubeの表示フラグ
    public int start_frame; // 開始フレーム
    public String end_frame; // 終了フレーム  
    float play_time; // 再生時間 
    Transform[] bone_t; // モデルのボーンのTransform
    Transform[] cube_t; // デバック表示用のCubeのTransform
    Vector3 init_position; // 初期のセンターの位置
    Quaternion[] init_rot; // 初期の回転値
    Quaternion[] init_inv; // 初期のボーンの方向から計算されるクオータニオンのInverse
    List<Vector3[]> pos; // pos.txtのデータを保持するコンテナ
    int[] bones = new int[10] { 1, 2, 4, 5, 7, 8, 11, 12, 14, 15 }; // 親ボーン
    int[] child_bones = new int[10] { 2, 3, 5, 6, 8, 10, 12, 13, 15, 16 }; // bonesに対応する子ボーン
    int bone_num = 17;
    Animator anim;
    int s_frame;
    int e_frame;

    // pos.txtのデータを読み込み、リストで返す
    List<Vector3[]> ReadPosData(string filename) {
        List<Vector3[]> data = new List<Vector3[]>();

        List<string> lines = new List<string>();
        StreamReader sr = new StreamReader(filename);
        while (!sr.EndOfStream) {
            lines.Add(sr.ReadLine());
        }
        sr.Close();

        foreach (string line in lines) {
            string line2 = line.Replace(",", "");
            string[] str = line2.Split(new string[] { " " }, System.StringSplitOptions.RemoveEmptyEntries); // スペースで分割し、空の文字列は削除

            Vector3[] vs = new Vector3[bone_num];
            for (int i = 0; i < str.Length; i += 4) {
                vs[(int)(i/4)] = new Vector3(-float.Parse(str[i + 1]), float.Parse(str[i + 3]), -float.Parse(str[i + 2]));
            }
            data.Add(vs);
        }
        return data;
    }

    // BoneTransformの取得。回転の初期値を取得
    void GetInitInfo()
    {
        bone_t = new Transform[bone_num];
        init_rot = new Quaternion[bone_num];
        init_inv = new Quaternion[bone_num];

        bone_t[0] = anim.GetBoneTransform(HumanBodyBones.Hips);
        bone_t[1] = anim.GetBoneTransform(HumanBodyBones.RightUpperLeg);
        bone_t[2] = anim.GetBoneTransform(HumanBodyBones.RightLowerLeg);
        bone_t[3] = anim.GetBoneTransform(HumanBodyBones.RightFoot);
        bone_t[4] = anim.GetBoneTransform(HumanBodyBones.LeftUpperLeg);
        bone_t[5] = anim.GetBoneTransform(HumanBodyBones.LeftLowerLeg);
        bone_t[6] = anim.GetBoneTransform(HumanBodyBones.LeftFoot);
        bone_t[7] = anim.GetBoneTransform(HumanBodyBones.Spine);
        bone_t[8] = anim.GetBoneTransform(HumanBodyBones.Neck);
        bone_t[10] = anim.GetBoneTransform(HumanBodyBones.Head);
        bone_t[11] = anim.GetBoneTransform(HumanBodyBones.LeftUpperArm);
        bone_t[12] = anim.GetBoneTransform(HumanBodyBones.LeftLowerArm);
        bone_t[13] = anim.GetBoneTransform(HumanBodyBones.LeftHand);
        bone_t[14] = anim.GetBoneTransform(HumanBodyBones.RightUpperArm);
        bone_t[15] = anim.GetBoneTransform(HumanBodyBones.RightLowerArm);
        bone_t[16] = anim.GetBoneTransform(HumanBodyBones.RightHand);

        // Spine,LHip,RHipで三角形を作ってそれを前方向とする。
        Vector3 init_forward = TriangleNormal(bone_t[7].position, bone_t[4].position, bone_t[1].position);
        init_inv[0] = Quaternion.Inverse(Quaternion.LookRotation(init_forward));

        init_position = bone_t[0].position;
        init_rot[0] = bone_t[0].rotation;
        for (int i = 0; i < bones.Length; i++) {
            int b = bones[i];
            int cb = child_bones[i];

            // 対象モデルの回転の初期値
            init_rot[b] = bone_t[b].rotation;
            // 初期のボーンの方向から計算されるクオータニオン
            init_inv[b] = Quaternion.Inverse(Quaternion.LookRotation(bone_t[b].position - bone_t[cb].position,init_forward));
        }
    }

    // 指定の3点でできる三角形に直交する長さ1のベクトルを返す
    Vector3 TriangleNormal(Vector3 a, Vector3 b, Vector3 c)
    {
        Vector3 d1 = a - b;
        Vector3 d2 = a - c;

        Vector3 dd = Vector3.Cross(d1, d2);
        dd.Normalize();

        return dd;
    }

    // デバック用cubeを生成する。生成済みの場合は位置を更新する
    void UpdateCube(int frame)
    {
        if (cube_t == null) {
            // 初期化して、cubeを生成する
            cube_t = new Transform[bone_num];

            for (int i = 0; i < bone_num; i++) {
                Transform t = GameObject.CreatePrimitive(PrimitiveType.Cube).transform;
                t.transform.parent = this.transform;
                t.localPosition = pos[frame][i] * scale_ratio;
                t.name = i.ToString();
                t.localScale = new Vector3(0.05f, 0.05f, 0.05f);
                cube_t[i] = t;

                Destroy(t.GetComponent<BoxCollider>());
            }
        }
        else {
            // モデルと重ならないように少しずらして表示
            Vector3 offset = new Vector3(1.2f, 0, 0);

            // 初期化済みの場合は、cubeの位置を更新する
            for (int i = 0; i < bone_num; i++) {
                cube_t[i].localPosition = pos[frame][i] * scale_ratio + new Vector3(0, heal_position, 0) + offset;
            }
        }
    }

    void Start()
    {
        anim = GetComponent<Animator>();
        play_time = 0;
        if (System.IO.File.Exists (pos_filename) == false) {
            Debug.Log("<color=blue>Error! Pos file not found(" + pos_filename + "). Check Pos_filename in Inspector.</color>");
        }
        pos = ReadPosData(pos_filename);
        GetInitInfo();
        if (pos != null) {
            // inspectorで指定した開始フレーム、終了フレーム番号をセット
            if (start_frame >= 0 && start_frame < pos.Count) {
                s_frame = start_frame;
            } else {
                s_frame = 0;
            }
            int ef;
            if (int.TryParse(end_frame, out ef)) {
                if (ef >= s_frame && ef < pos.Count) {
                    e_frame = ef;
                } else {
                    e_frame = pos.Count - 1;
                }
            } else {
                e_frame = pos.Count - 1;
            }
            Debug.Log("End Frame:" + e_frame.ToString());
        }
    }

    void Update()
    {
        if (pos == null) {
            return;
        }
        play_time += Time.deltaTime;

        int frame = s_frame + (int)(play_time * 30.0f);  // pos.txtは30fpsを想定
        if (frame > e_frame) {
            play_time = 0;  // 繰り返す
            frame = s_frame;
        }

        if (debug_cube) {
            UpdateCube(frame); // デバッグ用Cubeを表示する
        }

        Vector3[] now_pos = pos[frame];

        // センターの移動と回転
        Vector3 pos_forward = TriangleNormal(now_pos[7], now_pos[4], now_pos[1]);
        bone_t[0].position = now_pos[0] * scale_ratio + new Vector3(init_position.x, heal_position, init_position.z);
        bone_t[0].rotation = Quaternion.LookRotation(pos_forward) * init_inv[0] * init_rot[0];

        // 各ボーンの回転
        for (int i = 0; i < bones.Length; i++) {
            int b = bones[i];
            int cb = child_bones[i];
            bone_t[b].rotation = Quaternion.LookRotation(now_pos[b] - now_pos[cb], pos_forward) * init_inv[b] * init_rot[b];
        }

        // 顔の向きを上げる調整。両肩を結ぶ線を軸として回転
        bone_t[8].rotation = Quaternion.AngleAxis(head_angle, bone_t[11].position - bone_t[14].position) * bone_t[8].rotation;
    }
}


参考にさせていただいたサイト

エラー

miragesoloにBuild and Runした際に
Console画面にエラーメッセージは出ていませんが、唯一出ているメッセージは

Build completed with a result of 'Succeeded'
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)


です。これはエラー文ではないです。

補足情報・試したこと

Unity 2018.3.14f1(64-bit)
MiragesoloとUnityの接続参考にさせていただいたサイト
キューブを真横に動かすように設定してみたら、それは動きました。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • sakura_hana

    2019/06/19 18:54

    とりあえずデバッグ用のログを見て、原因箇所の特定が先決かなと思います。本体側のログが見れないなら一時的にUIを作ってそこに表示させる(もしくはOnGUIを利用する)等するとよいかと。

    今怪しそうなのは「pos_filename」でしょうか。エディタと実機ではアクセス出来る場所やその方法が異なります。「unity android 外部ファイル パス」辺りでググると参考になるかと思います。

    キャンセル

  • misimaso

    2019/06/21 15:18

    とても参考になります。
    ありがとうございます。
    試してみます。

    キャンセル

回答 1

0

Android上でエラーが発生しているために3Dモデルが想定している動作をしていない恐れがあります。
Application.dataPathなどを使用して正しいパスを指定されていますでしょうか?
PC用のみにパスを指定しているがために想定している動作結果が得られていないのではないでしょうか。
https://qiita.com/consolesoup/items/19fed212d4ef2bd1e1dd
実機上でログを取得してみて下さい。
Textコンポーネントを使えば実機上でもログがみられるはずです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/21 15:14

    ご回答ありがとうございます
    試してみます

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.38%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Android

    7510questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

  • Unity3D

    1926questions

    Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

  • MRTK(Mixed Reality Toolkit)

    2questions