武器のステータス
CoddyのUnityジャーニー「Unityにおけるゲームアーキテクチャ」セクションの一部。レッスン 20/50。
剣とハンマーは同じ動きをします。振り、待ち、また振ります。違いは数値です。剣は4のダメージを与え、0.5秒ごとに振ります。ハンマーは10のダメージを1.5秒ごとに与えます。つまり、どちらにも同じWeaponスクリプトを使い、それぞれの武器の数値はアセットに保存します。
[CreateAssetMenu(menuName = "Combat/Weapon Data")]
public class WeaponData : ScriptableObject
{
public string weaponName;
public int damage;
public float swingTime;
public GameObject hitEffect;
}public class Weapon : MonoBehaviour
{
public WeaponData data;
private float nextSwing;
public void Swing(Health target)
{
if (Time.time < nextSwing) return;
nextSwing = Time.time + data.swingTime;
target.TakeDamage(data.damage);
Instantiate(data.hitEffect, target.transform.position, Quaternion.identity);
}
}プロジェクトには、Swordアセット(4、0.5、火花のプレハブ)とHammerアセット(10、1.5、砂ぼこりのプレハブ)があります。騎士とオーガはどちらもWeaponスクリプトを持っています。騎士のdataフィールドにはSwordが、オーガのフィールドにはHammerが設定されています。Createメニューから槍のアセットをもうひとつ作ればよく、スクリプトを変更する必要はありません。アセットはhitEffectのようにプレハブやほかのアセットを参照できますが、シーン内のオブジェクトは参照できません。アセットはプロジェクト内にあり、どのシーンにも属していないためです。
武器ごとに数値を変えるほかの方法では、どれも数値をコードに記述します。if (weaponName == "Sword") damage = 4; else if ...は武器が増えるたびに長くなります。また、数値を設定するだけのWeaponのサブクラスSwordを作ると、アセットごとにクラスが必要になります。サブクラスは、矢を放つ弓のように、武器の動作が異なる場合に使います。単にダメージが大きい、または振る速度が速いだけの武器なら、専用のアセットを用意すればよく、コードは必要ありません。
チャレンジ
中級射撃場には4種類の銃があります。ピストルが2丁、ライフルが1丁、新しいブラスターが1丁です。Spaceを押し続けると、すべて発射されます。GunスクリプトはgunTypeに対するif/elseを使って弾丸、発射間隔、ダメージを選びますが、ブラスターはその中にないため発射されません(Consoleを確認してください)。
すべての銃がアセットから数値を読み取るようにしてください。GunData.csは準備済みで、そこから作成したPistol、Rifle、Blasterのアセットがプロジェクトにあり、それぞれに専用の弾丸プレハブが設定されています。
GunにGunData型のpublicフィールドdataを追加します。Inspectorで各銃のアセットを割り当てます。data.bulletPrefabを発射し、発射の間隔をdata.fireIntervalにして、各弾丸にdata.damageを設定します。gunType、2つの弾丸フィールド、privateなコピー、およびif/elseを削除します。
再生を押してSpaceを押し続け、その後確認を押します。
自分で試してみよう
using UnityEngine;
using UnityEngine.InputSystem;
public class Gun : MonoBehaviour
{
public string gunType = "Pistol";
public GameObject pistolBullet;
public GameObject rifleBullet;
private GameObject bulletPrefab;
private float fireInterval;
private int damage;
private float nextShot;
void Start()
{
if (gunType == "Pistol")
{
bulletPrefab = pistolBullet;
fireInterval = 0.25f;
damage = 1;
}
else if (gunType == "Rifle")
{
bulletPrefab = rifleBullet;
fireInterval = 0.6f;
damage = 4;
}
}
void Update()
{
if (Keyboard.current.spaceKey.isPressed && Time.time >= nextShot)
{
nextShot = Time.time + fireInterval;
GameObject bullet = Instantiate(bulletPrefab, transform.position + transform.forward, transform.rotation);
bullet.GetComponent<Bullet>().damage = damage;
}
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。