モノ創りで国造りを

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

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

前編では距離に応じて力が変化するスクリプトを書いてみたけど
磁石オブジェクトと金属オブジェクトの位置関係によって
引力になったり斥力になったりと、ひどい結果でした。
今回は磁石と金属の位置関係に関わらず、両者の間に常に引力が発生するよう
コードを修正できたので記載。
不等式の公式から両者の位置関係を把握して、
x軸方向、y軸方向それぞれにかかる力の符号を変えるようにしました。

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

    // 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 () {
        tanObjects = (metal.transform.position.y - magPosition.y) / (metal.transform.position.x - magPosition.x);
        angleObjects = Mathf.Atan(tanObjects);
        distanceN = (magPosition - metal.transform.position).magnitude * Mathf.Sin(angleObjects);
        magForce = magConst / distanceN;
        magForceX = Mathf.Abs(magForce * Mathf.Sin(magAngle));
        magForceY = Mathf.Abs(magForce * Mathf.Cos(magAngle));
        if (metal.transform.position.x > (metal.transform.position.y - magPosition.y) / Mathf.Tan(magAngle) + magPosition.x) {
            xDir = -1.0f;
        }
        else {
            xDir = 1.0f;
        }
        if (metal.transform.position.y > Mathf.Tan(magAngle) * (metal.transform.position.x - magPosition.x) + magPosition.y) {
            yDir = -1.0f;
        }
        else {
            yDir = 1.0f;
        }
        this.rigid2D.AddForce(new Vector2(xDir * magForceX, yDir * magForceY), ForceMode2D.Force);
    }
}