どうも、この度大学生になりました、drumathです。
さて、今回はUnityについての記事を書こうと思います。とはいえほんの小ネタですが、どうぞお付き合いください。
#砲台?
3Dゲームだと、敵を撃ったりするモーションがよくあるじゃないですか。そんなものを作りたいと考えまして、自分なりに作ってみました。どんな砲台を作るのかというと、
- スペースキーを押すと弾が発射
- 弾は重力と当たり判定がついている(つまりCollisionとRigidbody)
- 砲台は左右の回転ができる
- スクリプトファイルは1つだけ
- オブジェクトはUnityで用意されている、Plane、Cylinder、Sphereを使う(置き換えることによって応用可能)
以上です。
#Unityにオブジェクトを置いていく
まずはオブジェクトを置いていきましょう。最初に必要なものは3個だけ、
ヒエラルキービューで右クリック→3D Object→Plane, Cylinder, Sphereを選択し、置きます。
3つのオブジェクトをそれぞれ、「ground」「battery」「ammunition」と名付けました。
テキトーにマテリアルも設定しておきます。
そしたら次に、砲台の発射口となるEmptyObjectをbatteryの子要素として作ります。このオブジェクトの位置を複製した砲弾オブジェクトの初期値として渡します。
次に、ammunitionオブジェクトに、Rigidbodyをアタッチします。設定はデフォルトのままで。好みでCollisionにPhysicsMaterialを設定してみてもいいと思います。私は反発係数をつけたかったのでそうしました。それができたら、ヒエラルキービューからアセットのほうへD&Dしてプレハブ化しましょう。これで砲弾の設定が終わりました。
次に、batteryオブジェクトにC#スクリプトをアタッチします。名前は「batteryController」にしました。
#C#スクリプをを書いていく
先ほどbatteryにアタッチした、スクリプトを以下のように編集しました。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class batteryController : MonoBehaviour {
public GameObject port; // 発射口
public GameObject ammunition; // 砲弾オブジェクト
public float forceStrength; // 打ち出す力の強さ
void Start () {
}
void Update () {
// 砲弾を複製して打ち出す処理
if(Input.GetKeyDown(KeyCode.Space)){
GameObject g = Instantiate(ammunition, port.transform.position, port.transform.rotation);
g.GetComponent<Rigidbody>().AddForce(g.transform.up * forceStrength, ForceMode.Impulse);
Destroy(g, 5.0f);
}
// 左右回転処理
if(Input.GetKey(KeyCode.RightArrow)){
transform.Rotate(0,0,-1);
}
else if(Input.GetKey(KeyCode.LeftArrow)){
transform.Rotate(0,0,1);
}
}
}
わずか40行にも満たないコードですが、これで左右回転する砲台のスクリプトが完成しました。
補足をします。
public GameObject port;
public GameObject ammunition;
public float forceStrength;
うえの3つの変数はすべてPublicな変数ですので、あとでUnity上で格納してやる必要があります。
port
には砲台の子要素に設定した発射口のEmptyObjectを入れてください。
ammunition
にはプレハブ化したammunitionオブジェクトをD&Dして格納します。
forceStrength
には好みの強さをUnity上で入れてください。なんかオブジェクトが生成されるけど打ち出されない・・・なんて時にはこいつの設定が小さすぎるか、設定してないかだと思います。
if(Input.GetKeyDown(KeyCode.Space)){
GameObject g = Instantiate(ammunition, port.transform.position, port.transform.rotation);
g.GetComponent<Rigidbody>().AddForce(g.transform.up * forceStrength, ForceMode.Impulse);
Destroy(g, 5.0f);
}
次にUpdate()の中身ですが、
まず、一行目ではスペースが押されたら発火するような条件が組まれています。
2行目はInstantiate()
を使ってammutionオブジェクトをportの位置で複製しています。これを変数g
に格納します。
3行目では、先ほど複製したオブジェクト、gに瞬間的な力積を与えることで飛ばします。その方向はtransform.up
つまり上方向です。
4行目では、gをDestroy関数で削除していますが、よくみると、第2引数に5が設定されています。これは5秒後に削除するという意味です。実際これもpublicな変数にすればあとから変更も利きますね。お好みでどうぞ。
if(Input.GetKey(KeyCode.RightArrow)){
transform.Rotate(0,0,-1);
}
else if(Input.GetKey(KeyCode.LeftArrow)){
transform.Rotate(0,0,1);
}
ここはわかりやすいですよね。左右の矢印キーが押されている間、指定の方向に回転しているだけです。