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

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

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

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

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

1388閲覧

Unity Rayを使用したAnimatorについて

14dai

総合スコア15

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

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

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2020/04/21 14:56

編集2020/05/03 08:26

イメージ説明イメージ説明
Unityのanimatorにてraycustで当たり判定を使用しアニメーターを作成したのですが、添付写真の青のトランジションの部分にアニメーションが推移しないという現象が起きています。青のトランジション部分はidleがtrue(Rayが当たっていない時)の時に推移するようscriptを記載していますがマウスポイントが当たっていなくてもIdleの前のHoverLoopを繰り返しているという状態です。どなたか分かりますでしょうか。
ちなみにオブジェクトは1つコライダーもそれに伴って1つの為、他のオブジェクトにRayが反応していることはないと考えます。

C#

1 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5 6[RequireComponent(typeof(Collider))] 7public class LootBox : MonoBehaviour 8{ 9 public GameObject lootBox; 10 public GameObject lootReward; 11 12 private Animator animator; 13 private RaycastHit hit; 14 private Ray ray; 15 // Start is called before the first frame update 16 void Start() 17 { 18 animator = GetComponent<Animator>(); 19 } 20 21 // Update is called once per frame 22 void Update() 23 { 24 ray = Camera.main.ScreenPointToRay(Input.mousePosition); 25 26 if (Physics.Raycast(ray, out hit)) 27 { 28 if (hit.transform.name != gameObject.name) 29 { 30 animator.SetBool("Idle", true); 31 animator.SetBool("Hover", false); 32 33 34 35 if (Input.GetMouseButtonDown(0)) 36 { 37 animator.SetBool("Open", true); 38 39 } 40 } 41 else 42 { 43 animator.SetBool("Idle", false); 44 animator.SetBool("Hover", true); 45 46 } 47 48 } 49 } 50 51 public void LootReward() 52 { 53 var loot = Instantiate(lootReward) as GameObject; 54 55 Destroy(lootBox); 56 } 57 58}

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

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

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

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

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

guest

回答1

0

ベストアンサー

ご提示のコードを拝見しますと、animator.SetBool("Idle", true);の部分に到達するのは「レイキャストが成功し、かつ衝突相手の名前と自分自身の名前が一致しないとき」の場合だけであって、「レイキャストが失敗したとき」のケースでは何もしていないように見えますね。
下記のような分岐経路だとどうでしょうか?

C#

1 // Update is called once per frame 2 void Update() 3 { 4 ray = Camera.main.ScreenPointToRay(Input.mousePosition); 5 6 var hover = Physics.Raycast(ray, out hit); 7 if (hover && (hit.transform.name == gameObject.name)) 8 { 9 hover = false; 10 } 11 12 if (hover) 13 { 14 animator.SetBool("Idle", false); 15 animator.SetBool("Hover", true); 16 } 17 else 18 { 19 animator.SetBool("Idle", true); 20 animator.SetBool("Hover", false); 21 22 if (Input.GetMouseButtonDown(0)) 23 { 24 animator.SetBool("Open", true); 25 } 26 } 27 }

追記

ご質問内容から想像した動きを元にアニメーションを構成してみました。
コンポーネントのアタッチ状況は下図のようになっています。

図1

AnimatorのApply Root Motionはオフ前提としましたので、Animatorを持つオブジェクト全体を空のオブジェクトに入れて、ボール全体の位置を動かすには親オブジェクトの方を動かすことにしました。
コライダーはHoverアニメーションの上下動範囲をカバーするように縦長にして、アニメーションと一緒に動くようにはしませんでした。上下動するボール本体に球形コライダーを付ける案も試してみたものの、マウスポインタの位置によっては上下動のためにポインタが当たったり外れたりしてアニメーションがせわしなく切り替わり、若干見苦しく感じたため却下しました。

アニメーションは、マウスポインタを当てると浮遊して存在をアピールし、クリックすると開くというアイテムボックス的なものをイメージしました。
ステート遷移の概要は...

  • Idle、IdleToHover、Hover、Openの4つのステートを持つ。
  • Idleは何もアニメーションしない。Loop Timeオン。
  • IdleToHoverは地上から空中へ浮き上がるモーション。Loop Timeオフ。
  • Hoverは空中をふわふわ上下するモーション。Loop Timeオン。
  • Openはフタを開くモーションで、アニメーション終了後はフタが開かれた状態のまま維持される。Loop Timeオフ。
  • 初期状態はIdleで、マウスポインタを当てるとIdleToHoverへ、引き続きHoverへ移行する。
  • IdleToHoverまたはHover状態でマウスポインタが外れるとIdle状態へ遷移する。
  • マウスクリックがあった場合、どのステートからでもOpenへ遷移させる。ただし自分自身への遷移は無効化しておき、OpenからOpenへの遷移は起こらないようにする。
  • Openは遷移先を持たず、いったんOpen状態になるとそのまま元に戻らない。

となります。プロパティとしては...

  • マウスポインタが当たっているかどうかはBoolプロパティの「Hover」で表現し、trueなら当たっていてfalseなら当たっていない。
  • マウスクリックはTriggerプロパティの「Open」で表現し、コライダー上でクリックした時に起動される。

の2つを用意しました。
ご質問者さんが「Idle」と「Hover」の2種類のプロパティを使っている理由がよく分からなかったのですが、おそらくこれら2つは排他的だろうと想像し、Boolプロパティ一つでまかなうことにしました。
「Open」については、Boolプロパティのような二者択一の2つの状態というよりも、ボールを開くアクションの引き金としての意味合いが強いように感じましたのでTriggerとしました。
これだとまずいようでしたらコメントいただけましたらさらに遷移条件を検討してみようと思います。

各ステートは下記のように矢印を繋いでいます。

  • IdleからIdleToHoverへの遷移条件は「Hoverがtrue」。Exit Timeなし。Interruption SourceはNext State。
  • IdleToHoverからIdleへの遷移条件は「Hoverがfalse」。Exit Timeなし。Interruption SourceはNext State。
  • IdleToHoverからHoverへの遷移条件はない。Exit Timeあり。Interruption Sourceはどちらでもいいが、さしあたりNext State。
  • HoverからIdleへの遷移条件は「Hoverがfalse」。Exit Timeなし。Interruption SourceはNext State。
  • Any StateからOpenへの遷移条件は「Openトリガーが発火」。Interruption Sourceなし。Can Transition To Selfオフ。

最初の図で親オブジェクト側にアタッチしているBallControllerがマウスポインタの当たり判定を検知し、Animatorの状態を制御しています。

C#

1using UnityEngine; 2 3public class BallController : MonoBehaviour 4{ 5 private static bool needsRaycast = true; 6 private static Collider raycastResult; 7 private static readonly int HoverState = Animator.StringToHash("Hover"); 8 private static readonly int OpenState = Animator.StringToHash("Open"); 9 private Animator animator; 10 private new Collider collider; 11 private Camera mainCamera; 12 13 private void Start() 14 { 15 this.animator = this.GetComponentInChildren<Animator>(); 16 this.collider = this.GetComponentInChildren<Collider>(); 17 this.mainCamera = Camera.main; 18 } 19 20 private void Update() 21 { 22 if (needsRaycast) 23 { 24 // 今回想定したケースでは、複数のボールがあったとしてもレイキャストは1フレームあたり 25 // 少なくとも1回やれば十分なはずなので、最初にUpdateを処理することになったボールが 26 // 代表してレイキャストを行い、結果をstaticフィールドに保存しておく 27 var mouseRay = this.mainCamera.ScreenPointToRay(Input.mousePosition); 28 raycastResult = Physics.Raycast(mouseRay, out var hitInfo) ? hitInfo.collider : null; 29 needsRaycast = false; 30 } 31 32 // 自分が担当しているコライダーと、先の当たり判定で見つかったコライダーが一致すれば 33 // それはこのボールにマウスポインタが当たっていることを意味する 34 var hover = this.collider == raycastResult; 35 this.animator.SetBool(HoverState, hover); 36 37 // 自分の上にマウスポインタが当たっており、かつマウスボタンがクリックされたのであれば 38 // このボールがクリックされたと判断できるので、Openトリガーを起動する 39 if (hover && Input.GetMouseButtonDown(0)) 40 { 41 this.animator.SetTrigger(OpenState); 42 } 43 } 44 45 private void LateUpdate() 46 { 47 needsRaycast = true; 48 } 49}

実行時のステート遷移は下図のような様子でした。

図2

投稿2020/04/21 20:16

編集2020/05/05 01:30
Bongo

総合スコア10811

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

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

14dai

2020/04/22 02:20 編集

ご丁寧にご回答いただきありがとうございます。 上記コードで再生を押すとIdleの状態から推移しないという結果になりました。 また記載いただいたコードを下記のように変更し再生するとHoverLoopまで行きカーソルを画面外までずらしてもIdleに戻らない結果になりました。どうも画像青のトランジションに移行しないです、、 void Update() { ray = Camera.main.ScreenPointToRay(Input.mousePosition); var hover = Physics.Raycast(ray, out hit); if (hit.transform.name == gameObject.name) { animator.SetBool("Idle", false); animator.SetBool("Hover", true); } else { animator.SetBool("Idle", true); animator.SetBool("Hover", false); if (Input.GetMouseButtonDown(0)) { animator.SetBool("Open", true); } } }
14dai

2020/04/22 06:50

試してみたのですが、どうもオブジェクトの後ろにPlaneを90度回転させ背景のような形で持ってくるとRayが反応していますね。Rayが反応してはいるのですが、クリックの反応はGameオブジェクトではなく下の方で反応します。背景のPlaneを追加したためオブジェクトからカーソルをずらすとPlaneのコライダーにあたっている為、正しく動作していると考えています。 Rayの使い方としては、オブジェクトの背景に何かを置かないとカーソルの移動が変わらないということなんですかね、、
Bongo

2020/04/22 09:16

当たり判定のしかたが怪しいとなると、ひとまずステート遷移条件の件は保留して、そちらを片付けてしまったほうがよさそうですね。animator関連のコードは一旦コメントアウトして、Debug.Log(...)でメッセージを表示させるだけのようなシンプルなコードで試した方が当たり判定の形を確認しやすいんじゃないかと思います。 カーソルとの当たり判定に関してですが、普通はわざわざ背景を置いたりしなくても、オブジェクトがちゃんと3D用コライダーを持っていれば問題ないと思うんですがね...オブジェクトのインスペクターの様子をご提示いただけると手がかりになるかもしれません。
14dai

2020/05/03 08:29

ご対応ありがとうございます。 シーン上に配置しているアニメーション対応したいオブジェクトのインスペクター画面を追加しました。 球体上のオブジェクトにのみコライダーを付けているので、シーン上だと背景Planeのコライダーと球体のコライダーの2つが存在しています。
Bongo

2020/05/03 16:25

コライダーはちゃんと付いているようですね。 先のコメントで「クリックの反応はGameオブジェクトではなく下の方で反応します」というものがありましたが、それは球形コライダーがアニメーションに追従しないという意味でしょうか(つまりHover時のアニメーションというのは円盤状の台座から球体が浮き上がるようなモーションだが、プレイモードでHover状態にしてみるとグラフィックだけが浮き上がり、コライダーの領域を示す緑色の球体は元の位置のままで、見た目と当たり判定が乖離してしまうとか)? それともそれでは説明がつかない異常な挙動...たとえばプレイモード中にシーンビューの様子を観察してみてもコライダーの領域を示す緑色の球体は意図通りの位置に表示されており、明らかにマウスポインタがコライダーにヒットしているはずなのにそこでは反応せず、そこより下の変な位置で反応している...みたいな感じでしょうか?
14dai

2020/05/04 04:39

Bongo様 ご丁寧にありがとうございます。 いただいたコメントの後者になります。しかし、後者の方もPlaneを背景に敷いていて調整を行っていた時に起きていた現象で添付写真のようにコライダーをオブジェクトの少し上に持ってくることにより下にカーソルを持ってこないと動かないという現象は解決しました。 Planeを敷かない場合はゲーム中、コライダーの領域を示す緑色の球体は意図通りの位置に表示されていますが、カーソルを当ててHoverの状態にした後にカーソルをそらしてもIdleに戻らない状態になっています、、
Bongo

2020/05/05 01:30

すみません、まだHoverからIdleへ状態遷移しない理由がつかめておりません... ちょっと方針を変更して、私の想像する動きをもとに好き勝手にアニメーションを作ってみて追記することにしました。あれとご質問者さんのアニメーション設定を見比べてみて、何か怪しそうな点は見つかりませんでしょうか? 「自分の場合はここの設定がこうなっているが、何か影響しそうか?」みたいなお気付きの点がありましたら、コメントいただければさらに調べてみようと思います。
14dai

2020/05/05 03:25

懇切丁寧にご回答いただきありがとうございます。無事Planeを配置せずに問題にあったHoverからOpenに推移を行うことが出来ました。 追記いただいた点で前回のアニメーション設定と見比べて InterruptionSourceをすべてのトランジションでNoneにしていることですがアニメーションに直接影響はしないと考えています。 私の方で作成したアニーションステートは写真添付のIdle、Hover、HoverLoop、Openの4つのステートを用意しています。IdleとHoverLoopはLooPtimeにチェックを入れています。 IdleからHoverのトランジションはHasExitTimeなし、Interruptionなし、HoverがTrueです。 HoverからIdleのトランジションはHasExitTimeなし、Interruptionなし、IdleがTrueです。 HoverからHoverLoopのトランジションはHasExitTimeあり、Interruptionなし、Condition なしです。 HoverLoopからIdleのトランジションはHasExitTimeなし、Interruptionなし、IdleがTrueです。 後は写真のようにIdle,Hover,HoverLoopがそれぞれOpenにつながるようにトランジションを作成し、HasExitTimeなし、Interruptionなし、OpenがTrueで作成しています。 もう一度1から作成しなおして原因を確認してみます。 なによりご提示いただいた方法で解決したので、非常に助かりました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問