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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Unity3D

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

Q&A

解決済

1回答

1557閲覧

UNITY ヒューマノイド型モデルの動きを同期させたい

Qoo

総合スコア1249

Unity3D

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

0グッド

0クリップ

投稿2019/06/25 07:10

本来は別々のオブジェクトを想定していますが、テストのため、unityちゃんモデル2体でテストしています。

シーン上にunityちゃんモデル2体を配置し(モデルA,B)、モデルAだけにアニメーションをつけています
この状態でアニメーションを実行した場合に、モデルBもモデルAと動きをさせたいので、各ボーンの位置が同じようになるように各ボーン分のパラメタを作成しスクリプトでモデルBのボーンの位置をモデルAの位置に合わせるように作ってみたのですが、まったく動作しません。

何が悪いのでしょうか。
アニメーション時は各ボーンの位置は取得できない?などあるのでしょうか??

スクリプトが長いのでキャプチャしてみました

あと、各ボーンの取得を一度に取得するようなことはできないのでしょうか。。

unity2018.3.14f1です。
よろしくお願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

可能性としては、同期先のユニティちゃんのAnimatorが生きていて、スクリプトで書き換えた動きをさらに上書きしている...とかでしょうかね?
下記のように、AvatarHumanPoseHandler経由で操作するパターンと子オブジェクトを走査して姿勢を書き写すパターンを試してみましたが、ちゃんと動きがコピーされました。

C#

1using System.Linq; 2using UnityEngine; 3 4public class UnitychanSynchronizer : MonoBehaviour 5{ 6 [SerializeField] private Transform source; 7 [SerializeField] private Transform destination; 8 [SerializeField] private bool useHumanPoseHandler = true; 9 10 private HumanPoseHandler sourcePoseHandler; 11 private HumanPoseHandler destinationPoseHandler; 12 private HumanPose pose; 13 14 private Transform[] sourceTransforms; 15 private Transform[] destinationTransforms; 16 private (Transform, Transform)[] transformPairs; 17 18 private void Start() 19 { 20 if ((this.source == null) || (this.destination == null)) 21 { 22 Debug.LogError("Source or destination not found."); 23 this.enabled = false; 24 return; 25 } 26 27 if (this.useHumanPoseHandler) 28 { 29 // Avatarを操作して動きを合わせる場合 30 var sourceAnimator = this.source.GetComponent<Animator>(); 31 var destinationAnimator = this.destination.GetComponent<Animator>(); 32 if ((sourceAnimator == null) || (destinationAnimator == null)) 33 { 34 Debug.LogError("Animator not found."); 35 this.enabled = false; 36 return; 37 } 38 39 // 同期元と同期先についてHumanPoseHandlerを作成 40 // 同期先のAnimatorは干渉を防ぐため無効化しておく 41 this.sourcePoseHandler = new HumanPoseHandler(sourceAnimator.avatar, this.source); 42 this.destinationPoseHandler = new HumanPoseHandler(destinationAnimator.avatar, this.destination); 43 destinationAnimator.enabled = false; 44 } 45 else 46 { 47 // Avatarを使用しない場合 48 var destinationAnimator = this.destination.GetComponent<Animator>(); 49 if (destinationAnimator != null) 50 { 51 destinationAnimator.enabled = false; 52 } 53 54 // 同期元と同期先の子オブジェクト群を取得しておく 55 this.sourceTransforms = this.source.transform.OfType<Transform>() 56 .SelectMany(child => child.GetComponentsInChildren<Transform>()).ToArray(); 57 this.destinationTransforms = this.destination.transform.OfType<Transform>() 58 .SelectMany(child => child.GetComponentsInChildren<Transform>()).ToArray(); 59 60 // 念のため同期元と同期先の子オブジェクトの数・名前が同じかチェック 61 if (this.sourceTransforms.Length != this.destinationTransforms.Length) 62 { 63 Debug.LogError("Child count are not same."); 64 this.enabled = false; 65 return; 66 } 67 68 this.transformPairs = this.sourceTransforms.Zip( 69 this.destinationTransforms, 70 (sourceChild, destinationChild) => (sourceChild, destinationChild)).ToArray(); 71 if (this.transformPairs.Select( 72 pair => 73 { 74 var (sourceChild, destinationChild) = pair; 75 var notSameName = sourceChild.name != destinationChild.name; 76 if (notSameName) 77 { 78 Debug.LogError($"Source:{sourceChild.name} Destination:{destinationChild.name}"); 79 } 80 81 return notSameName; 82 }).Any(notSameName => notSameName)) 83 { 84 Debug.LogError("Child names are not same."); 85 this.enabled = false; 86 return; 87 } 88 } 89 } 90 91 private void Update() 92 { 93 if (this.useHumanPoseHandler) 94 { 95 // Avatarを操作して動きを合わせる場合 96 if ((this.sourcePoseHandler == null) || (this.destinationPoseHandler == null)) 97 { 98 return; 99 } 100 101 var sourcePosition = this.source.position; 102 var sourceRotation = this.source.rotation; 103 this.source.position = Vector3.zero; 104 this.source.rotation = Quaternion.identity; 105 this.sourcePoseHandler.GetHumanPose(ref this.pose); 106 this.source.position = sourcePosition; 107 this.source.rotation = sourceRotation; 108 this.destinationPoseHandler.SetHumanPose(ref this.pose); 109 } 110 else 111 { 112 // Avatarを使用しない場合 113 if (this.transformPairs == null) 114 { 115 return; 116 } 117 118 foreach (var (sourceChild, destinationChild) in this.transformPairs) 119 { 120 if ((sourceChild == null) || (destinationChild == null)) 121 { 122 continue; 123 } 124 125 destinationChild.localPosition = sourceChild.localPosition; 126 destinationChild.localRotation = sourceChild.localRotation; 127 } 128 } 129 } 130}

結果

投稿2019/06/25 21:22

編集2019/06/25 21:28
Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Qoo

2019/06/26 01:14

テストまでしていただきありがとうございます! 頂いたコードをもとに再トライしてみます!
Qoo

2019/06/26 07:13

出来ました!直接ボーンのtransformを制御するものだと考えていたので、 めちゃくちゃ勉強になりました!ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問