Характеристики оружия
Часть раздела Архитектура игр в Unity путешествия по Unity на Coddy. Урок 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 ... разрастается с каждым новым оружием, а подкласс Sword класса Weapon, который только задаёт числа, означает отдельный класс для каждого ресурса. Подклассы нужны для оружия, которое действует иначе, например для лука, стреляющего стрелами. Оружию, которое только наносит больше урона или бьёт быстрее, нужен собственный ресурс, а не код.
Задание
СреднеНа стрельбище есть четыре пушки: два пистолета, винтовка и новый бластер. Удерживай Space, чтобы стрелять из них. Скрипт Gun выбирает пулю, интервал стрельбы и урон с помощью if/else на основе gunType, а бластера в нём нет, поэтому он не стреляет (посмотри на Console).
Сделай так, чтобы каждая пушка считывала свои параметры из ресурса. GunData.cs уже готов, и в проекте есть созданные на его основе ресурсы Pistol, Rifle и Blaster, каждый со своим префабом пули.
- Добавь в
Gunпубличное полеdataтипа GunData; в Inspector для каждой пушки укажи её ресурс. - Стреляй из
data.bulletPrefab, ждиdata.fireIntervalмежду выстрелами и задавай каждой пуле уронdata.damage. - Удали
gunType, оба поля пуль, их приватные копии и if/else.
Нажми Play и удерживай Space, затем нажми Check.
Попробуйте сами
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
1Компоненты, а не иерархии
Небольшие компонентыБазовый скрипт врагаАбстрактные компонентыСовместная работа компонентовПовторение: модульная турель4Сериализованные данные
Сериализуемые классыСписки в InspectorПеречисления в InspectorПовторение: таблица лута2Интерфейсы в Unity
IDamageableИнтерфейсы и TryGetComponentGetComponentsПовторение: клавиша взаимодействия5ScriptableObjects
Ресурсы данныхХарактеристики оружияОбщие настройкиВолны как данныеПовторение: база предметов