銃のオブジェクトがマガジンのオブジェクトを持つようにして、簡単に弾の種類を切り替えてみました。
まず、マガジンと弾のクラスを作って、それらを継承した赤い弾の入ったマガジンクラスと青い弾の入ったマガジンクラスを作りました。
弾のクラスでは弾を飛ばす力と発射メソッドを定義しています。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(Collider))]
public class Bullet : MonoBehaviour
{
[SerializeField] float power = 20f;
// Start is called before the first frame update
void Start()
{
Destroy(gameObject, 4f);
}
public void Shoot()
{
Rigidbody rb = GetComponent<Rigidbody>();
rb.AddForce(transform.forward * power, ForceMode.Impulse);
}
}
これを継承した二種類の弾クラスを作って、シーン上のSphereにアタッチしてプレハブ化しておきます。インスペクタで弾の種類毎に違った値を設定できます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RedBullet : Bullet
{
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BlueBullet : Bullet
{
}
マガジンクラスは弾のプレハブと弾数のデータを持っていて、射撃メソッドが呼ばれると弾をインスタンス化して、弾のメソッドを呼びます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Magazine : MonoBehaviour
{
[SerializeField] Bullet bullet;
[SerializeField] int count = 20;
public int GetCount()
{
return count;
}
public bool Shoot()
{
if (count > 0)
{
Bullet b = Instantiate(bullet, Player2.GetInstance().transform.position + Player2.GetInstance().transform.forward * 1.5f, Player2.GetInstance().transform.rotation).GetComponent<Bullet>();
b.Shoot();
count--;
GameScript3.GetInstance().SetBulletCount(this);
return true;
}
else
{
return false;
}
}
}
これを継承したマガジンクラスを二種類作りました。今回はこれらを空のゲームオブジェクトにアタッチしてシーンに配置しました。インスペクタで弾の種類と残弾数を個別に設定できます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RedMagazine : Magazine
{
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BlueMagazine : Magazine
{
}
銃のクラスを作るためにまずは武器の抽象クラスを作りました。このクラスでは、マウスクリックしたときとクリックを放した時に呼ぶメソッドと寿命を作りました。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
abstract public class Weapon : MonoBehaviour
{
abstract public void StartAttack();
abstract public void StopAttack();
[SerializeField] protected float lifespan = 1f;
public float GetLifespan()
{
return lifespan;
}
}
そして、これを継承した小火器クラスを作りました。小火器クラスではマガジンと発射メソッドを定義します。マガジンは自由に入れ替えられます。とりあえずマウスクリックされると一度発射メソッドを呼んで、放すと何もしないようにしました。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SmallArms : Weapon
{
[SerializeField] Magazine magazine;
public void SetMagazine(Magazine m)
{
magazine = m;
}
public Magazine GetMagazine()
{
return magazine;
}
protected void Shoot()
{
if (magazine == null) return;
if (magazine.Shoot())
{
lifespan -= 0.01f;
}
}
public override void StartAttack()
{
Shoot();
}
public override void StopAttack()
{
}
}
弾が発射されると武器の寿命を少し減らします。
さらにこれを継承したハンドガンクラスとマシンガンクラスを作りました。これらも空のゲームオブジェクトにアタッチしてシーンに置きました。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HandGun1 : SmallArms
{
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MachineGun1 : SmallArms
{
WaitForSeconds wait;
[SerializeField] float rate = 0.1f;
private void Awake()
{
wait = new WaitForSeconds(rate);
}
public override void StartAttack()
{
StartCoroutine("RapidFire");
}
public override void StopAttack()
{
StopCoroutine("RapidFire");
}
IEnumerator RapidFire()
{
while (true)
{
Shoot();
yield return wait;
}
}
}
マシンガンクラスでは、連射コルーチンの繰り返し処理の中で発射メソッドを呼び、マウスクリックで連射を開始、放すと停止します。ハンドガンには無い連射速度のフィールドもあります。
プレイヤーの頭に付けたスクリプトで武器クラスの入れ替えと攻撃を行います。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player2 : MonoBehaviour
{
[SerializeField] Weapon weapon;
public void SetWeapon(Weapon w)
{
weapon = w;
}
public Weapon GetWeapon()
{
return weapon;
}
static Player2 instance;
public static Player2 GetInstance()
{
return instance;
}
// Start is called before the first frame update
void Start()
{
instance = this;
}
// Update is called once per frame
void Update()
{
if(Input.GetMouseButtonDown(0))
{
if (weapon != null) weapon.StartAttack();
}else if(Input.GetMouseButtonUp(0))
{
if (weapon != null) weapon.StopAttack();
}
}
}
今回はとりあえずキー入力で武器やマガジンを入れ替えます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GameScript3 : MonoBehaviour
{
[SerializeField] Magazine redMagazine;
[SerializeField] Magazine blueMagazine;
[SerializeField] Weapon handGun1;
[SerializeField] Weapon machineGun1;
[SerializeField] Text magazineText;
[SerializeField] Text weaponText;
static GameScript3 instance;
public static GameScript3 GetInstance()
{
return instance;
}
// Start is called before the first frame update
void Start()
{
instance = this;
magazineText.text = "";
weaponText.text = "";
}
// Update is called once per frame
void Update()
{
if(Input.GetKeyDown(KeyCode.Alpha1))
{
SmallArms g = (SmallArms)Player2.GetInstance().GetWeapon();
g.SetMagazine(redMagazine);
SetBulletCount(redMagazine);
}
else if (Input.GetKeyDown(KeyCode.Alpha2))
{
SmallArms g = (SmallArms)Player2.GetInstance().GetWeapon();
g.SetMagazine(blueMagazine);
SetBulletCount(blueMagazine);
}
else if(Input.GetKeyDown(KeyCode.E))
{
Player2.GetInstance().SetWeapon(handGun1);
weaponText.text = handGun1.name;
SetBulletCount((SmallArms)handGun1);
} else if(Input.GetKeyDown(KeyCode.Q))
{
Player2.GetInstance().SetWeapon(machineGun1);
weaponText.text = machineGun1.name;
SetBulletCount((SmallArms)machineGun1);
}
}
public void SetBulletCount(Magazine magazine)
{
magazineText.text = magazine.name + "\n" + magazine.GetCount().ToString();
}
void SetBulletCount(SmallArms smallArms)
{
SmallArms sa = smallArms;
Magazine m = sa.GetMagazine();
if (m == null)
{
magazineText.text = "";
}else
{
SetBulletCount(m);
}
}
}
これで武器やマガジンを簡単に入れ替えられるようになりました。武器オブジェクトがマガジンオブジェクトを持っているので、2種類の武器に別のマガジンオブジェクトを付けていれば、武器を切り替えると出る弾の種類も変わります。