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

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

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

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

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Unity

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

Q&A

解決済

1回答

1537閲覧

Anima2Dのコライダー(Mesh Collider)の反転

Bruno_5239

総合スコア23

C#

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

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Unity

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

0グッド

1クリップ

投稿2020/04/19 04:02

編集2020/04/21 03:22

現在、Anima2Dでキャラクターを制御し、それに伴う当たり判定の実装をコライダーとレイキャスティングで行っています。

魚のキャラクターが一定間隔で左右にゆらゆらと泳ぐ動きをAnimatorで制御しているのですが、レンダラーの都合上、方向転換をRotationではなく、Scale.xを-1にすることで実装しています。
レンダリングはこれでうまくいっているのですが、この方法だとコライダーは反転せず常に正方向を向いた状態で魚についてしまっています。
https://raspberly.hateblo.jp/entry/2018/09/13/000000
こちらの方法を参考にもしてみましたが形は反転せず、しかもコライダーはレイキャスティングに引っ掛からなくなりました。
レイキャスティングに引っ掛からなくなった以上何かしらの影響は与えているのだと思いますが、形は反転しておらず、判定も取れなくなっているので解決には至っていません。

どなたか2Dオブジェクトの判定の反転のうまい方法を教えていただけないでしょうか。

イメージ説明
・反転制御。Animatorを使ってScaleを変更している。真ん中らへんのくぼんだ形になっている薄いピンクのカーブ

C#

1void Update() 2{ 3 var mesh = new Mesh(); 4 var waitForFixedUpdate = new WaitForFixedUpdate(); 5 6 var scale = meshCol.gameObject.transform.localScale; 7 meshCol.gameObject.transform.localScale = Vector3.one; 8 9 skinnedMesh.BakeMesh(mesh); 10 meshCol.sharedMesh = mesh; 11 12 meshCol.gameObject.transform.localScale = scale; 13}

・MeshColliderのベイクのコード

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

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

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

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

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

guest

回答1

0

ベストアンサー

スケールが操作されたオブジェクトに対してBakeMeshを行うと、なんだか謎な挙動をするみたいなんですよね...
Anima2Dのアニメーションに沿ってコライダーを生成したい。」で例示しましたスクリプトを下記のように変更してみましたが、これならどうでしょうか?

C#

