●Rigidbody
…重なっているものを「弾く」性質がある。
止まっているもの同士の接触や重なりには反応しない。
片方が動いていれば判定はされる。
●弾を動かすときー
①Rigidbodyで加速度をつける or ②Positionをいじる
①の方が簡単。とりあえずこの例を作ってみる。
using Unity.Collections;
using UnityEngine;
public class Player : MonoBehaviour
{
[Header("---Bullet Settings---")]
public GameObject bulletPrefab;
public float shotPower = 10f;
[HideInInspector] public Rigidbody2D bulletRb; // Rigidbodyの参照
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
GameObject bullet = Instantiate(bulletPrefab, new Vector3(0, 0, 0), Quaternion.identity);//複製されたオブジェクトをbulletで受ける
bulletRb = bullet.GetComponent<Rigidbody2D>(); // Rigidbody2Dを取得してbulletRbに代入
//AddForce(飛ばす方向と力、飛ばすときのモード指定)
bulletRb.AddForce(new Vector2(0, 1)*shotPower, ForceMode2D.Impulse); // Rigidbody2Dに力を加える
}
}
}
AddForceの第二引数
⇒ForceMode:徐々に力を加える
⇒ImpulseMode:一気に力を加える
GameObjectを追加(Square)して、Enemyにリネーム。
BoxCollider2DとRigidbody2Dをアタッチ。GravityScaleを0に。

Enemy.csスクリプトを作成。
OnCollisionEnter2Dを追加。
using UnityEngine;
public class Enemy : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
}
//Collider同士が接触した”瞬間(フレーム)”に実行される関数
void OnCollisionEnter2D(Collision2D collision)
{
Debug.Log($"HIT!...");
}
}
OnCollisionEnter2D:Collider同士が接触した瞬間(フレーム)だけに実行
OnCollisonStay2D:Collider同士が接触している(フレーム)の間実行し続ける
OnCollisionExit2D:Collider同士が”離れた瞬間(フレーム)”実行される。
上記スクリプトをEnemyオブジェクトにアタッチして、弾を当ててみる。

