Задание
Разработать 2D-игру «Zombie Attack 2D» в жанре RPG . RPG Zombie Attack 2D — это мрачная 2D RPG с элементами экшена и выживания, где ты управляешь сразу двумя героями: разумным зомби и человеком, оказавшимися по разные стороны апокалипсиса… но вынужденными действовать вместе.
После вспышки вируса мир погрузился в хаос. Один из заражённых сохранил разум — и теперь он сражается не только с ордами мутантов, но и с собственной природой. Рядом с ним — человек, для которого каждый бой может стать последним.
Особенности игры:
-
💀 Два героя — одна судьба Переключайся между человеком и разумным зомби. Если один погибает — второй продолжает бой. Игроки менются автоматически в зависмости от результата.
-
⚔️ Боевая система Сражайся в ближнем бою, используй оружие и выживай против усиливающихся волн зомби.
-
🧟 Сцена сражений - отдельная боевая сцена с противниками, обладающие разными характеристиками силы, здоровья и урона.
-
🎒 Инвентарь и магазин
Цель игры:
Выжить в мире, где нет чёткой границы между человеком и монстром. Используй силу обоих героев, чтобы пройти через самые опасные битвы и приблизиться к разгадке вируса.
Фрагмент программного кода
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class BattleManager : MonoBehaviour
{
public GameObject enemyObject;
public GameObject playerObject;
public Sprite[] enemySprite;
public Sprite[] playerSprite;
public Text PlayerHP;
public Text EnemyHP;
public bool EnemyDie;
public bool PlayerDie;
public BattleState CurrState = BattleState.Battle_Start;
public EnemyClass enemyProfile;
public CharacterClass playerProfile;
public bool playerAttacking;
//public int playerRounds = 0;
//public int enemyRounds = 0;
//public int currentRound = 1;
//public int roundsToWin = 3; // best of 3
// Start is called before the first frame update
void Start()
{
//EnemyDie = false;
//PlayerDie = false;
//playerAttacking = false;
//CurrState = BattleState.Player_Attack;
//playerRounds = 0;
//enemyRounds = 0;
//currentRound = 1;
if (GameState.CurrPlayer.RightHand != null)
{
Debug.Log(GameState.CurrPlayer.RightHand.power);
}
enemyProfile = ScriptableObject.CreateInstance<EnemyClass>();
enemyProfile.type = GameState.CurrEnemy;
if (GameState.CurrEnemy == EnemyType.Zombie_1)
{
enemyObject.GetComponent<SpriteRenderer>().sprite = enemySprite[0];
enemyProfile.hp = 5;
enemyProfile.defense = 0;
enemyProfile.damage = 1;
}
else if (GameState.CurrEnemy == EnemyType.Zombie_2)
{
enemyObject.GetComponent<SpriteRenderer>().sprite = enemySprite[1];
enemyProfile.hp = 5;
enemyProfile.defense = 0;
enemyProfile.damage = 2;
}
else if (GameState.CurrEnemy == EnemyType.Zombie_3)
{
enemyObject.GetComponent<SpriteRenderer>().sprite = enemySprite[2];
enemyProfile.hp = 5;
enemyProfile.defense = 0;
enemyProfile.damage = 3;
}
else if (GameState.CurrEnemy == EnemyType.Zombie_4)
{
enemyObject.GetComponent<SpriteRenderer>().sprite = enemySprite[3];
enemyProfile.hp = 5;
enemyProfile.defense = 0;
enemyProfile.damage = 3;
}
else if (GameState.CurrEnemy == EnemyType.Boss_Enemy)
{
enemyObject.GetComponent<SpriteRenderer>().sprite = enemySprite[4];
enemyProfile.hp = 5;
enemyProfile.defense = 0;
enemyProfile.damage = 5;
}
playerProfile = ScriptableObject.CreateInstance<CharacterClass>();
playerProfile.Type = GameState.CurrPlayer.Type;
if (GameState.CurrPlayer.Type == CharacterType.Character_1)
{
playerObject.GetComponent<SpriteRenderer>().sprite = playerSprite[0];
playerProfile.hp = 5;
playerProfile.defense = 0;
playerProfile.damage = 0;
}
else if (GameState.CurrPlayer.Type == CharacterType.Character_2)
{
playerObject.GetComponent<SpriteRenderer>().sprite = playerSprite[1];
playerProfile.hp = 5;
playerProfile.defense = 0;
playerProfile.damage = 0;
}
}
public void StartAttack()
{
//Debug.Log("Attack button pressed");
CurrState = BattleState.Player_Attack;
playerAttacking = true;
}
// Update is called once per frame
void Update()
{
// --- НОВАЯ ЛОГИКА ПАУЗЫ ---
// Если игра на паузе и битва еще не закончилась - стоп машина!
if (PauseManager.IsGamePaused && CurrState != BattleState.Battle_End)
{
return; // Просто выходим из метода. Ничего не обновляем.
}
// --------------------------------
PlayerHP.text = "Player HP: " + GameState.CurrPlayer.hp;
EnemyHP.text = "Enemy HP: " + enemyProfile.hp;
switch (CurrState)
{
case BattleState.Battle_Start:
break;
case BattleState.Player_Attack:
if (playerAttacking && !PlayerDie)
{
AttackByPlayer();
}
break;
case BattleState.Enemy_Attack:
AttackByEnemy();
break;
case BattleState.Battle_End:
break;
}
//Debug.Log("State: " + CurrState);
}
public void AttackByPlayer()
{
GameState.CurrPlayer.AttackWithItems(enemyProfile);
playerAttacking = false;
CurrState = BattleState.Enemy_Attack;
CheckForDeath();
}
public void AttackByEnemy()
{
enemyProfile.Attack(GameState.CurrPlayer);
CurrState = BattleState.Player_Attack;
CheckForDeath();
}
public void CheckForDeath()
{
if (enemyProfile.hp <= 0)
{
enemyProfile.hp = 0;
EnemyDie = true;
CurrState = BattleState.Battle_End;
Debug.Log("Player win");
}
else if (GameState.CurrPlayer.hp <= 0)
{
GameState.CurrPlayer.hp = 0;
PlayerDie = true;
CurrState = BattleState.Battle_End;
Debug.Log("Enemy win");
}
}
//public void CheckForDeath()
//{
// if (enemyProfile.hp <= 0)
// {
// enemyProfile.hp = 0;
// playerRounds++;
// Debug.Log("Player win round " + currentRound);
// NextRoundOrEnd();
// }
// else if (GameState.CurrPlayer.hp <= 0)
// {
// GameState.CurrPlayer.hp = 0;
// enemyRounds++;
// Debug.Log("Enemy win round " + currentRound);
// NextRoundOrEnd();
// }
//}
//void NextRoundOrEnd()
//{
// Debug.Log("Score: " + playerRounds + " - " + enemyRounds);
// // победа игрока
// if (playerRounds >= roundsToWin)
// {
// EnemyDie = true;
// CurrState = BattleState.Battle_End;
// Debug.Log("Player WIN battle");
// return;
// }
// // победа врага
// if (enemyRounds >= roundsToWin)
// {
// PlayerDie = true;
// CurrState = BattleState.Battle_End;
// Debug.Log("Enemy WIN battle");
// return;
// }
// // следующий раунд
// currentRound++;
// Debug.Log("Start Round " + currentRound);
// ResetRound();
//}
//void ResetRound()
//{
// // сброс HP игрока
// GameState.CurrPlayer.hp = GameState.CurrPlayer.maxHP;
// // сброс HP врага (по типу заново)
// if (GameState.CurrEnemy == EnemyType.Zombie_1)
// enemyProfile.hp = 5;
// else if (GameState.CurrEnemy == EnemyType.Zombie_2)
// enemyProfile.hp = 5;
// else if (GameState.CurrEnemy == EnemyType.Zombie_3)
// enemyProfile.hp = 5;
// else if (GameState.CurrEnemy == EnemyType.Zombie_4)
// enemyProfile.hp = 5;
// else if (GameState.CurrEnemy == EnemyType.Boss_Enemy)
// enemyProfile.hp = 6;
// // возвращаем управление игроку
// CurrState = BattleState.Player_Attack;
// playerAttacking = false;
//}
public void OnGUI()
{
if (EnemyDie)
{
GUI.BeginGroup(new Rect(Screen.width / 2 - 150, 50, 300, 250));
GUI.Box(new Rect(0, 0, 300, 250), "");
GUI.Label(new Rect(5, 10, 300, 68), "Поздравляем, Вы победили!!!");
if (GUI.Button(new Rect(55, 100, 180, 40), "ОК"))
{
//PlayerPrefs.SetInt("BattleEnd", 1);
SceneManager.LoadScene("Cemetery");
}
GUI.EndGroup();
}
if (PlayerDie)
{
GUI.BeginGroup(new Rect(Screen.width / 2 - 150, 50, 300, 250));
GUI.Box(new Rect(0, 0, 300, 250), "");
GUI.Label(new Rect(5, 10, 300, 68), "Вы потерпели неудачу!!!");
if (GUI.Button(new Rect(55, 100, 180, 40), "ОК"))
{
// смена персонажа при смерти
if (GameState.CurrPlayer.Type == CharacterType.Character_1)
GameState.CurrPlayer.Type = CharacterType.Character_2;
else
GameState.CurrPlayer.Type = CharacterType.Character_1;
GameState.CurrPlayer.hp = GameState.CurrPlayer.maxHP;
//PlayerPrefs.SetInt("BattleEnd", 1);
SceneManager.LoadScene("Cemetery");
}
GUI.EndGroup();
}
}
}
Скриншот архива с проектом
Пояснения по запуску программы
▶️ Инструкция по запуску игры
📦 Установка
-
Скачайте архив с игрой.
-
Распакуйте его в любую удобную папку (например, на Рабочий стол).
🚀 Запуск
-
Откройте папку с игрой.
-
Найдите файл ZombieAttack.exe
-
Запустите его двойным кликом.
⚙️ Важно
-
Не удаляйте файлы рядом с
.exe(папку Data и другие) — без них игра не запустится. -
Если появляется предупреждение Windows — нажмите “Подробнее” → “Выполнить в любом случае”.
🎮 Управление
-
Стрелки (← →) — движение
-
Кнопка атаки — бой
-
I — открыть инвентарь
-
M — меню паузы
❗ Возможные проблемы
-
Игра не запускается → Проверьте, не заблокировал ли антивирус
-
Чёрный экран или вылет → Попробуйте запустить от имени администратора
🛠️ Инструкция по запуску проекта (Unity)
📦 Требования
Перед запуском проекта необходимо установить:
-
Unity Hub
-
Unity Editor версии 6.3 LTS
-
Visual Studio Community 2022 или Visual Studio Community 2026
📌 Важно: При установке Visual Studio выбрать:
-
Разработка игр с Unity
⚙️ Установка Unity Editor
-
Откройте Unity Hub
-
Перейдите во вкладку Installs
-
Нажмите Install Editor
-
Выберите версию 6.3 LTS
-
На этапе установки выберите платформы:
-
Windows Build Support
-
(при необходимости) Android Build Support
-
(при необходимости) iOS Build Support
📌 Важно: Unity Hub не содержит Editor по умолчанию — его нужно установить отдельно вместе с нужными модулями.
📂 Открытие проекта
-
Скачайте архив с проектом
-
Распакуйте его
-
Откройте Unity Hub
-
Нажмите Add (Добавить проект)
-
Укажите папку проекта
-
Нажмите Open (Открыть)
▶️ Запуск проекта
-
Дождитесь импорта файлов
-
Откройте основную сцену: City
-
Нажмите кнопку ▶ Play
⚠️ Важно
-
Не удаляйте папки:
-
Assets -
ProjectSettings -
Packages
-
-
При запросе обновления проекта нажмите Confirm / Continue
❗ Возможные проблемы
-
Проект не открывается → Проверьте установлен ли нужный Unity Editor
-
Скрипты не открываются → Проверьте установку Visual Studio Community 2022 или Visual Studio Community 2026
-
Ошибки в консоли → Очистите Console (Clear) и перезапустите сцену
🎮 Дополнительно
-
Основная сцена: City
-
В игре реализованы:
-
два персонажа (человек и разумный зомби)
-
автоматическая смена персонажа при смерти
-
инвентарь и магазин
-
отдельная боевая сцена
-
Телеграм
-