Menu
CoddyTech

Характеристики оружия

Часть раздела Архитектура игр в 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, который только задаёт числа, означает отдельный класс для каждого ресурса. Подклассы нужны для оружия, которое действует иначе, например для лука, стреляющего стрелами. Оружию, которое только наносит больше урона или бьёт быстрее, нужен собственный ресурс, а не код.

challenge icon

Задание

Средне

На стрельбище есть четыре пушки: два пистолета, винтовка и новый бластер. Удерживай 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;
        }
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Архитектура игр в Unity