スケールが操作されたオブジェクトに対してBakeMesh
を行うと、なんだか謎な挙動をするみたいなんですよね...
「Anima2Dのアニメーションに沿ってコライダーを生成したい。 」で例示しましたスクリプトを下記のように変更してみましたが、これならどうでしょうか?
C#
1 using System . Collections ;
2 using UnityEngine ;
3
4 public 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#
1 using UnityEngine ;
2
3 [ DefaultExecutionOrder ( 1 ) ]
4 public 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 }
キャラクターのアニメーションはご質問者さんのものをまねて下図のようにして...
シーンビューでコライダーの追従状況を見てみたところ、わずかな遅れはあるものの左右が逆転するような大きなズレはなさそうでした。
マウスポインタの位置での当たり判定においても、コライダーは左右反転してはいないようです。もしコライダーが左右反転していればはっきり区別がつくだろうと思い、荒ぶっている髪の毛周辺に重点的にポインタを持っていきましたが、決定的に不自然な反応は見られませんでした。
念のため上図の実験で球にアタッチした当たり判定および色塗りスクリプトも追記しますが、とりわけ特殊なことはしておらずPhysics.Raycast
を使った判定を行っているだけです。
C#
1 using UnityEngine ;
2
3 public 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 09:59 編集
2020/04/19 11:37
2020/04/20 04:17
2020/04/20 12:11
2020/04/21 02:37