Initial commit

This commit is contained in:
2026-05-11 20:48:41 +03:00
commit e35e9a07d5
229 changed files with 82642 additions and 0 deletions
+22
View File
@@ -0,0 +1,22 @@
using UnityEngine;
public class AudioManager : MonoBehaviour
{
[SerializeField] private AudioSource[] _grassBlockDestroySound;
private int _grassSoundIndex = 0;
public void PlayBlockDestroySound(BlockScript block)
{
switch (block.Type)
{
case BlockScript.BlockType.Grass:
case BlockScript.BlockType.PathFinish:
if (_grassBlockDestroySound == null)
return;
_grassBlockDestroySound[_grassSoundIndex].Play();
_grassSoundIndex = (_grassSoundIndex + 1) % _grassBlockDestroySound.Length;
break;
}
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 44efdad54537f514eb583c74783d7f0e
+63
View File
@@ -0,0 +1,63 @@
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
public class BlockDetector : MonoBehaviour
{
[SerializeField] private InputAction _clickAction;
[SerializeField] private UnityEvent<BlockScript> _onBlockClicked;
[SerializeField] private UnityEvent<BlockScript> _onBlockDetected;
public event UnityAction<BlockScript> OnBlockClicked
{
add => _onBlockClicked.AddListener(value);
remove => _onBlockClicked.RemoveListener(value);
}
public event UnityAction<BlockScript> OnBlockDetected
{
add => _onBlockDetected.AddListener(value);
remove => _onBlockDetected.RemoveListener(value);
}
private void OnEnable()
{
_clickAction.Enable();
_clickAction.performed += Click_performed;
}
private void OnDisable()
{
_clickAction.performed -= Click_performed;
_clickAction.Disable();
}
private void Click_performed(InputAction.CallbackContext context)
{
var clickPosition = Vector2.zero;
if (Touchscreen.current != null)
clickPosition = Touchscreen.current.position.ReadValue();
if (clickPosition == Vector2.zero)
clickPosition = Mouse.current.position.ReadValue();
var block = DetectBlockOnPosition(clickPosition);
if (block != null)
_onBlockClicked?.Invoke(block);
}
private BlockScript DetectBlockOnPosition(Vector2 position)
{
var ray = Camera.main.ScreenPointToRay(position);
if (Physics.Raycast(ray, out var hit) && hit.transform.CompareTag("GrassBlock"))
return hit.transform.GetComponent<BlockScript>();
return null;
}
private void Update()
{
var block = DetectBlockOnPosition(Mouse.current.position.ReadValue());
if (block != null)
_onBlockDetected?.Invoke(block);
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: bd2070fb0c6397f10b0302d1f156f6e6
+53
View File
@@ -0,0 +1,53 @@
using System.Collections.Generic;
using UnityEngine;
public class BlockScript : MonoBehaviour
{
public enum BlockType
{
None,
Grass,
Sand,
PathFinish
}
[SerializeField] private BlockType _type = BlockType.None;
public BlockType Type { get => _type; protected set => _type = value; }
public bool IsPath => _type is BlockType.Sand or BlockType.PathFinish;
public List<BlockScript> GetNeighbors()
{
var neighbors = new List<BlockScript>();
var ray = new Ray(transform.position, Vector3.up);
if (CheckNeighbor(ray, out var neighbor))
neighbors.Add(neighbor);
ray.direction = Vector3.forward;
if (CheckNeighbor(ray, out neighbor))
neighbors.Add(neighbor);
ray.direction = Vector3.right;
if (CheckNeighbor(ray, out neighbor))
neighbors.Add(neighbor);
ray.direction = Vector3.down;
if (CheckNeighbor(ray, out neighbor))
neighbors.Add(neighbor);
ray.direction = Vector3.back;
if (CheckNeighbor(ray, out neighbor))
neighbors.Add(neighbor);
ray.direction = Vector3.left;
if (CheckNeighbor(ray, out neighbor))
neighbors.Add(neighbor);
return neighbors;
}
private static bool CheckNeighbor(Ray ray, out BlockScript neighbor)
{
if (Physics.Raycast(ray, out var hit, 1f))
return hit.transform.TryGetComponent(out neighbor);
neighbor = null;
return false;
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8d6715c95501a4f49bd34c8832850f32
+36
View File
@@ -0,0 +1,36 @@
using UnityEngine;
public class BlockSelector : MonoBehaviour
{
[SerializeField] private BlockDetector _blockDetector;
[SerializeField] private Material _selectedMaterial;
private Renderer _selectedBlockRenderer;
private Material _oldMaterial;
private void OnEnable()
{
_blockDetector.OnBlockDetected += OnBlockDetected;
}
private void OnDisable()
{
_blockDetector.OnBlockDetected -= OnBlockDetected;
if (_selectedBlockRenderer != null)
{
_selectedBlockRenderer.material = _oldMaterial;
_selectedBlockRenderer = null;
}
}
private void OnBlockDetected(BlockScript block)
{
if (_selectedBlockRenderer != null)
_selectedBlockRenderer.material = _oldMaterial;
_selectedBlockRenderer = block.GetComponent<Renderer>();
_oldMaterial = _selectedBlockRenderer.material;
_selectedBlockRenderer.material = _selectedMaterial;
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3ae3ce76e48e194429448bf2071e7073
+13
View File
@@ -0,0 +1,13 @@
using UnityEngine;
public static class ComponentHelper
{
public static T GetComponentInChildrenWithoutParent<T>(this Component obj) where T : Component
{
foreach (var comp in obj.GetComponentsInChildren<T>())
if (comp.gameObject != obj.gameObject)
return comp;
return null;
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9575f79ebc216754fb44b8066ae811b2
+44
View File
@@ -0,0 +1,44 @@
using UnityEngine;
public class Debugger : MonoBehaviour
{
[SerializeField] private GameManager _gameManager;
[SerializeField] private SandPathBuildService _sandPathBuildService;
[SerializeField] private TurretsShop _turretShop;
private void OnEnable()
{
_gameManager.OnStateChanged += OnGameStateChanged;
_sandPathBuildService.OnBuildComplete += OnBuildComplete;
_turretShop.OnTurretSelected += OnTurretSelected;
_turretShop.OnTurretDeselected += OnTurretDeselected;
}
private void OnDisable()
{
_gameManager.OnStateChanged -= OnGameStateChanged;
_sandPathBuildService.OnBuildComplete -= OnBuildComplete;
_turretShop.OnTurretSelected -= OnTurretSelected;
_turretShop.OnTurretDeselected -= OnTurretDeselected;
}
private static void OnGameStateChanged(GameManager.GameState newState)
{
print("State changed, current state: " + newState);
}
private static void OnBuildComplete()
{
print("Build complete");
}
private static void OnTurretSelected(TurretShopItem item)
{
print("Turret selected: " + item.TurretPrefab.name);
}
private static void OnTurretDeselected()
{
print("Turret deselected");
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9f920e63c4a34e61a183a87c8c35d534
timeCreated: 1777495310
+89
View File
@@ -0,0 +1,89 @@
using UnityEngine;
using UnityEngine.Events;
using System.Collections.Generic;
public class Enemy : MonoBehaviour
{
[SerializeField] private SandPathBuildService _pathService;
[SerializeField] private float _health = 5f;
[SerializeField] private float _speed = 1f;
[SerializeField] private float _damage = 1f;
[SerializeField] private int _killReward = 10;
[SerializeField] private UnityEvent<float> _onHealthChanged;
[SerializeField] private UnityEvent<OnEnemyDeathEventArgs> _onDeath;
private Queue<Vector3> _path;
private Vector3 _target;
public event UnityAction<float> OnHealthChanged
{
add => _onHealthChanged.AddListener(value);
remove => _onHealthChanged.RemoveListener(value);
}
public event UnityAction<OnEnemyDeathEventArgs> OnDeath
{
add => _onDeath.AddListener(value);
remove => _onDeath.RemoveListener(value);
}
public SandPathBuildService PathBuildService
{
get => _pathService;
set => _pathService = value;
}
public float Health
{
get => _health;
private set
{
_health = value;
_onHealthChanged?.Invoke(value);
}
}
public float Damage { get => _damage; set => _damage = value; }
private void Start()
{
_path = new Queue<Vector3>(_pathService.GetPath());
_target = _path.Dequeue();
}
private void Update()
{
if (transform.position == _target)
{
if (_path.Count == 0) return;
_target = _path.Dequeue();
}
transform.position = Vector3.MoveTowards(transform.position, _target, _speed * Time.deltaTime);
transform.LookAt(_target);
}
private void OnTriggerEnter(Collider other)
{
if (!other.TryGetComponent(out TurretBullet bullet))
return;
TakeDamage(bullet.Damage);
Destroy(other.gameObject);
}
public void TakeDamage(float damage)
{
Health -= damage;
if (Health <= 0f)
{
_onDeath?.Invoke(new OnEnemyDeathEventArgs { KillReward = _killReward });
Destroy(gameObject);
}
}
public class OnEnemyDeathEventArgs
{
public int KillReward { get; set; }
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cc6b4f7ed5ed4fdbbcfc85d14e3e9ad9
timeCreated: 1774365562
+51
View File
@@ -0,0 +1,51 @@
using System;
using System.Collections;
using UnityEngine;
using System.Collections.Generic;
public class EnemySpawner : MonoBehaviour
{
[SerializeField] private GameManager _gameManager;
[SerializeField] private SandPathBuildService _pathBuildService;
[SerializeField] private Transform _enemyHolder;
[SerializeField] private Transform _spawnPoint;
[SerializeField] private Wallet _wallet;
//private readonly List<Enemy> _enemies = new();
private void Awake()
{
if (_gameManager == null)
_gameManager = FindAnyObjectByType<GameManager>();
if (_enemyHolder == null)
_enemyHolder = transform;
if (_spawnPoint == null)
_spawnPoint = transform;
}
private void OnEnable()
{
_gameManager.OnLevelChanged += OnLevelChanged;
}
private void OnDisable()
{
_gameManager.OnLevelChanged -= OnLevelChanged;
}
private void OnLevelChanged(Level level) => StartCoroutine(SpawnCoroutine(level));
private IEnumerator SpawnCoroutine(Level level)
{
var wait = new WaitForSeconds(level.LevelTimeSec / level.EnemiesPrefabs.Count);
foreach (var prefab in level.EnemiesPrefabs)
{
var enemy = Instantiate(prefab, _spawnPoint.position, _spawnPoint.rotation, _enemyHolder);
enemy.PathBuildService = _pathBuildService;
enemy.OnDeath += e => _wallet.AddMoney(e.KillReward);
//_enemies.Add(enemy);
yield return wait;
}
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8c18267efc955fbe3928becc91bf4ba3
+66
View File
@@ -0,0 +1,66 @@
using UnityEngine;
using UnityEngine.Events;
public class GameManager : MonoBehaviour
{
public enum GameState
{
BuildingPath,
BuildingTurrets,
Level
}
[SerializeField] private Level[] _levels;
[SerializeField] private SandPathBuildService _pathBuildService;
[SerializeField] private UnityEvent<GameState> _onStateChanged;
[SerializeField] private UnityEvent<Level> _onLevelChanged;
public event UnityAction<GameState> OnStateChanged
{
add => _onStateChanged.AddListener(value);
remove => _onStateChanged.RemoveListener(value);
}
public event UnityAction<Level> OnLevelChanged
{
add => _onLevelChanged.AddListener(value);
remove => _onLevelChanged.RemoveListener(value);
}
private int _currentLvlIndex = -1;
private GameState _currentState = GameState.BuildingPath;
public GameState CurrentState
{
get => _currentState;
set
{
_currentState = value;
_onStateChanged?.Invoke(value);
}
}
//public Level CurrentLevel => _levels[_currentLvlIndex];
private void OnEnable()
{
_pathBuildService.OnBuildComplete += OnBuildComplete;
}
private void OnDisable()
{
_pathBuildService.OnBuildComplete -= OnBuildComplete;
}
private void OnBuildComplete()
{
CurrentState = GameState.BuildingTurrets;
}
public void NextLevel()
{
_currentLvlIndex = (_currentLvlIndex + 1) % _levels.Length;
CurrentState = GameState.Level;
_onLevelChanged?.Invoke(_levels[_currentLvlIndex]);
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: aec3c0c64e4509b5db4d419ad4c5cc6b
+100
View File
@@ -0,0 +1,100 @@
using UnityEngine;
using UnityEngine.Events;
using System.Linq;
using System.Collections.Generic;
public class SandPathBuildService : MonoBehaviour
{
[SerializeField] private GameManager _gameManager;
[SerializeField] private BlockDetector _blockDetector;
[SerializeField] private BlockScript _blockPrefab;
[SerializeField] private BlockScript _grassBlockPrefab;
[SerializeField] private BlockScript _pathStart;
[SerializeField] private BlockScript _pathEnd;
[SerializeField] private BlockScript[] _pathFinish;
[SerializeField] private BlockScript[] _predefinedBlocks;
[SerializeField] private UnityEvent<BlockScript> _onBlockDestroy;
[SerializeField] private UnityEvent _onBuildComplete;
public event UnityAction<BlockScript> OnBlockDestroy
{
add => _onBlockDestroy.AddListener(value);
remove => _onBlockDestroy.RemoveListener(value);
}
public event UnityAction OnBuildComplete
{
add => _onBuildComplete.AddListener(value);
remove => _onBuildComplete.RemoveListener(value);
}
private BlockScript _currentBlock;
private readonly List<BlockScript> _blocksInPath = new();
private void Start() => InitBlocks();
private void InitBlocks()
{
_currentBlock = _pathStart;
_blocksInPath.AddRange(_predefinedBlocks);
}
public void DestroyBlock(BlockScript block)
{
_onBlockDestroy?.Invoke(block);
Destroy(block.gameObject);
}
private void OnEnable()
{
_blockDetector.OnBlockClicked += OnBlockDetected;
}
private void OnDisable()
{
_blockDetector.OnBlockClicked -= OnBlockDetected;
}
public void ResetPath()
{
// TODO: исправить удаление блоков финала пути
for (int i = _predefinedBlocks.Length; i < _blocksInPath.Count; i++)
{
var block = _blocksInPath[i];
Instantiate(_grassBlockPrefab, block.transform.position, block.transform.localRotation, block.transform.parent);
Destroy(block.gameObject);
}
_blocksInPath.Clear();
InitBlocks();
}
private void OnBlockDetected(BlockScript block)
{
if (_gameManager.CurrentState != GameManager.GameState.BuildingPath)
return;
if (!_currentBlock.GetNeighbors().Contains(block) ||
block.GetNeighbors().Count((o) => o.Type == BlockScript.BlockType.Sand) > 1)
return;
var t = block.transform;
_currentBlock = Instantiate(_blockPrefab, t.position, t.localRotation, t.parent);
_blocksInPath.Add(_currentBlock);
if (_pathFinish.Contains(block))
{
_currentBlock = _pathEnd;
_blocksInPath.Add(_currentBlock);
_onBuildComplete?.Invoke();
}
DestroyBlock(block);
}
public IEnumerable<Vector3> GetPath() =>
_blocksInPath.Select(b =>
{
var pos = b.transform.position;
pos.y += 1f;
return pos;
});
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2234a2a63b27a534f9fc6fdcdb15afcb
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 13aa96d6e4bf50589a66618b4eb22f78
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+12
View File
@@ -0,0 +1,12 @@
using UnityEngine;
using System.Collections.Generic;
[CreateAssetMenu(fileName = "Level_No", menuName = "Scriptable Objects/Level")]
public class Level : ScriptableObject
{
[SerializeField] private Enemy[] _enemiesPrefabs;
[SerializeField] private float _levelTimeSec = 10f;
public IReadOnlyCollection<Enemy> EnemiesPrefabs => _enemiesPrefabs;
public float LevelTimeSec => _levelTimeSec;
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b1e1b282bef2878e089a42b9c8507311
+19
View File
@@ -0,0 +1,19 @@
using System;
using UnityEngine;
[RequireComponent(typeof(TowerHealth))]
public class Tower : MonoBehaviour
{
private TowerHealth _towerHealth;
private void Start()
{
_towerHealth = GetComponent<TowerHealth>();
}
private void OnTriggerEnter(Collider other)
{
if (other.TryGetComponent(out Enemy enemy))
_towerHealth.TakeDamage(enemy.Damage);
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 49451834470586d42a0a0039b348f818
+67
View File
@@ -0,0 +1,67 @@
using System;
using UnityEngine;
using UnityEngine.Events;
public class TowerHealth : MonoBehaviour
{
[SerializeField] private float _maxHealth = 100f;
[SerializeField] private float _currentHealth = 100f;
[SerializeField] private UnityEvent<OnHealthChangedEventArgs> _onHealthChanged;
public event UnityAction<OnHealthChangedEventArgs> OnHealthChanged
{
add => _onHealthChanged.AddListener(value);
remove => _onHealthChanged.RemoveListener(value);
}
public float MaxHealth
{
get => _maxHealth;
private set
{
_maxHealth = value;
_onHealthChanged?.Invoke(new(_currentHealth, _maxHealth));
}
}
public float CurrentHealth
{
get => _currentHealth;
private set
{
_currentHealth = value;
_onHealthChanged?.Invoke(new(_currentHealth, _maxHealth));
}
}
private void OnTriggerEnter(Collider other)
{
if (!other.TryGetComponent(out Enemy enemy))
return;
TakeDamage(enemy.Damage);
Destroy(enemy.gameObject);
}
public void TakeDamage(float damage)
{
CurrentHealth -= damage;
// TODO: доделать проигрыш
if (CurrentHealth <= 0)
Debug.Log("Game over");
}
public class OnHealthChangedEventArgs : EventArgs
{
public readonly float CurrentHealth;
public readonly float MaxHealth;
public OnHealthChangedEventArgs(float currentHealth, float maxHealth)
{
CurrentHealth = currentHealth;
MaxHealth = maxHealth;
}
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 73f23bf5d451b9d99a2529ebac821e47
+22
View File
@@ -0,0 +1,22 @@
using System;
using UnityEngine;
public class TowerHealthViewer : MonoBehaviour
{
[SerializeField] private TowerHealth _towerHealth;
private void OnEnable()
{
_towerHealth.OnHealthChanged += OnHealthChanged;
}
private void OnDisable()
{
_towerHealth.OnHealthChanged -= OnHealthChanged;
}
private static void OnHealthChanged(TowerHealth.OnHealthChangedEventArgs e)
{
print("Health changed: " + e.CurrentHealth);
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 623cfd758f42513808424b0fdb743846
+41
View File
@@ -0,0 +1,41 @@
using System;
using UnityEngine;
public class Turret : MonoBehaviour
{
[SerializeField] private TurretBullet _bulletPrefab;
[SerializeField] private float _reloadTime = 1f;
[SerializeField] private float _damage;
[SerializeField] private float _distance;
private float _reloadTimer;
private void Update()
{
if (_reloadTimer >= _reloadTime)
{
SpawnBullet(Vector3.forward);
SpawnBullet(Vector3.back);
SpawnBullet(Vector3.left);
SpawnBullet(Vector3.right);
_reloadTimer = 0f;
}
_reloadTimer += Time.deltaTime;
}
private void SpawnBullet(Vector3 direction)
{
if (!DetectEnemy(direction))
return;
var rot = transform.rotation;
rot.SetLookRotation(direction);
Instantiate(_bulletPrefab, transform.position, rot, transform);
}
private bool DetectEnemy(Vector3 direction) =>
Physics.Raycast(transform.position, direction, out var hit, _bulletPrefab.Distance + _distance) &&
hit.transform.TryGetComponent(out Enemy _);
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 28342e4845776bf5982ef6ad03926c37
+25
View File
@@ -0,0 +1,25 @@
using UnityEngine;
public class TurretBullet : MonoBehaviour
{
[SerializeField] private float _damage = 1f;
[SerializeField] private float _speed = 5f;
[SerializeField] private float _distance = 3f;
private Vector3 _spawnPos;
public float Damage => _damage;
public float Distance => _distance;
private void Start()
{
_spawnPos = transform.position;
}
private void Update()
{
transform.Translate(Vector3.forward * (_speed * Time.deltaTime));
if (Vector3.Distance(transform.position, _spawnPos) > _distance)
Destroy(gameObject);
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 45192ee5599f42de7864fdec0f93ce27
+14
View File
@@ -0,0 +1,14 @@
using System;
using UnityEngine;
[Serializable]
public struct TurretShopItem
{
[SerializeField] private Turret _turretPrefab;
[SerializeField] private Sprite _icon;
[SerializeField] private int _price;
public readonly Turret TurretPrefab => _turretPrefab;
public readonly Sprite Icon => _icon;
public readonly int Price => _price;
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4599f6d87f88c5e4bb120a45c1dc6e59
+85
View File
@@ -0,0 +1,85 @@
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.Events;
using UnityEngine.InputSystem;
public class TurretsShop : MonoBehaviour
{
[SerializeField] private Wallet _wallet;
[SerializeField] private BlockDetector _blockDetector;
[SerializeField] private Transform _turretsHolder;
[SerializeField] private InputAction _deselectAction;
[SerializeField] private TurretShopItem[] _turretShopItems;
[SerializeField] private UnityEvent<TurretShopItem> _onTurretSelected;
[SerializeField] private UnityEvent _onTurretDeselected;
public event UnityAction<TurretShopItem> OnTurretSelected
{
add => _onTurretSelected.AddListener(value);
remove => _onTurretSelected.RemoveListener(value);
}
public event UnityAction OnTurretDeselected
{
add => _onTurretDeselected.AddListener(value);
remove => _onTurretDeselected.RemoveListener(value);
}
public IReadOnlyCollection<TurretShopItem> TurretShopItems => _turretShopItems;
private TurretShopItem _selectedTurret;
private bool _isTurretSelected = false;
public void SelectTurret(TurretShopItem item)
{
_isTurretSelected = _wallet.Money >= item.Price;
if (!_isTurretSelected)
return;
_selectedTurret = item;
_onTurretSelected?.Invoke(item);
}
public void DeselectTurret()
{
_isTurretSelected = false;
_onTurretDeselected?.Invoke();
}
private void OnEnable()
{
_deselectAction.Enable();
_deselectAction.performed += DeselectActionPerformed;
_blockDetector.OnBlockClicked += OnBlockClicked;
}
private void OnDisable()
{
_deselectAction.performed -= DeselectActionPerformed;
_deselectAction.Disable();
_blockDetector.OnBlockClicked -= OnBlockClicked;
}
private void Start()
{
if (_turretsHolder == null)
_turretsHolder = transform;
}
private void DeselectActionPerformed(InputAction.CallbackContext _) => DeselectTurret();
private void OnBlockClicked(BlockScript block)
{
if (!_isTurretSelected || _selectedTurret.Price > _wallet.Money)
return;
var pos = block.transform.position;
pos.y += 1;
Instantiate(_selectedTurret.TurretPrefab, pos, Quaternion.identity, _turretsHolder);
_wallet.TakeMoney(_selectedTurret.Price);
if (_wallet.Money < _selectedTurret.Price)
DeselectTurret();
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5980606f117d314418be8bbb5abf9a95
+70
View File
@@ -0,0 +1,70 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Animator))]
public class TurretsShopViewer : MonoBehaviour
{
[SerializeField] private TurretsShop _shop;
[SerializeField] private Wallet _wallet;
[SerializeField] private GameManager _gameManager;
[SerializeField] private Button _buttonPrefab;
private Animator _animator;
private bool _hidden = true;
private readonly Dictionary<Button, TurretShopItem> _buttons = new();
private static readonly int _hideAnimation = Animator.StringToHash("HideTurretShopPanelAnimation");
private static readonly int _showAnimation = Animator.StringToHash("ShowTurretShopPanelAnimation");
private void Start()
{
foreach (var item in _shop.TurretShopItems)
{
var button = Instantiate(_buttonPrefab, transform);
var icon = button.GetComponentInChildrenWithoutParent<Image>();
if (icon != null && item.Icon != null)
{
icon.gameObject.SetActive(true);
icon.sprite = item.Icon;
}
button.onClick.AddListener(() => _shop.SelectTurret(item));
_buttons.Add(button, item);
}
}
private void Awake()
{
_animator = GetComponent<Animator>();
}
private void OnEnable()
{
_gameManager.OnStateChanged += OnGameStateChanged;
_wallet.OnMoneyChanged += OnMoneyChanged;
}
private void OnDisable()
{
_gameManager.OnStateChanged -= OnGameStateChanged;
_wallet.OnMoneyChanged -= OnMoneyChanged;
}
private void OnGameStateChanged(GameManager.GameState state)
{
if (!_hidden || state != GameManager.GameState.BuildingTurrets)
return;
_animator.Play(_showAnimation);
_hidden = false;
}
private void OnMoneyChanged(int money)
{
foreach (var (button, item) in _buttons)
{
button.interactable = money >= item.Price;
}
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 13f8d814a03532843895b328349ccfd5
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ef3ea4b0304aec24d8f2b6ed14e432d1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+43
View File
@@ -0,0 +1,43 @@
using UnityEngine;
using UnityEngine.UI;
public class GameMenuButtons : MonoBehaviour
{
[SerializeField] private GameManager _gameManager;
[SerializeField] private SandPathBuildService _sandPathBuildService;
[SerializeField] private Button _nextLevelButton;
[SerializeField] private Button _resetPathButton;
private void OnEnable()
{
_gameManager.OnStateChanged += OnStateChanged;
if (_resetPathButton != null)
_resetPathButton.onClick.AddListener(OnResetButtonClick);
}
private void OnDisable()
{
_gameManager.OnStateChanged -= OnStateChanged;
if (_resetPathButton != null)
_resetPathButton.onClick.RemoveListener(OnResetButtonClick);
}
private void OnStateChanged(GameManager.GameState newState)
{
_nextLevelButton.interactable = newState != GameManager.GameState.BuildingPath;
if (!_nextLevelButton.interactable || _resetPathButton == null)
return;
_resetPathButton.onClick.RemoveAllListeners();
Destroy(_resetPathButton.gameObject);
_resetPathButton = null;
}
private void OnResetButtonClick()
{
_sandPathBuildService.ResetPath();
_gameManager.CurrentState = GameManager.GameState.BuildingPath;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b08066ad0060a5d4fb8e8d7d9dadc514
+35
View File
@@ -0,0 +1,35 @@
using UnityEngine;
using UnityEngine.Events;
public class Wallet : MonoBehaviour
{
[SerializeField] private int _money;
[SerializeField] private UnityEvent<int> _onMoneyChanged;
public event UnityAction<int> OnMoneyChanged
{
add => _onMoneyChanged.AddListener(value);
remove => _onMoneyChanged.RemoveListener(value);
}
public int Money
{
get => _money;
private set
{
_money = value;
_onMoneyChanged?.Invoke(value);
}
}
public void AddMoney(int money) => Money += money;
public bool TakeMoney(int money)
{
if (Money < money)
return false;
Money -= money;
return true;
}
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d5c1bdc2782c2a7b2a0a156402dbc325