Cube や Sphere の内壁で衝突判定したい

自分用メモ。

# 概要

メッシュの内壁と衝突判定させたい場合、Cube や Sphere といったプリミティブをそのまま使うことはできないようです。
理由は、衝突判定にはメッシュの法線ベクトルの向きが関係しており、Cube や Sphere では法線ベクトルが外向きになっているため。

# 衝突判定させる方法（球の場合）

プリミティブでは法線ベクトルが外向きのために内壁で衝突判定ができない……ということは、
法線ベクトルを逆向きにしてやればできる！

下記リンク先では Sphere の法線を逆向きにした Inverted Sphere を作ってインスペクタから使えるようにする方法が解説されています。
http://answers.unity3d.com/questions/514637/how-do-i-invert-normals-of-a-sphere.html

該当部分を和訳しておきます。

> 以下は Inverted Sphere を作るためのスクリプトです。
> このスクリプトをあなたのプロジェクトの Assets/Editor フォルダに保存してください。
> 保存後に Hierarchy 上で右クリック > GameObject > Create Other > Inverted Sphere... を選択すると Inverted Sphere を配置できます。

```csharp:InvertedSphere.cs
     using UnityEngine;
     using UnityEditor;
     
     public class InvertedSphere : EditorWindow {
         private string st = "1.0";
      
         [MenuItem("GameObject/Create Other/Inverted Sphere...")]
         public static void ShowWindow() {
             EditorWindow.GetWindow(typeof(InvertedSphere));
         }
      
         public void OnGUI() {
             GUILayout.Label("Enter sphere size:");
             st = GUILayout.TextField (st);
             
             float f;
             if (!float.TryParse (st, out f))
                 f = 1.0f;
             if (GUILayout.Button("Create Inverted Sphere")) {
                 CreateInvertedSphere(f);
             }
         }
         
         private void CreateInvertedSphere(float size) {
             GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
             MeshFilter mf = go.GetComponent<MeshFilter>();
             Mesh mesh = mf.sharedMesh;
             
             GameObject goNew = new GameObject();    
             goNew.name = "Inverted Sphere";
             MeshFilter mfNew = goNew.AddComponent<MeshFilter>();
             mfNew.sharedMesh = new Mesh();
     
             
             //Scale the vertices;
             Vector3[] vertices = mesh.vertices;
             for (int i = 0; i < vertices.Length; i++)
                 vertices[i] = vertices[i] * size;
             mfNew.sharedMesh.vertices = vertices;
             
             // Reverse the triangles
             int[] triangles = mesh.triangles;
             for (int i = 0; i < triangles.Length; i += 3) {
                 int t = triangles[i];
                 triangles[i] = triangles[i+2];
                 triangles[i+2] = t;
             }
             mfNew.sharedMesh.triangles = triangles;
             
             // Reverse the normals;
             Vector3[] normals = mesh.normals;
             for (int i = 0; i < normals.Length; i++)
                 normals[i] = -normals[i];
             mfNew.sharedMesh.normals = normals;
             
             
             mfNew.sharedMesh.uv = mesh.uv;
             mfNew.sharedMesh.uv2 = mesh.uv2;
             mfNew.sharedMesh.RecalculateBounds();
             
             // メモ： 下記３行は Unity 5.0.2 ではコンパイルエラーになりました。まるごと削除すれば普通に使えます。
             // Add the same material that the original sphere used
             MeshRenderer mr = goNew.AddComponent<MeshRenderer>();
             mr.sharedMaterial = go.renderer.sharedMaterial;
             
             DestroyImmediate(go);
         }
     }
```

Cube なども同じ方法で作成できそうです。