武器のステータス
CoddyのUnityジャーニー「Unityのゲームアーキテクチャ」セクションの一部。レッスン 24/64。
剣もハンマーも、振って、待って、また振るという動作は同じです。違うのは数値です。剣は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、火花のPrefab)とHammerアセット(10、1.5、土煙のPrefab)があります。騎士もオーガもWeaponスクリプトを持っています。騎士のdataフィールドにはSwordが、オーガのフィールドにはHammerが設定されています。Createメニューから作成するだけで、槍ももう1つのアセットとして追加できます。スクリプトを変更する必要はありません。アセットはhitEffectのようにPrefabやほかのアセットを参照できますが、シーン内のオブジェクトは参照できません。アセットはプロジェクト内にあり、どのシーンにも属さないためです。
武器ごとに数値を変える別の方法では、どちらも数値をコード内に記述します。if (weaponName == "Sword") damage = 4; else if ...は武器が増えるたびに膨らんでいきます。また、数値を設定するだけのWeaponのサブクラスSwordを作ると、アセットごとにクラスが必要になります。サブクラスを使うのは、矢を放つ弓のように、武器の動作が異なる場合です。より強いダメージを与える、またはより速く振るだけの武器なら、専用のアセットを用意すればよく、コードは必要ありません。
チャレンジ
中級すべての銃が、GunDataアセットから数値を読み込むようにします。
Gunにpublic GunData data;を追加します。data.bulletPrefabを発射し、各ショットの間にdata.fireIntervalだけ待ち、各弾丸にdata.damageを設定します。gunType、2つの弾丸フィールド、3つのプライベートコピー、そしてStart()を削除します。
「プレイ」を押して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;
}
}
}
Unityのゲームアーキテクチャのすべてのレッスン
自分で練習してみよう: Unityプレイグラウンド