1using System.Collections; 2using UnityEngine; 3 4public class ColliderUpdater : MonoBehaviour 5{ 6 private IEnumerator Start() 7 { 8 var skinnedMeshRenderer = this.GetComponent<SkinnedMeshRenderer>(); 9 while (skinnedMeshRenderer == null) 10 { 11 yield return null; 12 13 skinnedMeshRenderer = this.GetComponent<SkinnedMeshRenderer>(); 14 } 15 16 var meshCollider = this.GetComponent<MeshCollider>(); 17 if (meshCollider == null) 18 { 19 meshCollider = this.gameObject.AddComponent<MeshCollider>(); 20 } 21 22 var bakedMesh = new Mesh(); 23 var waitForFixedUpdate = new WaitForFixedUpdate(); 24 while (true) 25 { 26 // 調査不十分だが、MeshCollider更新処理は 27 // FixedUpdateとタイミングを合わせた方がよさそう? 28 yield return waitForFixedUpdate; 29 30 // ベイク前に現在のスケールを記憶しておき... 31 var scale = this.transform.localScale; 32 33 // ベイク処理はスケール1倍の状態で行う 34 this.transform.localScale = Vector3.one; 35 skinnedMeshRenderer.BakeMesh(bakedMesh); 36 meshCollider.sharedMesh = bakedMesh; 37 38 // その後スケールを元の状態に復帰する 39 this.transform.localScale = scale; 40 } 41 } 42}

追記

スクリプトをちょこっといじってみましたが、これだとどうでしょうか?

C#

1using UnityEngine; 2 3[DefaultExecutionOrder(1)] 4public class ColliderUpdater : MonoBehaviour 5{ 6 private SkinnedMeshRenderer skinnedMeshRenderer; 7 private MeshCollider meshCollider; 8 private Mesh bakedMesh; 9 10 private void Start() 11 { 12 this.skinnedMeshRenderer = this.GetComponent<SkinnedMeshRenderer>(); 13 if (this.skinnedMeshRenderer == null) 14 { 15 Debug.LogError("SkinnedMeshRenderer not found."); 16 } 17 18 this.meshCollider = this.GetComponent<MeshCollider>(); 19 if (this.meshCollider == null) 20 { 21 this.meshCollider = this.gameObject.AddComponent<MeshCollider>(); 22 } 23 24 this.bakedMesh = new Mesh(); 25 26 // 「頻繁にデータ更新が行われるメッシュである」とマーキングしてみました 27 // 多少は動作が最適化されるかも...? 28 this.bakedMesh.MarkDynamic(); 29 } 30 31 // 更新タイミングはFixedUpdateの方がいいかも...などと申し上げましたが 32 // Updateでもよさそうに思い直しまして、Updateでメッシュ更新を行っています 33 private void Update() 34 { 35 var scale = this.transform.localScale; 36 this.transform.localScale = Vector3.one; 37 this.skinnedMeshRenderer.BakeMesh(this.bakedMesh); 38 this.transform.localScale = scale; 39 40 // スケールを元に戻してからコライダーにメッシュをセットするようにしてみました 41 // 私の場合ですと、このようにしたところシーンビュー上のコライダーの 42 // 緑色メッシュ表示と実際の形状との食い違いが解消されました 43 this.meshCollider.sharedMesh = this.bakedMesh; 44 } 45}

キャラクターのアニメーションはご質問者さんのものをまねて下図のようにして...

図1

シーンビューでコライダーの追従状況を見てみたところ、わずかな遅れはあるものの左右が逆転するような大きなズレはなさそうでした。

図2

マウスポインタの位置での当たり判定においても、コライダーは左右反転してはいないようです。もしコライダーが左右反転していればはっきり区別がつくだろうと思い、荒ぶっている髪の毛周辺に重点的にポインタを持っていきましたが、決定的に不自然な反応は見られませんでした。

図3

念のため上図の実験で球にアタッチした当たり判定および色塗りスクリプトも追記しますが、とりわけ特殊なことはしておらずPhysics.Raycastを使った判定を行っているだけです。

C#

1using UnityEngine; 2 3public class SphereController : MonoBehaviour 4{ 5 private Camera mainCamera; 6 private Material material; 7 8 private void Start() 9 { 10 var r = this.GetComponent<Renderer>(); 11 if (r == null) 12 { 13 this.enabled = false; 14 return; 15 } 16 17 Cursor.visible = false; 18 this.material = r.material; 19 this.mainCamera = Camera.main; 20 } 21 22 private void Update() 23 { 24 var ray = this.mainCamera.ScreenPointToRay(Input.mousePosition); 25 var plane = new Plane(Vector3.back, 0); 26 if (plane.Raycast(ray, out var enter)) 27 { 28 this.transform.position = ray.GetPoint(enter); 29 } 30 31 this.material.color = Physics.Raycast(ray) ? Color.green : Color.red; 32 } 33}

投稿2020/04/19 06:00

編集2020/04/20 12:11
Bongo

総合スコア10811

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

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

Bruno_5239

2020/04/19 09:59 編集

何度もご回答ありがとうございます。 当たり判定は確かに逆向きでも取れるようになりました!が、形はやはり一定方向のままです。。。 一度Scaleをもとに戻してからベイクしているからだとは思うのですが。。逆を向いた形に添ったコライダーにはなっていないようです。LinqのReverse()も使えませんでしたし、やはりRotationをさせなければならないのでしょうか。 しかし、Scaleをいじってからベイクするとおかしくなるというのは初めて知りました。ありがとうございます!
Bongo

2020/04/19 11:37

残念、ダメでしたか... 結局状況的にはご質問文でおっしゃるような様子のままで、反転状態だとゲームビュー上のグラフィックは左右反転するものの、コライダーの形状は順方向のままになってしまうということでしょうか。 後でマウスポインタとの当たり判定を見ていたときに気付いたのですが、シーンビュー上に緑色で表示されているコライダーのメッシュ形状は左右の食い違った状態なのに、ゲームビュー上でのマウスポインタとの判定は正しく一致した向きになっている...といったややこしい状態になるケースもあるようです。シーンビューの表示が当てにならないとなると、動作の検証もやっかいになりそうです... もっと詳しく調べてみようと思うのですが、参考として現状のコライダー更新スクリプトとキャラクターの左右反転を行っているスクリプトをご提示いただけませんでしょうか。あるいは、差し支えなければ...でかまいませんが、どこかのアップローダーにでもプロジェクト全体をアップロードいただけると、ご質問者さんの状況をより正確に見ることができてありがたいです。 どうにも解決困難そうなら、いくらか方針を変更するべきなのかもしれません。たとえばスケールを操作しなくても済むように、右向きと左向きのキャラクターをそれぞれ作っておいて必要に応じて切り替えて使用する...みたいな手は使えそうでしょうかね?
Bruno_5239

2020/04/20 04:17

ありがとうございます。本文に新しくAnimatorとベイクのコードを載せました。 確かにそもそもの移動の制御を見直したほうが早いかもしれませんね。。
Bongo

2020/04/20 12:11

追記ありがとうございます。すみませんがまだ原因を突き止めることができていませんが、いくらかいじってみて気になった部分を変更したスクリプトを追記しました(ついでにコルーチンもやめて、処理をStartとUpdateの2つに分散しました)。これなら何か変化はあるでしょうか?
Bruno_5239

2020/04/21 02:37

お世話になっています。今日追記していただいた通り、ベイクしてからスケールを戻しコライダーにメッシュを適用したところ、裏向きの場合でも判定が取れました!! スケールをいじっているAnima2Dにコライダーをとる場合は ScaleをVector3.oneで正規値に ↓ 新しいMeshにベイク ↓ スケールを戻す ↓ メッシュコライダーにベイクしたメッシュを適用 のプロセスを踏む必要があるんですね!確かに、今回に限らず少し特殊な動作が複雑に絡んでいる場合はいったんほかの箇所をデフォルトに戻してから再び変更をかける方法も有効なようですね。勉強になりました! 長い間お付き合いくださり本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問