このブログはUnityの初心者向けに、Untiyの機能の使い方、基本のスクリプトファイルの使い方から応用までをご説明しています。中級以上の方に読んでいただきたい内容も随時更新していますので、お時間がある方、検索でここにアクセスされた方はぜひ立ち寄っていってください。
前回の記事「スペースキーを押してプレハブで作られたミサイルを発射する方法」に引き続き、クローンを使ってオブジェクトを作成する方法をご紹介します。今回はスペースキーなど、任意のキーを押したときに、用意したミサイルのクローンからインスタンスを生成、さらにRigidbodyに力を与え前方に飛ばすという仕組みを作成します。
下の動画は「ファイブボックス 一分間Unity講座 クリックした座標に向けてミサイル発射」 のショート動画です。ご興味がございましたら、こちらの動画もご参照ください。
1,作成済みのプログラムの確認
前回まで、PrefabManagerクラスではスペースキーを押すとミサイルのプレハブが発射されるプログラム、さらに1秒間に1つずつ、ランダムな場所にCubeのプレハブが生成される仕組みも作成済みです。
PrefabManager.cs
[SerializeField] GameObject cubePrefab; //cubeのプレハブ
[SerializeField] GameObject bulletPrefab, battery;
float timer; //経過時間を管理する変数
void Update()
{
if (Input.GetKeyDown(KeyCode.Space)) //スペースキーが押されたとき
{
//bulletPrefabのPrefabを生成
GameObject bullet = Instantiate(bulletPrefab,
attery.transform.position, Quaternion.identity);
//Rigidbodyを取得し、AddForceMethodで前向きの力を加える
bullet.GetComponent<Rigidbody>().AddForce(transform.forward * 2000);
Destroy(bullet,3.0f); //3秒後に削除
}
timer += Time.deltaTime; //timerに経過時間を加算
if (timer > 1.0f) //timerが1秒を超えたら
{
//Vector3型の変数:pos を宣言、半径5の球体内のランダムな場所を指定
Vector3 pos = Random.insideUnitSphere * 5.0f;
//cubePrefabをposの座標に、回転無しで生成
Instantiate(cubePrefab, pos, Quaternion.identity);
timer = 0; //timerを0リセット
}
}
[SerializeField]で宣言した変数には、それぞれInspectorから以下のものをAssignしています。
BurretにはRigidbodyコンポーネントを追加、Cubeは素材のままで結構です。
Battery(砲台)のColliderは無効化しておきましょう。
詳しくは過去動画をご参照ください。
2,クリックした座標へのミサイル発射プログラム
クリックした座標を取得するには、メインカメラでスクリーン上のポイントを取得します。
事前にメインカメラを使用するための変数を宣言、Start関数で初期値を取得します。
Camera cam; //メインカメラ
void Start()
{
cam = Camera.main; //メインカメラを取得し代入
}
Update関数内では、マウスの左クリックが押されたらクリックされた場所にミサイルが発射されるプログラムを作成します。
void Update()
{
//マウスが左クリックされたとき
if(Input.GetMouseButtonDown(0))
{
//マウスの座標を取得
var mousePos=Input.mousePosition;
//カメラからの奥行きを10に設定
mousePos.z = 10.0f;
// スクリーン座標をワールド座標に変換
var targetPos = cam.ScreenToWorldPoint(mousePos);
// 弾を生成
GameObject bullet =
Instantiate(bulletPrefab, battery.transform.position,
uaternion.identity);
// クリックした位置へのベクトルを取得し標準化
var dir = (targetPos - battery.transform.position).normalized;
// Rigidbodyに力を加える(クリックした座標に2000の力で飛ばす)
bullet.GetComponent<Rigidbody>().AddForce(dir * 2000);
//弾を3秒後に削除
Destroy(bullet, 3.0f);
}
//以下記述済み(省略)
}
1. マウスの座標を取得
var mousePos = Input.mousePosition;
var(推論型)はVector3型になります。
Input.mousePosition: 現在のマウスのスクリーン座標を取得、マウスの位置は スクリーン座標(ピクセル単位)で表されます。
X: 画面の横方向の位置。
Y: 画面の縦方向の位置。
Z: スクリーン座標では未使用で、通常0。
2. カメラからの奥行きを10に設定
mousePos.z = 10.0f;
スクリーン座標のZ値を10に設定します。
ここでのZは、カメラから見た奥行き(深度) を意味し、変換するワールド座標が「カメラから10単位離れた位置」となります。
3. スクリーン座標をワールド座標に変換
var targetPos = cam.ScreenToWorldPoint(mousePos);
cam.ScreenToWorldPoint:
スクリーン座標(2D座標)をワールド座標(3D座標)に変換します。var はVector3型になります。 mousePosには、上で設定したZ=10.0f が含まれているため、カメラから10ユニット離れた位置に対応するワールド座標が計算されます。
4. 弾を生成
GameObject bullet = Instantiate(bulletPrefab, battery.transform.position, Quaternion.identity);
Instantiate:指定したInstanceを生成
bulletPrefab: (何を)弾として使用するプレハブ
battery.transform.position: (場所)弾を生成する位置
Quaternion.identity: (向き)回転なしで生成
5. クリックした位置への方向を計算
var dir = (targetPos - battery.transform.position).normalized;
var はVector3型になります。
targetPos - battery.transform.position: 弾を発射するためのベクトル(方向と距離)を計算。
targetPos: マウスのクリック位置のワールド座標(上で取得した座標)。
battery.transform.position: 砲台の位置。
.normalized: ベクトルを標準化(長さ1に調整)。方向だけを扱うため、距離の影響を除外。
6. Rigidbodyに力を加える
bullet.GetComponent<Rigidbody>().AddForce(dir * 2000);
bullet.GetComponent<Rigidbody>(): 弾のRigidbodyコンポーネントを取得。
AddForce(dir * 2000):
dir: クリックした位置への方向。
2000: 弾を飛ばす力の大きさ。値を調整することで弾のスピードが変動(任意値)。
7. 弾を一定時間後に削除
Destroy(bullet, 3.0f);
弾(bullet)を3秒後に削除します。
長時間残らないようにし、パフォーマンスの問題を防ぎます。
これでマウスクリックの場所に弾が飛ぶようになりました。
ファイブボックスでは、スクラッチやUnityの個別指導のオンラインレッスンを行っています。
Comments