Unityで学ぶ電流①片方の電極から片方の電極へ動くプラスイオンの実装

電流の直列や並列をUnityで勉強せん?

電流の直列や並列って小学生の頃に勉強しましたよね。あれ、Unityで作った教材で学びやすくならないかな、と思い作ることにしました。とりあえずUnityで3Dとして作れば、VRコンテンツにするのも楽なので、とりあえず3Dでインタラクティブな映像として作ります

まずは、電線の中をプラスイオンが動いている様子を実装しました

参考にしたプログラム

平たくて四角いタイルから同様のタイルへキューブを常時送り続けるプログラムのコードを知っていたのでそれを参考にしました。

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

public class Ramen : MonoBehaviour {

    public GameObject upperStage;
    public GameObject ramen;
    float  upperStageX;
    float  upperStageZ;

    void Start(){
        upperStageX = upperStage.GetComponent<Renderer> ().bounds.size.x;
        upperStageZ = upperStage.GetComponent<Renderer> ().bounds.size.z;




    }

    void Update () {
        GameObject[] ramens = GameObject.FindGameObjectsWithTag ("ramen");
        if (enemies.Length < 5) {
            Instantiate (ramen, upperStage.transform.position + new Vector3 (Random.Range (-upperStageX / 2, upperStageX / 2), 0, 
                Random.Range (-upperStageZ / 2, upperStageZ / 2)), Quaternion.identity);
        }
    }
}

コードだけでどんなゲームオブジェクトを置いたのか分からないので「何のこっちゃ」って感じだと思います(笑)

要は、片方の四角タイル(upperStageという変数に代入されています)のX座標方向の長さとZ座標方向の長さを取得して、タイル上の範囲内にramenというゲームジェクト(Sphere)を5個生成する。ramenの数が減って5個未満になったら新たにramenを生成するというプログラムです。Stageがもう一個あって、UpperStageからStageへとramenは移動して、Stageに到達するとvoid OnCollisionEnter()を使ってramenを破壊しているからramenは定期的に減って、そして補充されているわけです。

四角ではなく円にするだけでちょっと難しい

電線の断面が四角いと変なので円にします。すると単純に円の2つの座標方向の長さを取得してその範囲にSphereを生成したらおかしいことになります。

f:id:kazutakayokoils:20171019195043p:plain

上の画像のグリーンの部分上にSphereができてほしいわけですがオレンジの部分にできてもらうと、そこ電線の外やん!ってことになるわけです。
そこでこう書き換えました。

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

public class CurrentController : MonoBehaviour {

	public GameObject PlusIon;
	public GameObject ElectrodeMinus;
	float  upperStageY;
	float  yposition;
	double zrange;
	public float PlusIonNumber;
	float aboutzrange;
	bool One;

	void Start(){
		upperStageY = ElectrodeMinus.GetComponent<Renderer> ().bounds.size.y;
		One = true;
	}
		
		void Update () {
		yposition = Random.Range (-upperStageY / 2, upperStageY / 2);
		zrange    = System.Math.Sqrt (25 - System.Math.Pow(yposition, 2));
		aboutzrange = (float)System.Math.Truncate (zrange);
		GameObject[] PlusIonCount = GameObject.FindGameObjectsWithTag ("PlusIon");
		if (PlusIonCount.Length < PlusIonNumber) {
			Instantiate (PlusIon, ElectrodeMinus.transform.position + new Vector3(-1, yposition, Random.Range(-aboutzrange, aboutzrange)), Quaternion.identity);
			}
        }
}

(0,0,0)が中心の半径が5の円があり、ここからPlusIonを出します。ここでは、ざっくり言うと、円上の特定のy座標の値を定めて、そのy座標を持てる円上の点のz座標の範囲を調べ、その範囲にPlusIonというSphereを生成しようとしています。Sphereにはx座標方向に進むスクリプトをアタッチしてあります。
y座標を持てる円上の点のz座標の範囲は、「5~2-y~2の平方根」から「マイナス 5~2-y~2の平方根」なわけですが、それを計算するには、System.Math クラスを使います。詳しくはこちら!
小数点を切り捨て、切り上げ、四捨五入する: .NET Tips: C#, VB.NET

doubleクラスをfloat型に変換しないとエラーが出るので注意です。double型で変数zrangeを定義したのは、計算結果がより正確になるためですね。別にfloat型で定義してもいいんですけど。

じゃあ、とりあえずこの辺で。