Ezy-Slice を用いて3Dオブジェクトを切断する (1)

前回記事.
xrdnk.hateblo.jp

簡単にEzy-Sliceを使って,オブジェクトを切断してみました.

デモ

こんな感じにオブジェクトが切断面に沿って真っ二つになります.

準備

まずはEzy-SliceフレームワークGitHubから取得します.MITライセンスです.
github.com

切断したい物体を作る

切断したい物体を作りましょう. 自分はプリミティブオブジェクトのCube,Sphere,Cylinderを使います.
準備として,切断したい物体であることを示すLayerを作りましょう.例として,ボクはSliceable命名しました.

f:id:xrdnk:20200417231119p:plain

切断用の面を作る

Planeで切断用の面を作りましょう.上のデモで言えば,ピンク色の面ですね.
その後,以下のデモ用スクリプトをアタッチします.
以下のスクリプトはもともとEzy-Sliceで提供されているサンプルスクリプトを改変したり,一部を利用したりしています.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using EzySlice; // Ezy-Slice フレームワークを利用するために必要

public class SliceTest : MonoBehaviour
{
    // 切断面の色
    public Material MaterialAfterSlice;
    // 切断するレイヤー
    public LayerMask sliceMask;

    void Update()
    {
        // spaceボタン押下時
        if (Input.GetKeyDown("space"))
        {
            // Physics.OverlapBoxを用いて切断用の面と重なっている全コライダーを検出
            Collider[] objectsToSlice = Physics.OverlapBox(transform.position, new Vector3(1, 0.1f, 0.1f), transform.rotation, sliceMask);

            // 全コライダーごとに切断する
            foreach (Collider objectToSlice in objectsToSlice)
            {
                // 元オブジェクトの切断
                SlicedHull slicedObject = SliceObject(objectToSlice.gameObject, MaterialAfterSlice);

                // 上面側のオブジェクトの生成
                GameObject upperHullGameobject = slicedObject.CreateUpperHull(objectToSlice.GetComponent<Collider>().gameObject, MaterialAfterSlice);
                MakeItPhysical(upperHullGameobject);

                // 下面側のオブジェクトの生成
                GameObject lowerHullGameobject = slicedObject.CreateLowerHull(objectToSlice.GetComponent<Collider>().gameObject, MaterialAfterSlice);
                MakeItPhysical(lowerHullGameobject);

                // 元オブジェクトの削除
                Destroy(objectToSlice.gameObject);
            }
        }
    }

    // 切断時に生成するオブジェクトを返す
    private SlicedHull SliceObject(GameObject obj, Material crossSectionMaterial = null)
    {
        // Ezy-Slice フレームワーク を利用してスライスしている
        return obj.Slice(transform.position, transform.up, crossSectionMaterial);
    }

    // オブジェクト生成時にMeshColliderとRigidbodyをアタッチする
    private void MakeItPhysical(GameObject obj, Material mat = null)
    {
        // MeshCollider の Convex を true にしないと,すり抜けてしまうので注意
        obj.AddComponent<MeshCollider>().convex = true;
        obj.AddComponent<Rigidbody>();
    }
}

アタッチすると以下の画像のようになると思います.

f:id:xrdnk:20200417231200p:plain

Material After Slice は切断面のマテリアルを設定します.自分は今回わかりやすく緑色にしました.
そしてSlice Maskには先ほど作ったLayerのSliceableを設定します.

これでデモ動画のように物体を切断面に沿って真っ二つに出来ると思います.

ちなみに,MeshColliderのConvexをfalseにすると,
メッシュコライダー同士が衝突処理されないために切断されずにすり抜けてしまいます.

f:id:xrdnk:20200417233053g:plain

次回は,Ezy-Sliceを用いて,Beat Saber的なサムシングを作りたいなと思います.