カテゴリー別アーカイブ: C Sharp

【Unity C# スクリプト】マウスドラッグ・ホイールでメインカメラ位置制御

マウス操作でメインカメラの位置を制御可能にし、好きな角度から好きな倍率でシーンを見ることができるようにしてみよう。
そのためには、まずメインカメラの位置を球座標系で表すことにする。

public class ScrCamera : MonoBehaviour {
    public Vector3 m_target;    //   ターゲット位置
    public float m_distance;    //  ターゲット位置からの距離
    public float m_latitude;    //  緯度(上から見下ろしている場合: > 0)、[-90, +90]
    public float m_longitude;   //  経度(Z軸+方向から見ている場合:== 0)、Y軸+方向からみて時計回り、[0, 380)
    .....
}

コードは上記のようになる。
メインカメラが中央に捉えるターゲットの位置と、そこからの距離、緯度・経度(球座標系)をメンバ変数として保持する。

上記のデータが更新された場合、updateCamera() が呼ばれ、メインカメラの位置・方向が設定される。

    //  カメラ位置、向きを設定
    void updateCamera()
    {
        float y = m_distance * Mathf.Sin(m_latitude * Mathf.Deg2Rad);
        float t = m_distance * Mathf.Cos(m_latitude * Mathf.Deg2Rad);
        float x = t * Mathf.Sin(m_longitude * Mathf.Deg2Rad);
        float z = t * Mathf.Cos(m_longitude * Mathf.Deg2Rad);
        Camera.main.transform.position = new Vector3(x, y, z) + m_target;
        Camera.main.transform.LookAt(m_target);
    }

Mathf.Deg2Rad は、デグリーをラジアンに変換するための定数だ。
カメラの位置は、球座標で計算した変位にターゲット座標を加え、メインカメラの transform.position に代入している。
カメラの向きは LookAt(目標位置) で設定している。

このように Unity スクリプトには必要な機能がちゃんと用意されており、便利だなーと感心させられる。

これで、準備が整ったので、Start() で以下のようにカメラ位置・向きを初期化しておく。

    void Start () {
        m_target = new Vector3(0, 0, 0);
        m_distance = 5;
        m_latitude = 30;
        m_longitude = 45;
        updateCamera();
    }

カメラ初期位置などは適当に決めている。

次に、カメラ位置の更新だが、まずは簡単なマウスホイールによる拡大縮小から。
ターゲットとカメラの距離(m_distance)を増加させると縮小、減少させると拡大になるので、ホイールの回転を検知したら、増加・減少させるようにする。

    void Update()
    {
        float mouseWheelScroll = Input.GetAxis("Mouse ScrollWheel");
        if (mouseWheelScroll != 0)
        {
        	m_distance -= mouseWheelScroll*4;
        	if( mouseWheelScroll < 0 )
        		m_distance *= 1.1f;
        	else
        		m_distance /= 1.1f;
            if ((m_distance -= mouseWheelScroll*4) < 1)
                m_distance = 1;
            else if (m_distance > 1000)
                m_distance = 1000;
            updateCamera();
        }
        ....
    }

【Unity C# スクリプト】GUILayout で GUI コンポーネントを自動レイアウト

void OnGUI() 関数を定義したスクリプトを Canvas などにアタッチすると、GUILayout を使った自動レイアウトを使用することができるぞ。

GUILayout.BeginArea() でエリアを作成し、GUILayout.EndArea() で囲まれる部分にボタンなどのUIオブジェクトを配置していく。
以下は、2つのボタンを持つUIの例だ。

    void OnGUI() {
        GUILayout.BeginArea(new Rect(10, 10, 100, 100));
            GUILayout.Button("Click me");
            GUILayout.Button("Or me");
        GUILayout.EndArea();
    }

temp

もっと複雑なレイアウトにしたい場合は、BeginHorizontal、BeginVertical、BeginScrollView で入れ子エリアを作ることもできるぞ。

【Unity C# スクリプト】UI.Text に文字を設定

Hierarchy の Create をクリックして表示されるメニューから UI > Text を選び、Text オブジェクトを配置する。

temp

下図の様に、Canvas が自動的に作成され、その子オブジェクトとして Text オブジェクトが作成される。

temp

Project の Create を押し、C# スクリプトファイルを作成し、適当なコントロールオブジェクト(例えばメインカメラ)にアタッチする。

スクリプトの最初に using UnityEngine.UI; 文を追加し、GameObject  型の public 変数を追加する。
Unity エディタでアタッチされたオブジェクトをインスペクタで参照し、この public 変数を当該テキストオブジェクトに紐付ける。

using UnityEngine.UI;
....
public class ScriptName : MonoBehaviour {
    public GameObject uiText;
    .....
}

Text コンポーネントは uiText.GetComponent() で取得できるので、Text の text メンバ変数を参照・更新したり、他のメンバ関数をコールすることが可能。

    Debug.Log(uiText.GetComponent().text);  // 現テキストをコンソールに表示
    uiText.GetComponent().text = "hoge hoge";  // テキストを変更

 

【Unity C# スクリプト】オブジェクトを動的に生成

手順は以下の通り

1. 生成したいオブジェクトのプレファブを作成
2. オブジェクトを動的生成するスクリプトを作成し、なんらかのコントールオブジェクトにアタッチ
3. スクリプトのコードは以下のような感じ

public class scr_gameObject : MonoBehaviour {
  public Transform prefab;
  void Update () {
    if( Input.GetKey("space") ) {
      Instantiate(prefab, new Vector3(0f, 10f, 0f), Quaternion.identity);
    }
  }
}

最初にプレファブオブジェクト(への参照)を宣言する。
この変数と実際のプレファブとの紐付けは Unity エディタで行なう。

temp

注意点としては、スクリプトではなく、コントロールオブジェクトをインスペクタで見て、そこの prefab にドロップするという点だ。
スクリプトをインスペクターでみても prefab が表示されるが、そこにドロップしても期待したようには動作しない。

あとは、update() でキーが押されたときなどに、Instantiate() を用いて、プレファブからオブジェクトを生成する。
第2引数は生成位置、第3引数は回転行列を指定する。
回転しない場合は、例の用に「Quaternion.identity」を指定する。

【Unity C# スクリプト】シーン上オブジェクトをスクリプトから参照

シーン全体をコントロールするような、当該オブジェクトにアタッチされていないスクリプトから、特定のオブジェクトを参照する方法は、いくつか存在する。

ひとつは、GameObject.Find(オブジェクト名) で、オブジェクト(への参照)を取得する方法だ。

  var cube1 = GameObject.Find("Cube1");  // "Cube1" オブジェクトを取得
  cube1.transform.position = new Vector3(2f, 0.5f, -2f);  //  位置を指定

もうひとつの方法は、スクリプト内でパブリックなオブジェクト(への参照)変数を宣言し、Unity エディタで特定のオブジェクトと紐付ける方法だ。

public class scr_camera : MonoBehaviour
{
  public GameObject go;   //  他のゲームオブジェクト(への参照)
  .....
}

上記のように、オブジェクト(への参照)変数を宣言し、Unity のエディタでスクリプトをインスペクタで見ると、下図のように、プロパティが増えている。
そこに紐付けたいオブジェクトをドラッグ&ドロップすればよい。

temp

あとは、その変数を利用するだけだ。

  go.transform.position = new Vector3(2f, 0.5f, -2f);  //  位置を指定