Consoleに”HIT”が表示された。
using UnityEngine;
public class Enemy : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
}
//Collider同士が接触した”瞬間(フレーム)”に実行される関数
void OnCollisionEnter2D(Collision2D collision)
{
//OnCollisionEnter2D内の引数であるcollisionには、衝突したオブジェクトの情報(Collision2D)が入る
Debug.Log($"HIT!...{collision.transform.name}");
Destroy(gameObject);//接触で削除される
Destroy(collision.gameObject);//接触した相手のオブジェクトも削除する
}
}
このようにcollisionで、衝突した相手の情報を引いてきて、様々な処理を行うのがゲーム制作の基本。
ゲームパッドを使いたい場合、InputSystemーInputAcctionで検索してみる。
using Unity.Collections;
using UnityEngine;
public class Player : MonoBehaviour
{
[Header("---Bullet Settings---")]
public GameObject bulletPrefab;
public float shotPower = 10f;
[HideInInspector] public Rigidbody2D bulletRb; // Rigidbodyの参照
void Update()
{
if (Input.GetKey(KeyCode.LeftArrow)|Input.GetKey(KeyCode.A))
{
transform.Translate(-1, 0, 0);
}
if (Input.GetKey(KeyCode.RightArrow)|Input.GetKey(KeyCode.D))
{
transform.Translate(1, 0, 0);
}
if (Input.GetKeyDown(KeyCode.Space))
{
GameObject bullet = Instantiate(bulletPrefab, new Vector3(0, 0, 0), Quaternion.identity);
bulletRb = bullet.GetComponent<Rigidbody2D>(); // Rigidbody2Dを取得してbulletRbに代入
//AddForce(飛ばす方向と力、飛ばすときのモード指定)
bulletRb.AddForce(new Vector2(0, 1) * shotPower, ForceMode2D.Impulse); // Rigidbody2Dに力を加える
}
}
}
上のコードでは、単位がフレーム/mなので、1フレームで1m動くことになる。
Time.deltaTimeを掛けることで時間の単位を1秒に変えることができる。
using Unity.Collections;
using UnityEngine;
public class Player : MonoBehaviour
{
[Header("---Base Parameter")]
public float moveSpeed = 5.0f;
[Header("---Bullet Settings---")]
public GameObject bulletPrefab;
public float shotPower = 10f;
[HideInInspector] public Rigidbody2D bulletRb; // Rigidbodyの参照
void Update()
{
if (Input.GetKey(KeyCode.LeftArrow)|Input.GetKey(KeyCode.A))
{
transform.Translate(moveSpeed*Time.deltaTime, 0, 0);
}
if (Input.GetKey(KeyCode.RightArrow)|Input.GetKey(KeyCode.D))
{
transform.Translate(moveSpeed*Time.deltaTime, 0, 0);
}
if (Input.GetKeyDown(KeyCode.Space))
{
GameObject bullet = Instantiate(bulletPrefab, new Vector3(0, 0, 0), Quaternion.identity);
bulletRb = bullet.GetComponent<Rigidbody2D>(); // Rigidbody2Dを取得してbulletRbに代入
//AddForce(飛ばす方向と力、飛ばすときのモード指定)
bulletRb.AddForce(new Vector2(0, 1) * shotPower, ForceMode2D.Impulse); // Rigidbody2Dに力を加える
}
}
}
これで左右に動ける…が、プレイヤーが動いても同じ位置から発射される。
Instantiateの場所をプレイヤーの座標に変更する。
(Player.cs)
using Unity.Collections;
using Unity.VisualScripting;
using UnityEngine;
public class Player : MonoBehaviour
{
[Header("---Base Parameter")]
public float moveSpeed = 5.0f;
[Header("---Bullet Settings---")]
public GameObject bulletPrefab;
public float shotPower = 10f;
[HideInInspector] public Rigidbody2D bulletRb; // Rigidbodyの参照
void Update()
{
if (Input.GetKey(KeyCode.LeftArrow)|Input.GetKey(KeyCode.A))
{
transform.Translate(-moveSpeed*Time.deltaTime, 0, 0);
}
if (Input.GetKey(KeyCode.RightArrow)|Input.GetKey(KeyCode.D))
{
transform.Translate(moveSpeed*Time.deltaTime, 0, 0);
}
if (Input.GetKeyDown(KeyCode.Space))
{
GameObject bullet = Instantiate(bulletPrefab, this.transform.position, Quaternion.identity);
bulletRb = bullet.GetComponent<Rigidbody2D>(); // Rigidbody2Dを取得してbulletRbに代入
//AddForce(飛ばす方向と力、飛ばすときのモード指定)
bulletRb.AddForce(new Vector2(0, 1) * shotPower, ForceMode2D.Impulse); // Rigidbody2Dに力を加える
}
}
}
なお、”This”は省略可能で、省略した場合には、自分がアタッチされているオブジェクトのコンポーネントを参照する。
「プレイヤーが動く」
「弾を撃つ」
「弾に当たったら敵が止まる」
この要素がシューティングの骨格。これを改造していく。
次は、敵を増やしていく。
using UnityEditor.VersionControl;
using UnityEngine;
public class Spawner : MonoBehaviour
{
[Header("---Spawn Setting---")]
public GameObject enemyPrefab;
[Header("---Spawn Timer")]
public float timeLimit = 1.0f;
public float timer = 0.0f;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
timer += Time.deltaTime;//一秒で一加算。
if (timer >= timeLimit)
{
Instantiate(enemyPrefab, transform.position, Quaternion.identity);
timer = 0.0f;
}
}
}
Unityでは、fpsが一定ではないので、Time.deltaTimeを使って、時間で管理するのが普通。
SpawnerオブジェクトにSpawner.csをアタッチして、InspectorにEnemy.Prefabをアタッチするのも忘れずに。

コメント