UnityでClothに玉を衝突させる

投稿者: | 2020-03-07


Clothコンポーネントを付けたオブジェクトに玉を衝突させてみました。

まず、BlenderでPlaneメッシュを作って、細分化してUnityに持ってきました。

これにClothコンポーネントをつけて、Edit cloth constraintsボタンを押します。

シーン画面にClothの頂点を固定するツールが表示されるので、「Select」を押して、マウスドラッグでPlaneの一番上の頂点だけを矩形選択します。

そして、Max Distanceにチェックを入れて、値を0にします。

Sphereオブジェクトを新規作成して、SphereコライダーとRigidbodyを付けます。

これをProjectのどこかにドラッグアンドドロップしてプレハブ化します。

この玉とClothに衝突できるようにしますが、Clothコンポーネントでは玉がClothに影響を与えても、Clothが玉に影響を与えて玉が反発するということはないので、玉はClothを通り抜けます。
https://docs.unity3d.com/ja/2018.4/Manual/class-Cloth.html

スクリプトでClothに玉が衝突できるようにする

Clothが他のオブジェクトと衝突できるようにするには、Clothコンポーネントに衝突させたいコライダーをアタッチします。
Clothの使い方はこちら

それをプレイ中にスクリプトで行います。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ThrowBallScript3 : MonoBehaviour
{

    public GameObject ball;
    public float thrust = 10f;
    public GameObject plane;

    Vector3 cursorPosition;
    Vector3 cursorPosition3d;
    RaycastHit hit;
    Vector3 cameraPosition;
    Vector3 throwDirection;   
    GameObject rb_ball;

    Cloth planeCloth;
    ClothSphereColliderPair[] ballColliders;
    int n;

    // Start is called before the first frame update
    void Start()
    {
        planeCloth = plane.GetComponent<Cloth>(); // Clothコンポーネントを取得
        ballColliders = new ClothSphereColliderPair[10];
        n = 0;
    }

    // Update is called once per frame
    void Update()
    {

        if (Input.GetMouseButtonDown(0)) // マウスの左クリックをしたとき
        {
            rb_ball = Instantiate(ball, Camera.main.transform.position, transform.rotation); // 玉を生成
            rb_ball.GetComponent<Rigidbody>().AddForce(ThrowDirection() * thrust, ForceMode.Impulse); // カーソルの方向に力を一度加える
            rb_ball.name = n.ToString();

            ballColliders.SetValue(new ClothSphereColliderPair(rb_ball.GetComponent<SphereCollider>()), n);
            planeCloth.sphereColliders = ballColliders;

            n++;
            if (n > 9) n = 0; // 10以上でnを0に戻す
        }
    }

    Vector3 ThrowDirection()
    {
        cursorPosition = Input.mousePosition; // 画面上のカーソルの位置
        cursorPosition.z = 10.0f; // z座標に適当な値を入れる
        cursorPosition3d = Camera.main.ScreenToWorldPoint(cursorPosition); // 3Dの座標になおす

        return cursorPosition3d - Camera.main.transform.position; // 玉を飛ばす方向
    }
}

空のゲームオブジェクトを新規作成して上のスクリプトを付けました。

同じスクリプトで玉を発射していますが、それはこちらの記事で解説しています。

Clothコンポーネントにコライダーをアタッチするには、Clothコンポーネントの「Sphere Colliders」のSizeにその数を、各要素にSphereコライダーを入れます。

2つのSphereコライダーを入れると、それらをつなげた円錐カプセル形を定義できます。1つだけを使うときはSecondをnullにします。

この「Sphere Colliders」は、ClothSphereColliderPair型の配列なので、玉を生成したときにClothSphereColliderPair型の配列に要素を追加して、それをSphere Collidersメンバに代入してみました。

ballColliders = new ClothSphereColliderPair[10];
// ---
ballColliders.SetValue(new ClothSphereColliderPair(rb_ball.GetComponent<SphereCollider>()), n);
planeCloth.sphereColliders = ballColliders;

玉の数を10個に制限しているので、インデックスに使うnを発射のたびに1増加させて、10以上のときに0に戻るようにしています。

すると、プレイ中に玉を発射したときに、Clothコンポーネントにコライダーがアタッチされていきます。

11個目のコライダーは1個目のコライダーと入れ替わります。

Clothを制御する

Clothコンポーネントで曲げ剛性や減衰を上げると、Clothの動きが鈍くなって荒ぶりにくくなります。

ですが、玉の制限を少なくして玉を連射すると、たまにClothに強い力が加わることがあります。

この理由はよくわかりません。

コメントを残す

メールアドレスが公開されることはありません。