UnityのSpring Jointをマウスなどで操作する場合


はじめに

Spring Jointを使うの記事の補足です。Jointが繋がっているオブジェクトをマウスなどで動かす場合に使えるスクリプトを紹介します。

例:ピンボールの発射部分

要するに、ばねの上に玉をのせて、ばねを引いて弾く、というやつです。ばねを引くのに、マウスなどでドラッグする仕組みを考えます。

http://sun-malt.com/wp-content/uploads/2016/02/Image311.jpg より転載

Cubeを二つ上下に配置して、下は固定、上はY方向のみ動くようにして二つをSpring Jointでつなぎます。そのさらに上に玉を。

上のCubeはマウスでドラッグできるようにします。こちらの記事のMouseDragスクリプトをベースにしますが、マウスで動かすのはY方向だけにしたいので、元は

        Vector3 mousePointInScreen
            = new Vector3(Input.mousePosition.x,
                          Input.mousePosition.y,
                          objectPointInScreen.z);

となっているのを

        Vector3 mousePointInScreen
            = new Vector3(objectPointInScreen.x,
                          Input.mousePosition.y,
                          objectPointInScreen.z);

として、Yのみマウスの位置に依存するようにします。

変更したら、MouseDragスクリプトを上のキューブにアタッチしてください。

これで実行すると、下の動画のように、マウスで上のキューブを下に下げると、なぜか勝手に玉が上に飛んでいきます。

理由はよくわかりませんが、解決策としては、マウスでドラッグしている最中は、上のcubeのRigidbodyのisKinematicがオンになるようにすると、うまくいきます。

MouseDrag.cs
using UnityEngine;

public class MouseDrag : MonoBehaviour
{

    public Rigidbody _rigidbody;

    void Start()
    {
        _rigidbody = GetComponent<Rigidbody>();
    }

    void OnMouseDrag()
    {
        Vector3 objectPointInScreen
            = Camera.main.WorldToScreenPoint(this.transform.position);

        Vector3 mousePointInScreen
            = new Vector3(objectPointInScreen.x,
                          Input.mousePosition.y,
                          objectPointInScreen.z);

        Vector3 mousePointInWorld = Camera.main.ScreenToWorldPoint(mousePointInScreen);
        mousePointInWorld.z = this.transform.position.z;
        this.transform.position = mousePointInWorld;

        _rigidbody.isKinematic = true;

    }

    void OnMouseUp()
    {
        _rigidbody.isKinematic = false;
    }

}

ドラッグ中はisKinematicがtrueで、ドラッグを止める(OnMouseUp)とfalseに戻します。結果は以下の通りです。