モノ創りで国造りを

ハード/ソフト問わず知見をまとめてます

磁石に吸い付く動きをUnityで実装してみる--前編--

Unityで平らな板に磁石のようにオブジェクトが吸い付く動作を実装したいと思い色々と調べました。
磁石の力は、磁石からの距離に反比例します。
厳密には点磁化による力は距離の二乗に反比例するんですが
平らな磁石の場合は点磁化による力が積分されて距離に反比例するんですね。
細かい話は置いといて、とにかく距離に応じて力を変えたかったわけです。

UnityにはArea Effectorというコンポがあり
指定した範囲にあるオブジェクトに一定の力を加える事ができるんですが
それでは力の強さは一定になるんですね。

ということでスクリプトで頑張って実装してみました。
が、なかなかうまくいきません・・・
一応条件によっては、対象となるオブジェクトを引き付ける動作になるんですが
位置関係によってx方向だけor方向だけ斥力になったり、
まだまだ推敲が必要です。
*果たして後編はあるのか!?

public class magneticForce : MonoBehaviour {
    Vector3 distance;
    float distanceN;//法線方向の距離
    Vector3 magPosition;//磁石の中心位置
    float magForce;//磁力を受けるオブジェクトにかかる力
    float magForceX;//磁力を受けるオブジェクトにかかる力
    float magForceY;//磁力を受けるオブジェクトにかかる力
    float magConst = 100.0f;//定数のパラメータ
    float magAngle;//磁石の角度
    GameObject metal;//磁力を受けるオブジェクト
    Rigidbody2D rigid2D;
    float angleObjects;//オブジェクト間の角度

    // Use this for initialization
    void Start () {
        this.magPosition = transform.position;
        this.magAngle = transform.localEulerAngles.z * Mathf.Deg2Rad;//ラジアンで角度を取得
        this.metal = GameObject.Find("metal");
        this.rigid2D = this.metal.GetComponent<Rigidbody2D>();
    }
    
    // Update is called once per frame
    void Update () {
        angleObjects = Mathf.Atan((metal.transform.position.y - magPosition.y) / (metal.transform.position.x - magPosition.x));
        distanceN = (magPosition - metal.transform.position).magnitude * Mathf.Sin(angleObjects);
        magForce = magConst / distanceN;
        magForceX = magForce * Mathf.Sin(magAngle);
        magForceY = magForce * Mathf.Cos(magAngle);
        this.rigid2D.AddForce(new Vector2(magForceX, magForceY), ForceMode2D.Force);
    }
}