补充参战防御塔进入战斗逻辑

- 将 Inventory 中参战的防御塔数据传递到 CombatSelectForm 中
- 为防御塔的图标展示添加 TowerRepoItem 与 TowerIconArea 适配防御塔的三层 Image
This commit is contained in:
SepComet 2026-03-05 13:44:49 +08:00
parent 9db9aeabcd
commit 8a478982f8
56 changed files with 2507 additions and 467 deletions

View File

@ -76,7 +76,7 @@ SpriteRenderer:
m_SortingOrder: 2
m_Sprite: {fileID: 7482667652216324306, guid: 5ba74e3a185274149b15c24b321bead2,
type: 3}
m_Color: {r: 1, g: 0.40566027, b: 0.40566027, a: 1}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0
m_FlipY: 0
m_DrawMode: 0
@ -103,6 +103,7 @@ MonoBehaviour:
_bulletTypeId: 501
_muzzlePoint: {fileID: 7637292285124107611}
_bulletSpeed: 12
_renderer: {fileID: 7170949026143225663}
--- !u!1 &1221576993898367501
GameObject:
m_ObjectHideFlags: 0
@ -113,7 +114,6 @@ GameObject:
m_Component:
- component: {fileID: 6791423131335728073}
- component: {fileID: 8183383920109690380}
- component: {fileID: 3255949411223456789}
- component: {fileID: 4014432302095443276}
m_Layer: 0
m_Name: TowerEntity
@ -160,18 +160,6 @@ MonoBehaviour:
_attackRangeLineWidth: 0.08
_attackRangeColor: {r: 0.1, g: 1, b: 0.4, a: 0.8}
_attackRangeZOffset: -0.01
--- !u!114 &3255949411223456789
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1221576993898367501}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d87f56efd9024709a3baf8ef8a6f4fd3, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!120 &4014432302095443276
LineRenderer:
serializedVersion: 2
@ -379,6 +367,7 @@ MonoBehaviour:
_attackRange: 5
_aimToleranceAngle: 2
_rotateRoot: {fileID: 5517541809701307552}
_renderer: {fileID: 7775658596736532582}
--- !u!1 &4867507345079921359
GameObject:
m_ObjectHideFlags: 0
@ -456,7 +445,7 @@ SpriteRenderer:
m_SortingOrder: 0
m_Sprite: {fileID: 7482667652216324306, guid: 80a3790c48fc91d4ebcb4d7e2efbb8c8,
type: 3}
m_Color: {r: 0.3584906, g: 0.3584906, b: 0.3584906, a: 1}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0
m_FlipY: 0
m_DrawMode: 0
@ -480,3 +469,4 @@ MonoBehaviour:
m_EditorClassIdentifier:
_attackSpeed: 1
_attackPropertyType: 1
_renderer: {fileID: 6516390239457838709}

View File

@ -7,8 +7,11 @@ namespace Components
public class BasicBaseComp : MonoBehaviour
{
[SerializeField] [Min(0.01f)] private float _attackSpeed = 1f;
[SerializeField] private AttackPropertyType _attackPropertyType = AttackPropertyType.Physics;
[SerializeField] private SpriteRenderer _renderer;
private float _cooldownRemaining;
public float AttackSpeed => _attackSpeed;
@ -29,6 +32,14 @@ namespace Components
_cooldownRemaining = 0f;
}
public void SetColor(Color color)
{
if (_renderer != null)
{
_renderer.color = color;
}
}
public void Tick(float deltaTime)
{
if (_cooldownRemaining <= 0f)

View File

@ -6,10 +6,15 @@ namespace Components
public class BasicBearingComp : MonoBehaviour
{
[SerializeField] [Min(1f)] private float _rotateSpeed = 180f;
[SerializeField] [Min(0.1f)] private float _attackRange = 5f;
[SerializeField] [Min(0.1f)] private float _aimToleranceAngle = 2f;
[SerializeField] private Transform _rotateRoot;
[SerializeField] private SpriteRenderer _renderer;
public float RotateSpeed => _rotateSpeed;
public float AttackRange => _attackRange;
public float AimToleranceAngle => _aimToleranceAngle;
@ -26,6 +31,14 @@ namespace Components
_attackRange = 5f;
}
public void SetColor(Color color)
{
if (_renderer != null)
{
_renderer.color = color;
}
}
public bool IsTargetInRange(Transform target, Transform origin = null)
{
if (target == null)

View File

@ -9,11 +9,17 @@ namespace Components
public class ShooterMuzzleComp : MonoBehaviour
{
[SerializeField] [Min(1f)] private int _attackDamage = 100;
[SerializeField] private AttackMethodType _attackMethodType = AttackMethodType.NormalBullet;
[SerializeField] [Min(1)] private int _bulletTypeId = 501;
[SerializeField] private Transform _muzzlePoint;
[SerializeField] [Min(0.1f)] private float _bulletSpeed = 12f;
[SerializeField] private SpriteRenderer _renderer;
public int AttackDamage => _attackDamage;
public AttackMethodType AttackMethodType => _attackMethodType;
@ -31,6 +37,14 @@ namespace Components
_bulletTypeId = 501;
}
public void SetColor(Color color)
{
if (_renderer != null)
{
_renderer.color = color;
}
}
public bool Attack(Transform target)
{
return Attack(target, AttackPropertyType.None);

View File

@ -10,7 +10,8 @@ namespace Components
private const string AttackRangeIndicatorObjectName = "AttackRangeIndicator";
private const int MinTowerLevel = 0;
private const int MaxTowerLevel = 4;
private static Material s_AttackRangeSharedMaterial;
private static Material _attackRangeSharedMaterial;
[SerializeField] private ShooterMuzzleComp _muzzleComp;
[SerializeField] private BasicBearingComp _bearingComp;
@ -27,6 +28,9 @@ namespace Components
private float _retargetTimer;
private float _attackRange;
private int _towerLevel;
private Color _muzzleColor = Color.white;
private Color _bearingColor = Color.white;
private Color _baseColor = Color.white;
public Transform CurrentTarget => _currentTarget;
@ -40,6 +44,12 @@ namespace Components
OnInit(stats, MinTowerLevel);
}
public void OnInit(TowerStatsData stats, int towerLevel, Color muzzleColor, Color bearingColor, Color baseColor)
{
SetComponentColors(muzzleColor, bearingColor, baseColor);
OnInit(stats, towerLevel);
}
public void OnInit(TowerStatsData stats, int towerLevel)
{
ResolveComponents();
@ -57,6 +67,7 @@ namespace Components
_muzzleComp?.OnInit(attackDamage, stats.AttackMethodType);
_bearingComp?.OnInit(rotateSpeed, attackRange);
_baseComp?.OnInit(attackSpeed, stats.AttackPropertyType);
ApplyComponentColors();
SetAttackRange(attackRange);
SetAttackRangeVisible(false);
_currentTarget = null;
@ -90,6 +101,14 @@ namespace Components
RebuildAttackRangeGeometry();
}
public void SetComponentColors(Color muzzleColor, Color bearingColor, Color baseColor)
{
_muzzleColor = muzzleColor;
_bearingColor = bearingColor;
_baseColor = baseColor;
ApplyComponentColors();
}
public void SetTarget(Transform target)
{
_currentTarget = target;
@ -141,9 +160,9 @@ namespace Components
EnemyEntity bestEnemy = null;
float bestDistanceSquared = float.MaxValue;
for (int i = 0; i < EnemyEntity.ActiveEnemies.Count; i++)
foreach (var enemy in EnemyEntity.ActiveEnemies)
{
EnemyEntity enemy = EnemyEntity.ActiveEnemies[i];
if (enemy == null || !enemy.isActiveAndEnabled)
{
continue;
@ -164,6 +183,13 @@ namespace Components
return bestEnemy != null ? bestEnemy.transform : null;
}
private void ApplyComponentColors()
{
_muzzleComp?.SetColor(_muzzleColor);
_bearingComp?.SetColor(_bearingColor);
_baseComp?.SetColor(_baseColor);
}
private void ResolveComponents()
{
if (_muzzleComp == null)
@ -181,6 +207,7 @@ namespace Components
_baseComp = GetComponent<BasicBaseComp>();
}
ApplyComponentColors();
EnsureAttackRangeRenderer();
}
@ -250,18 +277,18 @@ namespace Components
_attackRangeRenderer.allowOcclusionWhenDynamic = false;
_attackRangeRenderer.enabled = false;
if (s_AttackRangeSharedMaterial == null)
if (_attackRangeSharedMaterial == null)
{
Shader lineShader = Shader.Find("Sprites/Default");
if (lineShader != null)
{
s_AttackRangeSharedMaterial = new Material(lineShader);
_attackRangeSharedMaterial = new Material(lineShader);
}
}
if (s_AttackRangeSharedMaterial != null)
if (_attackRangeSharedMaterial != null)
{
_attackRangeRenderer.sharedMaterial = s_AttackRangeSharedMaterial;
_attackRangeRenderer.sharedMaterial = _attackRangeSharedMaterial;
}
}

View File

@ -23,6 +23,7 @@ namespace GeometryTD.CustomComponent
private readonly Dictionary<int, List<DRLevelSpawnEntry>> _spawnEntriesByPhaseId = new();
private readonly Dictionary<int, IReadOnlyList<DRLevelSpawnEntry>> _selectedSpawnEntriesByPhaseId = new();
private readonly List<int> _levelIdBuffer = new();
private readonly List<TowerStatsData> _currentBuildTowerStats = new();
private readonly CombatScheduler _combatScheduler = new CombatScheduler();
private bool _runtimeInitialized;
@ -39,6 +40,7 @@ namespace GeometryTD.CustomComponent
public int CurrentBaseHp => _currentBaseHp;
public bool LastCombatSucceeded => _lastCombatSucceeded;
public bool CanEndCombat => _combatScheduler.CanEndCombat;
public int CurrentBuildTowerCount => _currentBuildTowerStats.Count;
public int LastDefeatedEnemyCount { get; private set; }
public int LastGainedCoin { get; private set; }
public int LastGainedGold { get; private set; }
@ -88,6 +90,7 @@ namespace GeometryTD.CustomComponent
_spawnEntriesByPhaseId.Clear();
_selectedSpawnEntriesByPhaseId.Clear();
_levelIdBuffer.Clear();
_currentBuildTowerStats.Clear();
IDataTable<DRLevel> dtLevel = GameEntry.DataTable.GetDataTable<DRLevel>();
IDataTable<DRLevelPhase> dtLevelPhase = GameEntry.DataTable.GetDataTable<DRLevelPhase>();
@ -181,6 +184,7 @@ namespace GeometryTD.CustomComponent
public void StartCombat()
{
_currentBuildTowerStats.Clear();
if (!EnsureCombatRuntimeInitialized())
{
Log.Warning("CombatNodeComponent start failed. Missing scheduler runtime.");
@ -216,6 +220,7 @@ namespace GeometryTD.CustomComponent
}
CurrentLevel = selectedLevel;
CacheBuildTowerStatsSnapshot();
_isCombatActive = false;
_currentCoin = Mathf.Max(0, selectedLevel.StartCoin);
_currentGold = 0;
@ -230,6 +235,7 @@ namespace GeometryTD.CustomComponent
_currentCoin = 0;
_currentGold = 0;
_currentBaseHp = 0;
_currentBuildTowerStats.Clear();
return;
}
@ -252,6 +258,7 @@ namespace GeometryTD.CustomComponent
_currentGold = 0;
_currentBaseHp = 0;
CurrentLevel = null;
_currentBuildTowerStats.Clear();
GameEntry.Event.Fire(this, NodeCompleteEventArgs.Create());
}
@ -281,6 +288,7 @@ namespace GeometryTD.CustomComponent
LastDefeatedEnemyCount = 0;
LastGainedCoin = 0;
LastGainedGold = 0;
_currentBuildTowerStats.Clear();
ShutdownCombatRuntime();
}
@ -341,6 +349,18 @@ namespace GeometryTD.CustomComponent
return true;
}
public bool TryGetBuildTowerStats(int buildIndex, out TowerStatsData stats)
{
stats = null;
if (buildIndex < 0 || buildIndex >= _currentBuildTowerStats.Count)
{
return false;
}
stats = CloneTowerStats(_currentBuildTowerStats[buildIndex]);
return stats != null;
}
public void AddCoin(int coin)
{
int gainCoin = Mathf.Max(0, coin);
@ -353,6 +373,54 @@ namespace GeometryTD.CustomComponent
FireCoinChangedEventIfNeeded();
}
private void CacheBuildTowerStatsSnapshot()
{
_currentBuildTowerStats.Clear();
if (GameEntry.PlayerInventory == null)
{
return;
}
IReadOnlyList<TowerItemData> towers = GameEntry.PlayerInventory.GetParticipantTowerSnapshot();
if (towers == null || towers.Count <= 0)
{
return;
}
for (int i = 0; i < towers.Count; i++)
{
TowerItemData tower = towers[i];
TowerStatsData clonedStats = CloneTowerStats(tower?.Stats);
if (clonedStats == null)
{
continue;
}
_currentBuildTowerStats.Add(clonedStats);
}
}
private static TowerStatsData CloneTowerStats(TowerStatsData source)
{
if (source == null)
{
return null;
}
return new TowerStatsData
{
AttackDamage = source.AttackDamage != null ? (int[])source.AttackDamage.Clone() : null,
DamageRandomRate = source.DamageRandomRate,
RotateSpeed = source.RotateSpeed != null ? (float[])source.RotateSpeed.Clone() : null,
AttackRange = source.AttackRange != null ? (float[])source.AttackRange.Clone() : null,
AttackSpeed = source.AttackSpeed != null ? (float[])source.AttackSpeed.Clone() : null,
AttackMethodType = source.AttackMethodType,
AttackPropertyType = source.AttackPropertyType,
Tags = source.Tags != null ? (TagType[])source.Tags.Clone() : null
};
}
private void OnDestroy()
{
OnShutdown();
@ -437,3 +505,5 @@ namespace GeometryTD.CustomComponent
}
}
}

View File

@ -1,4 +1,5 @@
using GeometryTD.CustomUtility;
using System.Collections.Generic;
using GeometryTD.CustomUtility;
using GeometryTD.Definition;
using UnityGameFramework.Runtime;
@ -44,6 +45,31 @@ namespace GeometryTD.CustomComponent
return _queryModel.GetSnapshot();
}
public IReadOnlyList<TowerItemData> GetParticipantTowerSnapshot()
{
EnsureInitialized();
BackpackInventoryData inventory = _queryModel.Inventory;
if (inventory?.ParticipantTowerInstanceIds == null || inventory.ParticipantTowerInstanceIds.Count <= 0)
{
return new List<TowerItemData>();
}
List<TowerItemData> result = new List<TowerItemData>(inventory.ParticipantTowerInstanceIds.Count);
for (int i = 0; i < inventory.ParticipantTowerInstanceIds.Count && result.Count < MaxParticipantTowerCount; i++)
{
long towerId = inventory.ParticipantTowerInstanceIds[i];
if (!_queryModel.TryGetTowerById(towerId, out TowerItemData tower) || tower == null)
{
continue;
}
result.Add(InventoryCloneUtility.CloneTower(tower));
}
return result;
}
public void MergeInventory(BackpackInventoryData gainedInventory)
{
EnsureInitialized();
@ -126,3 +152,4 @@ namespace GeometryTD.CustomComponent
}
}
}

View File

@ -34,6 +34,9 @@ namespace GeometryTD.Definition
/// </summary>
public List<TowerItemData> Towers { get; set; } = new List<TowerItemData>();
/// <summary>
/// 参与战斗的防御塔 Id。
/// </summary>
public List<long> ParticipantTowerInstanceIds { get; set; } = new List<long>();
}
}

View File

@ -1,4 +1,6 @@
using System;
using Newtonsoft.Json;
using UnityEngine;
namespace GeometryTD.Definition
{
@ -41,7 +43,7 @@ namespace GeometryTD.Definition
public RarityType Rarity { get; set; }
public bool IsParticipatingInCombat { get; set; }
/// <summary>
/// 构成该防御塔的枪口组件实例 Id。
/// </summary>
@ -61,5 +63,9 @@ namespace GeometryTD.Definition
/// 防御塔独立属性,不依赖组件对象引用。
/// </summary>
public TowerStatsData Stats { get; set; } = new TowerStatsData();
[JsonIgnore] public Sprite ComposedIconSprite { get; set; }
[JsonIgnore] public string ComposedIconKey { get; set; }
}
}
}

View File

@ -9,15 +9,22 @@ namespace GeometryTD.Entity.EntityData
{
[SerializeField] private TowerStatsData _stats = new TowerStatsData();
[SerializeField] private int _towerLevel = 0;
[SerializeField] private Color _muzzleColor = Color.white;
[SerializeField] private Color _bearingColor = Color.white;
[SerializeField] private Color _baseColor = Color.white;
public TowerData(int entityId, int typeId, Vector3 position, Quaternion rotation,
TowerStatsData stats, int towerLevel = 0)
TowerStatsData stats, int towerLevel = 0, Color? muzzleColor = null, Color? bearingColor = null,
Color? baseColor = null)
: base(entityId, typeId)
{
Position = position;
Rotation = rotation;
_stats = stats ?? new TowerStatsData();
_towerLevel = Mathf.Max(0, towerLevel);
_muzzleColor = muzzleColor ?? Color.white;
_bearingColor = bearingColor ?? Color.white;
_baseColor = baseColor ?? Color.white;
}
public TowerStatsData Stats
@ -31,5 +38,23 @@ namespace GeometryTD.Entity.EntityData
get => _towerLevel;
set => _towerLevel = Mathf.Max(0, value);
}
public Color MuzzleColor
{
get => _muzzleColor;
set => _muzzleColor = value;
}
public Color BearingColor
{
get => _bearingColor;
set => _bearingColor = value;
}
public Color BaseColor
{
get => _baseColor;
set => _baseColor = value;
}
}
}

View File

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using GeometryTD.CustomComponent;
using GeometryTD.CustomUtility;
using GeometryTD.Map;
using GeometryTD.Definition;
using GeometryTD.Entity.EntityData;
@ -14,12 +16,17 @@ namespace GeometryTD.Entity
public class MapEntity : EntityBase
{
private const int DefaultTowerTypeId = 401;
private static readonly Spawner[] EmptySpawners = Array.Empty<Spawner>();
[SerializeField] private bool _enableCombatSelectInput = true;
[SerializeField] private int _towerTypeId = DefaultTowerTypeId;
[SerializeField] private int[] _buildTowerCosts = { 40, 60, 60, 80 };
[SerializeField] private int _upgradeCost = 50;
[SerializeField] private int _destroyGain = 40;
private MapDataRefs _mapDataRefs;
@ -29,6 +36,8 @@ namespace GeometryTD.Entity
private CombatSelectInputService _combatSelectInputService;
private TowerPlacementService _towerPlacementService;
private TowerSelectionPresenter _towerSelectionPresenter;
private readonly BuildTowerVisualInfo[] _buildTowerVisualInfos = new BuildTowerVisualInfo[4];
public IReadOnlyList<Vector3Int> PathCells => _mapTopologyService != null
? _mapTopologyService.PathCells
@ -209,22 +218,38 @@ namespace GeometryTD.Entity
}
_combatSelectFormUseCase.SetCoinProvider(GetCurrentCoin);
BackpackInventoryData inventorySnapshot = GameEntry.PlayerInventory != null
? GameEntry.PlayerInventory.GetInventorySnapshot()
: null;
IReadOnlyList<TowerItemData> participantTowers = GameEntry.PlayerInventory != null
? GameEntry.PlayerInventory.GetParticipantTowerSnapshot()
: null;
Dictionary<long, MuzzleCompItemData> muzzleMap = BuildComponentMap(inventorySnapshot?.MuzzleComponents);
Dictionary<long, BearingCompItemData> bearingMap = BuildComponentMap(inventorySnapshot?.BearingComponents);
Dictionary<long, BaseCompItemData> baseMap = BuildComponentMap(inventorySnapshot?.BaseComponents);
int currentBuildTowerCount = GetCurrentBuildTowerCount();
for (int i = 0; i < 4; i++)
{
int buildIndex = i;
int buildCost = GetBuildTowerCost(buildIndex);
bool isBuildAvailable = buildIndex < currentBuildTowerCount;
BuildTowerVisualInfo buildVisual = ResolveBuildTowerVisual(participantTowers, buildIndex, muzzleMap, bearingMap, baseMap);
_buildTowerVisualInfos[buildIndex] = buildVisual;
_combatSelectFormUseCase.SetBuildAction(
buildIndex,
() => TryBuildTower(buildIndex),
GetBuildTowerCost(buildIndex));
isBuildAvailable ? () => TryBuildTower(buildIndex) : (Func<bool>)null,
buildCost,
null,
isBuildAvailable,
buildVisual.BaseColor,
buildVisual.BearingColor,
buildVisual.MuzzleColor);
_combatSelectFormUseCase.SetBuildVisible(buildIndex, isBuildAvailable);
}
_combatSelectFormUseCase.SetUpgradeAction(
TryUpgradeTower,
Mathf.Max(0, _upgradeCost));
_combatSelectFormUseCase.SetDestroyAction(
TryDestroyTower,
Mathf.Max(0, _destroyGain));
_combatSelectFormUseCase.SetUpgradeAction(TryUpgradeTower, Mathf.Max(0, _upgradeCost));
_combatSelectFormUseCase.SetDestroyAction(TryDestroyTower, Mathf.Max(0, _destroyGain));
}
private void HandleCombatSelectInput()
@ -275,8 +300,18 @@ namespace GeometryTD.Entity
return false;
}
CombatNodeComponent combatNode = GameEntry.CombatNode;
if (combatNode == null || !combatNode.TryGetBuildTowerStats(buildIndex, out TowerStatsData buildTowerStats))
{
return false;
}
BuildTowerVisualInfo buildVisual = buildIndex >= 0 && buildIndex < _buildTowerVisualInfos.Length
? _buildTowerVisualInfos[buildIndex]
: BuildTowerVisualInfo.Default;
if (!_towerPlacementService.TryBuildTower(selectedFoundationCell, IsFoundationCell, buildIndex, _buildTowerCosts,
_towerTypeId, Tilemap, TryConsumeCoin, AddCoin, out int towerEntityId))
buildTowerStats, buildVisual.MuzzleColor, buildVisual.BearingColor, buildVisual.BaseColor, _towerTypeId, Tilemap, TryConsumeCoin, AddCoin, out int towerEntityId))
{
return false;
}
@ -350,6 +385,77 @@ namespace GeometryTD.Entity
return Mathf.Max(0, _buildTowerCosts[buildIndex]);
}
private static int GetCurrentBuildTowerCount()
{
if (GameEntry.CombatNode == null)
{
return 0;
}
return Mathf.Clamp(GameEntry.CombatNode.CurrentBuildTowerCount, 0, 4);
}
private static BuildTowerVisualInfo ResolveBuildTowerVisual(
IReadOnlyList<TowerItemData> participantTowers,
int buildIndex,
IReadOnlyDictionary<long, MuzzleCompItemData> muzzleMap,
IReadOnlyDictionary<long, BearingCompItemData> bearingMap,
IReadOnlyDictionary<long, BaseCompItemData> baseMap)
{
if (participantTowers == null || buildIndex < 0 || buildIndex >= participantTowers.Count)
{
return BuildTowerVisualInfo.Default;
}
TowerItemData tower = participantTowers[buildIndex];
if (tower == null)
{
return BuildTowerVisualInfo.Default;
}
Color muzzleColor = ResolveComponentColor(muzzleMap, tower.MuzzleComponentInstanceId);
Color bearingColor = ResolveComponentColor(bearingMap, tower.BearingComponentInstanceId);
Color baseColor = ResolveComponentColor(baseMap, tower.BaseComponentInstanceId);
return new BuildTowerVisualInfo(muzzleColor, bearingColor, baseColor);
}
private static Color ResolveComponentColor<TComp>(IReadOnlyDictionary<long, TComp> componentMap, long componentId)
where TComp : TowerCompItemData
{
if (componentMap == null || componentId <= 0)
{
return Color.white;
}
return componentMap.TryGetValue(componentId, out TComp component) && component != null
? IconColorGenerator.GenerateForComponent(component)
: Color.white;
}
private static Dictionary<long, TComp> BuildComponentMap<TComp>(IReadOnlyList<TComp> items)
where TComp : TowerCompItemData
{
Dictionary<long, TComp> map = new Dictionary<long, TComp>();
if (items == null)
{
return map;
}
for (int i = 0; i < items.Count; i++)
{
TComp item = items[i];
if (item == null || item.InstanceId <= 0)
{
continue;
}
map[item.InstanceId] = item;
}
return map;
}
private static bool TryConsumeCoin(int cost)
{
int requiredCoin = Mathf.Max(0, cost);
@ -371,6 +477,22 @@ namespace GeometryTD.Entity
return GameEntry.CombatNode != null ? Mathf.Max(0, GameEntry.CombatNode.CurrentCoin) : 0;
}
private readonly struct BuildTowerVisualInfo
{
public static BuildTowerVisualInfo Default => new BuildTowerVisualInfo(Color.white, Color.white, Color.white);
public BuildTowerVisualInfo(Color muzzleColor, Color bearingColor, Color baseColor)
{
MuzzleColor = muzzleColor;
BearingColor = bearingColor;
BaseColor = baseColor;
}
public Color MuzzleColor { get; }
public Color BearingColor { get; }
public Color BaseColor { get; }
}
private static void AddCoin(int coin)
{
int amount = Mathf.Max(0, coin);
@ -382,3 +504,4 @@ namespace GeometryTD.Entity
}
}
}

View File

@ -53,7 +53,12 @@ namespace GeometryTD.Entity
return;
}
_towerController.OnInit(towerData.Stats, towerData.TowerLevel);
_towerController.OnInit(
towerData.Stats,
towerData.TowerLevel,
towerData.MuzzleColor,
towerData.BearingColor,
towerData.BaseColor);
}
protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)

View File

@ -0,0 +1,28 @@
using GameFramework;
using GameFramework.ObjectPool;
using GeometryTD.UI;
using UnityEngine;
namespace GeometryTD.PoolObjectBase
{
public class TowerRepoItemObject : ObjectBase
{
public static TowerRepoItemObject Create(object target)
{
TowerRepoItemObject itemObject = ReferencePool.Acquire<TowerRepoItemObject>();
itemObject.Initialize(target);
return itemObject;
}
protected override void Release(bool isShutdown)
{
TowerRepoItem item = (TowerRepoItem)Target;
if (item == null)
{
return;
}
Object.Destroy(item.gameObject);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6f6f2603e451c5f4f9b0d0cb8ee247d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -40,7 +40,7 @@ namespace GeometryTD.Map
}
public bool TryBuildTower(Vector3Int foundationCell, Func<Vector3Int, bool> isFoundationCell, int buildIndex,
int[] buildTowerCosts, int towerTypeId, Tilemap tilemap, Func<int, bool> tryConsumeCoin,
int[] buildTowerCosts, TowerStatsData buildTowerStats, Color muzzleColor, Color bearingColor, Color baseColor, int towerTypeId, Tilemap tilemap, Func<int, bool> tryConsumeCoin,
Action<int> addCoin,
out int towerEntityId)
{
@ -55,14 +55,19 @@ namespace GeometryTD.Map
return false;
}
TowerStatsData towerStats = CloneTowerStats(buildTowerStats);
if (towerStats == null)
{
return false;
}
int buildCost = GetBuildTowerCost(buildTowerCosts, buildIndex);
if (tryConsumeCoin != null && !tryConsumeCoin(buildCost))
{
return false;
}
TowerStatsData towerStats = BuildTowerStats(buildIndex);
if (!TryShowTowerEntity(foundationCell, towerStats, towerTypeId, tilemap, out int newTowerEntityId))
if (!TryShowTowerEntity(foundationCell, towerStats, muzzleColor, bearingColor, baseColor, towerTypeId, tilemap, out int newTowerEntityId))
{
addCoin?.Invoke(buildCost);
return false;
@ -177,7 +182,7 @@ namespace GeometryTD.Map
return Mathf.Max(0, buildTowerCosts[buildIndex]);
}
private static bool TryShowTowerEntity(Vector3Int foundationCell, TowerStatsData towerStats,
private static bool TryShowTowerEntity(Vector3Int foundationCell, TowerStatsData towerStats, Color muzzleColor, Color bearingColor, Color baseColor,
int towerTypeId,
Tilemap tilemap, out int towerEntityId)
{
@ -192,7 +197,7 @@ namespace GeometryTD.Map
Vector3 towerPosition = tilemap != null ? tilemap.GetCellCenterWorld(foundationCell) : foundationCell;
towerPosition.z = 0f;
var towerData = new TowerData(entityId, typeId, towerPosition, Quaternion.identity, towerStats,
MinTowerLevel);
MinTowerLevel, muzzleColor, bearingColor, baseColor);
GameEntry.Entity.ShowDefenseTower(towerData);
towerEntityId = entityId;
@ -346,4 +351,4 @@ namespace GeometryTD.Map
return values != null ? values.Length : 0;
}
}
}
}

View File

@ -10,5 +10,6 @@ namespace GeometryTD.UI
public bool IsInteractable;
public CombatSelectActionType ActionType;
public int ActionIndex;
public TowerIconAreaContext TowerIconAreaContext;
}
}

View File

@ -116,9 +116,8 @@ namespace GeometryTD.UI
if (inventory.Towers != null)
{
for (int i = 0; i < inventory.Towers.Count; i++)
foreach (TowerItemData tower in inventory.Towers)
{
var tower = inventory.Towers[i];
if (tower == null)
{
continue;
@ -131,7 +130,7 @@ namespace GeometryTD.UI
EnduranceRate01 = ItemDescUtility.ResolveTowerEnduranceRate(tower, muzzleMap, bearingMap, baseMap),
ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.None,
IconAreaContext = BuildIconAreaContext(tower)
IconAreaContext = BuildTowerIconContext(tower, muzzleMap, bearingMap, baseMap)
});
AddItemDescSeed(
@ -145,9 +144,8 @@ namespace GeometryTD.UI
if (inventory.MuzzleComponents != null)
{
for (int i = 0; i < inventory.MuzzleComponents.Count; i++)
foreach (MuzzleCompItemData item in inventory.MuzzleComponents)
{
var item = inventory.MuzzleComponents[i];
if (item == null)
{
continue;
@ -174,7 +172,7 @@ namespace GeometryTD.UI
if (inventory.BearingComponents != null)
{
foreach (var item in inventory.BearingComponents)
foreach (BearingCompItemData item in inventory.BearingComponents)
{
if (item == null)
{
@ -202,9 +200,8 @@ namespace GeometryTD.UI
if (inventory.BaseComponents != null)
{
for (int i = 0; i < inventory.BaseComponents.Count; i++)
foreach (BaseCompItemData item in inventory.BaseComponents)
{
var item = inventory.BaseComponents[i];
if (item == null)
{
continue;
@ -232,6 +229,38 @@ namespace GeometryTD.UI
return itemContexts.ToArray();
}
private static TowerIconAreaContext BuildTowerIconContext(
TowerItemData tower,
IReadOnlyDictionary<long, MuzzleCompItemData> muzzleMap,
IReadOnlyDictionary<long, BearingCompItemData> bearingMap,
IReadOnlyDictionary<long, BaseCompItemData> baseMap)
{
if (tower == null)
{
return null;
}
return new TowerIconAreaContext
{
Rarity = tower.Rarity,
MuzzleColor = ResolveComponentColor(tower.MuzzleComponentInstanceId, muzzleMap),
BearingColor = ResolveComponentColor(tower.BearingComponentInstanceId, bearingMap),
BaseColor = ResolveComponentColor(tower.BaseComponentInstanceId, baseMap)
};
}
private static Color ResolveComponentColor<TComp>(long instanceId, IReadOnlyDictionary<long, TComp> componentMap)
where TComp : TowerCompItemData
{
if (instanceId > 0 && componentMap != null && componentMap.TryGetValue(instanceId, out TComp comp) &&
comp != null)
{
return IconColorGenerator.GenerateForComponent(comp);
}
return Color.white;
}
private void AddItemDescSeed(long itemId, string title, string typeText, string description, TagType[] tags)
{
if (itemId <= 0)
@ -274,9 +303,8 @@ namespace GeometryTD.UI
return map;
}
for (int i = 0; i < items.Count; i++)
foreach (TComp item in items)
{
TComp item = items[i];
if (item == null || item.InstanceId <= 0)
{
continue;
@ -288,35 +316,13 @@ namespace GeometryTD.UI
return map;
}
private static IconAreaContext BuildIconAreaContext(TowerItemData tower)
{
if (tower == null)
{
return new IconAreaContext
{
ComponentSlotType = TowerCompSlotType.None,
Rarity = RarityType.None,
Color = Color.white,
Icon = null
};
}
return new IconAreaContext
{
ComponentSlotType = TowerCompSlotType.None,
Rarity = tower.Rarity,
Color = IconColorGenerator.GenerateForTower(tower),
Icon = null
};
}
private static IconAreaContext BuildIconAreaContext(TowerCompItemData item)
{
if (item == null)
{
return new IconAreaContext
{
ComponentSlotType = TowerCompSlotType.None,
ComponentSlotType = TowerCompSlotType.None,
Rarity = RarityType.None,
Color = Color.white,
Icon = null
@ -332,6 +338,8 @@ namespace GeometryTD.UI
};
}
#region Event Handlers
private void OnCombatFinishReturnButtonClicked(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender) || !(e is CombatFinishReturnEventArgs))
@ -370,6 +378,8 @@ namespace GeometryTD.UI
});
}
#endregion
private bool IsEventFromCurrentForm(object sender)
{
if (Form == null)
@ -392,3 +402,7 @@ namespace GeometryTD.UI
}
}
}

View File

@ -229,7 +229,13 @@ namespace GeometryTD.UI
IsVisible = rawData.IsVisible,
IsInteractable = rawData.IsInteractable,
ActionType = rawData.ActionType,
ActionIndex = rawData.ActionIndex
ActionIndex = rawData.ActionIndex,
TowerIconAreaContext = new TowerIconAreaContext()
{
BaseColor = rawData.BaseColor,
BearingColor = rawData.BearingColor,
MuzzleColor = rawData.MuzzleColor
}
};
}
@ -284,4 +290,4 @@ namespace GeometryTD.UI
RefreshFromUseCase();
}
}
}
}

View File

@ -11,5 +11,9 @@ namespace GeometryTD.UI
public bool IsInteractable;
public CombatSelectActionType ActionType;
public int ActionIndex;
public bool UseTowerLayers;
public Color BaseColor = Color.white;
public Color BearingColor = Color.white;
public Color MuzzleColor = Color.white;
}
}

View File

@ -42,6 +42,19 @@ namespace GeometryTD.UI
}
public void SetBuildAction(int buildIndex, Func<bool> buildAction, int cost, Sprite icon = null)
{
SetBuildAction(buildIndex, buildAction, cost, icon, false, Color.white, Color.white, Color.white);
}
public void SetBuildAction(
int buildIndex,
Func<bool> buildAction,
int cost,
Sprite icon,
bool useTowerLayers,
Color baseColor,
Color bearingColor,
Color muzzleColor)
{
if (buildIndex < 0 || buildIndex >= _buildOptions.Length)
{
@ -54,6 +67,10 @@ namespace GeometryTD.UI
option.Icon = icon;
option.IsGain = false;
option.IsVisible = true;
option.UseTowerLayers = useTowerLayers;
option.BaseColor = baseColor;
option.BearingColor = bearingColor;
option.MuzzleColor = muzzleColor;
}
public void SetBuildAction(int buildIndex, Action buildAction, int cost, Sprite icon = null)
@ -75,6 +92,16 @@ namespace GeometryTD.UI
icon);
}
public void SetBuildVisible(int buildIndex, bool visible)
{
if (buildIndex < 0 || buildIndex >= _buildOptions.Length)
{
return;
}
_buildOptions[buildIndex].IsVisible = visible;
}
public void SetUpgradeAction(Func<bool> upgradeAction, int cost, Sprite icon = null)
{
_upgradeOption.Action = upgradeAction;
@ -82,6 +109,7 @@ namespace GeometryTD.UI
_upgradeOption.Icon = icon;
_upgradeOption.IsGain = false;
_upgradeOption.IsVisible = true;
_upgradeOption.UseTowerLayers = false;
}
public void SetUpgradeAction(Action upgradeAction, int cost, Sprite icon = null)
@ -109,6 +137,7 @@ namespace GeometryTD.UI
_destroyOption.Icon = icon;
_destroyOption.IsGain = true;
_destroyOption.IsVisible = true;
_destroyOption.UseTowerLayers = false;
}
public void SetDestroyAction(Action destroyAction, int gain, Sprite icon = null)
@ -278,7 +307,11 @@ namespace GeometryTD.UI
IsVisible = option.IsVisible,
IsInteractable = option.Action != null && CanExecute(option, currentCoin),
ActionType = option.ActionType,
ActionIndex = option.ActionIndex
ActionIndex = option.ActionIndex,
UseTowerLayers = option.UseTowerLayers,
BaseColor = option.BaseColor,
BearingColor = option.BearingColor,
MuzzleColor = option.MuzzleColor
};
}
@ -293,6 +326,10 @@ namespace GeometryTD.UI
public bool IsVisible = true;
public Sprite Icon;
public Func<bool> Action;
public bool UseTowerLayers;
public Color BaseColor = Color.white;
public Color BearingColor = Color.white;
public Color MuzzleColor = Color.white;
public Option(CombatSelectActionType actionType, int actionIndex, bool requiresAffordable)
{

View File

@ -2,20 +2,23 @@ using TMPro;
using UnityEngine;
using UnityEngine.UI;
using GeometryTD.CustomEvent;
using UnityGameFramework.Runtime;
namespace GeometryTD.UI
{
public class TowerSelectItem : MonoBehaviour
{
[SerializeField] private Image _icon;
[SerializeField] private TMP_Text _price;
[SerializeField] private CommonButton _button;
[SerializeField] private TowerIconArea _towerIconArea;
private TowerSelectItemContext _context;
private Sprite _defaultIcon;
private bool _hasCachedDefaultIcon;
public void OnInit(TowerSelectItemContext context)
@ -23,28 +26,45 @@ namespace GeometryTD.UI
CacheDefaultIcon();
_context = context;
if (_icon != null)
if (context.ActionType == CombatSelectActionType.BuildTower)
{
if (context != null && context.Icon != null)
_icon?.gameObject.SetActive(false);
_towerIconArea?.OnInit(_context.TowerIconAreaContext);
if (_price != null)
{
_icon.sprite = context.Icon;
}
else if (_defaultIcon != null)
{
_icon.sprite = _defaultIcon;
_price.text = context.PriceText ?? string.Empty;
}
_icon.enabled = _icon.sprite != null;
if (_button != null)
{
_button.Interactive = context.IsInteractable;
}
}
if (_price != null)
else if (context.ActionType is CombatSelectActionType.UpgradeTower or CombatSelectActionType.DestroyTower)
{
_price.text = context?.PriceText ?? string.Empty;
if (_icon != null)
{
_icon.sprite = _context.Icon ?? _defaultIcon;
_icon.gameObject.SetActive(true);
}
_towerIconArea?.OnReset();
if (_price != null)
{
_price.text = context.PriceText ?? string.Empty;
}
if (_button != null)
{
_button.Interactive = context.IsInteractable;
}
}
if (_button != null)
else
{
_button.Interactive = context != null && context.IsInteractable;
_icon?.gameObject.SetActive(false);
_towerIconArea?.OnReset();
}
}
@ -59,6 +79,8 @@ namespace GeometryTD.UI
_icon.enabled = _icon.sprite != null;
}
_towerIconArea.OnReset();
if (_price != null)
{
_price.text = string.Empty;
@ -93,4 +115,4 @@ namespace GeometryTD.UI
_hasCachedDefaultIcon = true;
}
}
}
}

View File

@ -2,6 +2,7 @@ namespace GeometryTD.UI
{
public class CompAreaContext
{
public RepoItemContext[] Items;
public RepoItemContext[] ComponentItems;
public TowerRepoItemContext[] TowerItems;
}
}

View File

@ -2,7 +2,7 @@ namespace GeometryTD.UI
{
public class ParticipantAreaContext : UIContext
{
public RepoItemContext[] Items;
public TowerRepoItemContext[] TowerItems;
public int MaxCount;
}
}

View File

@ -0,0 +1,9 @@
using System;
namespace GeometryTD.UI
{
[Serializable]
public class TowerRepoItemContext : RepoItemContext
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 813496ec671788a4b975fa980ce16555
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -10,8 +10,9 @@ namespace GeometryTD.UI
{
private RepoFormContext BuildContext(RepoFormRawData rawData)
{
_itemContextMap.Clear();
_itemClickActionMap.Clear();
_itemDescSeedMap.Clear();
_compAreaTowerIds.Clear();
if (rawData?.Inventory == null)
{
_participantTowerIds.Clear();
@ -22,7 +23,8 @@ namespace GeometryTD.UI
Dictionary<long, BearingCompItemData> bearingMap = BuildComponentMap(rawData.Inventory.BearingComponents);
Dictionary<long, BaseCompItemData> baseMap = BuildComponentMap(rawData.Inventory.BaseComponents);
Dictionary<long, TowerItemData> towerMap = BuildTowerMap(rawData.Inventory.Towers);
List<RepoItemContext> items = new List<RepoItemContext>();
List<RepoItemContext> componentItems = new List<RepoItemContext>();
List<TowerRepoItemContext> towerItems = new List<TowerRepoItemContext>();
if (rawData.Inventory.Towers != null)
{
@ -33,15 +35,9 @@ namespace GeometryTD.UI
continue;
}
AddItemContext(items, new RepoItemContext
{
InstanceId = tower.InstanceId,
CanDrag = true,
EnduranceRate01 = ItemDescUtility.ResolveTowerEnduranceRate(tower, muzzleMap, bearingMap, baseMap),
ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.None,
IconAreaContext = BuildIconAreaContext(tower)
});
TowerRepoItemContext towerContext = BuildTowerRepoItemContext(tower, muzzleMap, bearingMap, baseMap,
RepoItemClickActionType.OpenDetail, true);
AddTowerItemContext(towerItems, towerContext);
AddItemDescSeed(
tower.InstanceId,
tower.Name,
@ -60,7 +56,7 @@ namespace GeometryTD.UI
continue;
}
AddItemContext(items, new RepoItemContext
RepoItemContext componentContext = new RepoItemContext
{
InstanceId = item.InstanceId,
CanDrag = true,
@ -68,7 +64,8 @@ namespace GeometryTD.UI
ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.Muzzle,
IconAreaContext = BuildIconAreaContext(item)
});
};
AddComponentItemContext(componentItems, componentContext);
AddItemDescSeed(
item.InstanceId,
item.Name,
@ -87,7 +84,7 @@ namespace GeometryTD.UI
continue;
}
AddItemContext(items, new RepoItemContext
RepoItemContext componentContext = new RepoItemContext
{
InstanceId = item.InstanceId,
CanDrag = true,
@ -95,7 +92,8 @@ namespace GeometryTD.UI
ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.Bearing,
IconAreaContext = BuildIconAreaContext(item)
});
};
AddComponentItemContext(componentItems, componentContext);
AddItemDescSeed(
item.InstanceId,
item.Name,
@ -114,7 +112,7 @@ namespace GeometryTD.UI
continue;
}
AddItemContext(items, new RepoItemContext
RepoItemContext componentContext = new RepoItemContext
{
InstanceId = item.InstanceId,
CanDrag = true,
@ -122,7 +120,8 @@ namespace GeometryTD.UI
ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.Base,
IconAreaContext = BuildIconAreaContext(item)
});
};
AddComponentItemContext(componentItems, componentContext);
AddItemDescSeed(
item.InstanceId,
item.Name,
@ -140,13 +139,14 @@ namespace GeometryTD.UI
CombineAreaContext = new CombineAreaContext(),
CompAreaContext = new CompAreaContext
{
Items = items.ToArray()
ComponentItems = componentItems.ToArray(),
TowerItems = towerItems.ToArray()
},
ParticipantAreaContext = participantAreaContext
};
}
private void AddItemContext(List<RepoItemContext> items, RepoItemContext itemContext)
private void AddComponentItemContext(List<RepoItemContext> items, RepoItemContext itemContext)
{
if (itemContext == null)
{
@ -154,7 +154,19 @@ namespace GeometryTD.UI
}
items.Add(itemContext);
_itemContextMap[itemContext.InstanceId] = itemContext;
_itemClickActionMap[itemContext.InstanceId] = itemContext.ClickActionType;
}
private void AddTowerItemContext(List<TowerRepoItemContext> items, TowerRepoItemContext itemContext)
{
if (itemContext == null)
{
return;
}
items.Add(itemContext);
_itemClickActionMap[itemContext.InstanceId] = itemContext.ClickActionType;
_compAreaTowerIds.Add(itemContext.InstanceId);
}
private void AddItemDescSeed(long itemId, string title, string typeText, string description, TagType[] tags)
@ -243,7 +255,7 @@ namespace GeometryTD.UI
IReadOnlyDictionary<long, BaseCompItemData> baseMap)
{
_participantTowerIds.Clear();
List<RepoItemContext> participantItems = new List<RepoItemContext>();
List<TowerRepoItemContext> participantItems = new List<TowerRepoItemContext>();
if (inventory?.ParticipantTowerInstanceIds != null && towerMap != null)
{
for (int i = 0; i < inventory.ParticipantTowerInstanceIds.Count; i++)
@ -264,41 +276,33 @@ namespace GeometryTD.UI
continue;
}
participantItems.Add(new RepoItemContext
TowerRepoItemContext towerContext = BuildTowerRepoItemContext(tower, muzzleMap, bearingMap, baseMap,
RepoItemClickActionType.RemoveParticipant, false);
if (towerContext != null)
{
InstanceId = tower.InstanceId,
CanDrag = false,
EnduranceRate01 = ItemDescUtility.ResolveTowerEnduranceRate(tower, muzzleMap, bearingMap, baseMap),
ClickActionType = RepoItemClickActionType.RemoveParticipant,
ComponentSlotType = TowerCompSlotType.None,
IconAreaContext = BuildIconAreaContext(tower)
});
participantItems.Add(towerContext);
_itemClickActionMap[towerContext.InstanceId] = towerContext.ClickActionType;
}
}
}
return new ParticipantAreaContext
{
Items = participantItems.ToArray(),
TowerItems = participantItems.ToArray(),
MaxCount = MaxParticipantCount
};
}
private void ApplyParticipantSelection()
{
if (Form == null || _itemContextMap.Count <= 0)
if (Form == null || _compAreaTowerIds.Count <= 0)
{
return;
}
foreach (KeyValuePair<long, RepoItemContext> pair in _itemContextMap)
foreach (long towerId in _compAreaTowerIds)
{
RepoItemContext itemContext = pair.Value;
if (itemContext == null || itemContext.ComponentSlotType != TowerCompSlotType.None)
{
continue;
}
Form.SetRepoItemSelected(pair.Key, _participantTowerIds.Contains(pair.Key));
Form.SetRepoItemSelected(towerId, _participantTowerIds.Contains(towerId));
}
}
@ -319,25 +323,33 @@ namespace GeometryTD.UI
ApplyParticipantSelection();
}
private static IconAreaContext BuildIconAreaContext(TowerItemData tower)
private static TowerRepoItemContext BuildTowerRepoItemContext(
TowerItemData tower,
IReadOnlyDictionary<long, MuzzleCompItemData> muzzleMap,
IReadOnlyDictionary<long, BearingCompItemData> bearingMap,
IReadOnlyDictionary<long, BaseCompItemData> baseMap,
RepoItemClickActionType clickActionType,
bool canDrag)
{
if (tower == null)
{
return new IconAreaContext
{
ComponentSlotType = TowerCompSlotType.None,
Rarity = RarityType.None,
Color = Color.white,
Icon = null
};
return null;
}
return new IconAreaContext
return new TowerRepoItemContext
{
InstanceId = tower.InstanceId,
CanDrag = canDrag,
EnduranceRate01 = ItemDescUtility.ResolveTowerEnduranceRate(tower, muzzleMap, bearingMap, baseMap),
ClickActionType = clickActionType,
ComponentSlotType = TowerCompSlotType.None,
Rarity = tower.Rarity,
Color = IconColorGenerator.GenerateForTower(tower),
Icon = null
IconAreaContext = new TowerIconAreaContext
{
Rarity = tower.Rarity,
MuzzleColor = ResolveComponentColor(tower.MuzzleComponentInstanceId, muzzleMap),
BearingColor = ResolveComponentColor(tower.BearingComponentInstanceId, bearingMap),
BaseColor = ResolveComponentColor(tower.BaseComponentInstanceId, baseMap)
}
};
}
@ -362,5 +374,21 @@ namespace GeometryTD.UI
Icon = null
};
}
private static Color ResolveComponentColor<TComp>(long instanceId,
IReadOnlyDictionary<long, TComp> componentMap)
where TComp : TowerCompItemData
{
if (instanceId > 0 &&
componentMap != null &&
componentMap.TryGetValue(instanceId, out TComp component) &&
component != null)
{
return IconColorGenerator.GenerateForComponent(component);
}
return Color.white;
}
}
}

View File

@ -11,9 +11,11 @@ namespace GeometryTD.UI
{
private const int MaxParticipantCount = 4;
private RepoFormUseCase _useCase;
private readonly Dictionary<long, RepoItemContext> _itemContextMap = new Dictionary<long, RepoItemContext>();
private readonly Dictionary<long, RepoItemClickActionType> _itemClickActionMap =
new Dictionary<long, RepoItemClickActionType>();
private readonly Dictionary<long, ItemDescSeed> _itemDescSeedMap = new Dictionary<long, ItemDescSeed>();
private readonly HashSet<long> _participantTowerIds = new HashSet<long>();
private readonly HashSet<long> _compAreaTowerIds = new HashSet<long>();
private sealed class ItemDescSeed
{
@ -111,14 +113,9 @@ namespace GeometryTD.UI
}
RepoItemClickActionType clickActionType = RepoItemClickActionType.OpenDetail;
if (sender is RepoItem clickedItem && clickedItem.Context != null)
if (_itemClickActionMap.TryGetValue(args.ItemId, out RepoItemClickActionType mappedAction))
{
clickActionType = clickedItem.Context.ClickActionType;
}
else if (_itemContextMap.TryGetValue(args.ItemId, out RepoItemContext itemContextFromMap) &&
itemContextFromMap != null)
{
clickActionType = itemContextFromMap.ClickActionType;
clickActionType = mappedAction;
}
if (args.ItemId <= 0)
@ -170,7 +167,7 @@ namespace GeometryTD.UI
return;
}
if (Form == null || !_itemContextMap.ContainsKey(args.ItemId))
if (Form == null || !_itemClickActionMap.ContainsKey(args.ItemId))
{
return;
}
@ -212,8 +209,8 @@ namespace GeometryTD.UI
{
return;
}
this.CloseUI();
CloseUI();
}
private void OnRepoCombineRequested(object sender, GameEventArgs e)
@ -258,12 +255,12 @@ namespace GeometryTD.UI
{
return;
}
if (_useCase == null || Form == null || args.TowerItemId <= 0)
{
return;
}
if (!_useCase.TryAddParticipantTower(args.TowerItemId))
{
return;

View File

@ -67,11 +67,6 @@ namespace GeometryTD.UI
InventoryParticipantUtility.NormalizeParticipantState(_fallbackInventory, MaxParticipantCount);
return _fallbackInventory;
}
public static BackpackInventoryData SampleInventory()
{
return InventorySeedUtility.CreateSampleInventory();
}
}
}

View File

@ -1,5 +1,5 @@
using GeometryTD.Definition;
using GeometryTD.CustomEvent;
using GeometryTD.Definition;
using UnityEngine;
using UnityEngine.EventSystems;
@ -102,19 +102,15 @@ namespace GeometryTD.UI
return;
}
RepoItem repoItem = pointerDrag.GetComponent<RepoItem>();
if (repoItem == null)
{
repoItem = pointerDrag.GetComponentInParent<RepoItem>();
}
if (repoItem == null)
IRepoDragItemView dragItem = pointerDrag.GetComponent<IRepoDragItemView>() ??
pointerDrag.GetComponentInParent<IRepoDragItemView>();
if (dragItem == null)
{
return;
}
bool assigned = TryAssignItem(repoItem.Context);
repoItem.SetDropResult(assigned);
bool assigned = TryAssignItem(dragItem.ComponentContext);
dragItem.SetDropResult(assigned);
}
private CombineSlotItem FindSlot(TowerCompSlotType slotType)

View File

@ -11,12 +11,17 @@ namespace GeometryTD.UI
{
[FormerlySerializedAs("m_Content")] [SerializeField] private Transform _content;
[FormerlySerializedAs("m_ItemTemplate")] [SerializeField] private RepoItem _itemTemplate;
[SerializeField] private TowerRepoItem _towerItemTemplate;
[FormerlySerializedAs("m_InstancePoolCapacity")] [SerializeField] private int _instancePoolCapacity = 64;
private readonly List<RepoItem> _activeItems = new List<RepoItem>();
private readonly Dictionary<long, RepoItem> _itemMap = new Dictionary<long, RepoItem>();
private IObjectPool<RepoItemObject> _itemPool;
private string _poolName;
private readonly List<RepoItem> _activeComponentItems = new List<RepoItem>();
private readonly List<TowerRepoItem> _activeTowerItems = new List<TowerRepoItem>();
private readonly Dictionary<long, RepoItem> _componentItemMap = new Dictionary<long, RepoItem>();
private readonly Dictionary<long, TowerRepoItem> _towerItemMap = new Dictionary<long, TowerRepoItem>();
private IObjectPool<RepoItemObject> _componentItemPool;
private IObjectPool<TowerRepoItemObject> _towerItemPool;
private string _componentPoolName;
private string _towerPoolName;
public void OnInit(CompAreaContext context)
{
@ -29,31 +34,46 @@ namespace GeometryTD.UI
EnsurePool();
OnReset();
if (context.Items == null || context.Items.Length == 0)
if (context.ComponentItems != null)
{
return;
foreach (RepoItemContext itemContext in context.ComponentItems)
{
RepoItem item = CreateOrSpawnComponentItem();
if (item == null)
{
continue;
}
item.gameObject.SetActive(true);
item.OnInit(itemContext);
_activeComponentItems.Add(item);
_componentItemMap[itemContext.InstanceId] = item;
}
}
foreach (var itemContext in context.Items)
if (context.TowerItems != null)
{
RepoItem item = CreateOrSpawnItem();
if (item == null)
foreach (TowerRepoItemContext itemContext in context.TowerItems)
{
continue;
}
TowerRepoItem item = CreateOrSpawnTowerItem();
if (item == null)
{
continue;
}
item.gameObject.SetActive(true);
item.OnInit(itemContext);
_activeItems.Add(item);
_itemMap[itemContext.InstanceId] = item;
item.gameObject.SetActive(true);
item.OnInit(itemContext);
_activeTowerItems.Add(item);
_towerItemMap[itemContext.InstanceId] = item;
}
}
}
public void OnReset()
{
for (int i = _activeItems.Count - 1; i >= 0; i--)
for (int i = _activeComponentItems.Count - 1; i >= 0; i--)
{
RepoItem item = _activeItems[i];
RepoItem item = _activeComponentItems[i];
if (item == null)
{
continue;
@ -61,49 +81,102 @@ namespace GeometryTD.UI
item.OnReset();
item.gameObject.SetActive(false);
_itemPool?.Unspawn(item);
_componentItemPool?.Unspawn(item);
}
_activeItems.Clear();
_itemMap.Clear();
for (int i = _activeTowerItems.Count - 1; i >= 0; i--)
{
TowerRepoItem item = _activeTowerItems[i];
if (item == null)
{
continue;
}
item.OnReset();
item.gameObject.SetActive(false);
_towerItemPool?.Unspawn(item);
}
_activeComponentItems.Clear();
_activeTowerItems.Clear();
_componentItemMap.Clear();
_towerItemMap.Clear();
}
private void OnDestroy()
{
OnReset();
_itemPool?.ReleaseAllUnused();
_componentItemPool?.ReleaseAllUnused();
_towerItemPool?.ReleaseAllUnused();
}
private void EnsurePool()
{
if (_itemPool != null)
if (_componentItemPool == null)
{
return;
_componentPoolName = $"RepoItemPool_{GetInstanceID()}";
_componentItemPool =
GameEntry.ObjectPool.CreateSingleSpawnObjectPool<RepoItemObject>(_componentPoolName,
_instancePoolCapacity);
}
_poolName = $"RepoItemPool_{GetInstanceID()}";
_itemPool = GameEntry.ObjectPool.CreateSingleSpawnObjectPool<RepoItemObject>(_poolName, _instancePoolCapacity);
if (_towerItemPool == null)
{
_towerPoolName = $"TowerRepoItemPool_{GetInstanceID()}";
_towerItemPool =
GameEntry.ObjectPool.CreateSingleSpawnObjectPool<TowerRepoItemObject>(_towerPoolName,
_instancePoolCapacity);
}
}
private RepoItem CreateOrSpawnItem()
private RepoItem CreateOrSpawnComponentItem()
{
if (_itemPool == null)
if (_componentItemPool == null)
{
return null;
}
RepoItemObject itemObject = _itemPool.Spawn();
RepoItemObject itemObject = _componentItemPool.Spawn();
RepoItem item = itemObject != null ? (RepoItem)itemObject.Target : null;
if (item == null)
{
if (_itemTemplate == null)
{
Log.Warning("CompArea requires an item template.");
Log.Warning("CompArea requires a component item template.");
return null;
}
item = Instantiate(_itemTemplate);
_itemPool.Register(RepoItemObject.Create(item), true);
_componentItemPool.Register(RepoItemObject.Create(item), true);
}
if (_content != null)
{
item.transform.SetParent(_content, false);
}
return item;
}
private TowerRepoItem CreateOrSpawnTowerItem()
{
if (_towerItemPool == null)
{
return null;
}
TowerRepoItemObject itemObject = _towerItemPool.Spawn();
TowerRepoItem item = itemObject != null ? (TowerRepoItem)itemObject.Target : null;
if (item == null)
{
if (_towerItemTemplate == null)
{
Log.Warning("CompArea requires a tower item template.");
return null;
}
item = Instantiate(_towerItemTemplate);
_towerItemPool.Register(TowerRepoItemObject.Create(item), true);
}
if (_content != null)
@ -116,12 +189,15 @@ namespace GeometryTD.UI
public void SetItemSelected(long itemId, bool isSelected)
{
if (!_itemMap.TryGetValue(itemId, out RepoItem item))
if (_componentItemMap.TryGetValue(itemId, out RepoItem componentItem))
{
return;
componentItem.SetSelected(isSelected);
}
item.SetSelected(isSelected);
if (_towerItemMap.TryGetValue(itemId, out TowerRepoItem towerItem))
{
towerItem.SetSelected(isSelected);
}
}
}
}

View File

@ -0,0 +1,19 @@
using GeometryTD.Definition;
namespace GeometryTD.UI
{
public interface IRepoDragItemView
{
long InstanceId { get; }
bool CanDrag { get; }
TowerCompSlotType ComponentSlotType { get; }
RepoItemClickActionType ClickActionType { get; }
RepoItemContext ComponentContext { get; }
void SetDropResult(bool assigned);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5cb3c8e275a9ba646a58a2656af31faa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -12,12 +12,12 @@ namespace GeometryTD.UI
public class ParticipantArea : MonoBehaviour, IDropHandler
{
[SerializeField] private Transform _content;
[SerializeField] private RepoItem _itemTemplate;
[SerializeField] private TowerRepoItem _towerItemTemplate;
[SerializeField] private int _instancePoolCapacity = 8;
private readonly List<RepoItem> _activeItems = new List<RepoItem>();
private readonly List<TowerRepoItem> _activeItems = new List<TowerRepoItem>();
private readonly HashSet<long> _boundItemIds = new HashSet<long>();
private IObjectPool<RepoItemObject> _itemPool;
private IObjectPool<TowerRepoItemObject> _itemPool;
private string _poolName;
private int _maxCount = 4;
@ -27,20 +27,20 @@ namespace GeometryTD.UI
EnsurePool();
_maxCount = Mathf.Max(1, context != null ? context.MaxCount : 4);
if (context?.Items == null || context.Items.Length <= 0)
if (context?.TowerItems == null || context.TowerItems.Length <= 0)
{
return;
}
for (int i = 0; i < context.Items.Length; i++)
for (int i = 0; i < context.TowerItems.Length; i++)
{
RepoItemContext itemContext = context.Items[i];
TowerRepoItemContext itemContext = context.TowerItems[i];
if (itemContext == null || itemContext.InstanceId <= 0)
{
continue;
}
RepoItem item = CreateOrSpawnItem();
TowerRepoItem item = CreateOrSpawnItem();
if (item == null)
{
continue;
@ -57,7 +57,7 @@ namespace GeometryTD.UI
{
for (int i = _activeItems.Count - 1; i >= 0; i--)
{
RepoItem item = _activeItems[i];
TowerRepoItem item = _activeItems[i];
if (item == null)
{
continue;
@ -79,19 +79,19 @@ namespace GeometryTD.UI
_itemPool?.ReleaseAllUnused();
}
public bool CanAssign(RepoItemContext itemContext)
public bool CanAssign(IRepoDragItemView dragItem)
{
if (itemContext == null || itemContext.InstanceId <= 0)
if (dragItem == null || dragItem.InstanceId <= 0)
{
return false;
}
if (itemContext.ComponentSlotType != TowerCompSlotType.None)
if (dragItem.ComponentSlotType != TowerCompSlotType.None)
{
return false;
}
if (_boundItemIds.Contains(itemContext.InstanceId))
if (_boundItemIds.Contains(dragItem.InstanceId))
{
return false;
}
@ -117,21 +117,21 @@ namespace GeometryTD.UI
return;
}
RepoItem repoItem = pointerDrag.GetComponent<RepoItem>() ?? pointerDrag.GetComponentInParent<RepoItem>();
if (repoItem == null)
IRepoDragItemView dragItem = pointerDrag.GetComponent<IRepoDragItemView>() ??
pointerDrag.GetComponentInParent<IRepoDragItemView>();
if (dragItem == null)
{
return;
}
RepoItemContext itemContext = repoItem.Context;
bool assigned = CanAssign(itemContext);
repoItem.SetDropResult(assigned);
bool assigned = CanAssign(dragItem);
dragItem.SetDropResult(assigned);
if (!assigned)
{
return;
}
GameEntry.Event.Fire(this, RepoParticipantAssignRequestedEventArgs.Create(itemContext.InstanceId));
GameEntry.Event.Fire(this, RepoParticipantAssignRequestedEventArgs.Create(dragItem.InstanceId));
}
private void EnsurePool()
@ -141,29 +141,30 @@ namespace GeometryTD.UI
return;
}
_poolName = $"ParticipantRepoItemPool_{GetInstanceID()}";
_itemPool = GameEntry.ObjectPool.CreateSingleSpawnObjectPool<RepoItemObject>(_poolName, _instancePoolCapacity);
_poolName = $"ParticipantTowerRepoItemPool_{GetInstanceID()}";
_itemPool =
GameEntry.ObjectPool.CreateSingleSpawnObjectPool<TowerRepoItemObject>(_poolName, _instancePoolCapacity);
}
private RepoItem CreateOrSpawnItem()
private TowerRepoItem CreateOrSpawnItem()
{
if (_itemPool == null)
{
return null;
}
RepoItemObject itemObject = _itemPool.Spawn();
RepoItem item = itemObject != null ? (RepoItem)itemObject.Target : null;
TowerRepoItemObject itemObject = _itemPool.Spawn();
TowerRepoItem item = itemObject != null ? (TowerRepoItem)itemObject.Target : null;
if (item == null)
{
if (_itemTemplate == null)
if (_towerItemTemplate == null)
{
Log.Warning("ParticipantArea requires an item template.");
Log.Warning("ParticipantArea requires a tower item template.");
return null;
}
item = Instantiate(_itemTemplate);
_itemPool.Register(RepoItemObject.Create(item), true);
item = Instantiate(_towerItemTemplate);
_itemPool.Register(TowerRepoItemObject.Create(item), true);
}
if (_content != null)

View File

@ -6,10 +6,10 @@ using UnityEngine.UI;
namespace GeometryTD.UI
{
public class RepoItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
public class RepoItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IRepoDragItemView
{
[SerializeField] private Image _bgImage;
[SerializeField] private IconArea _iconArea;
private static readonly Color SelectedColor = new Color32(255, 216, 102, 255);
@ -20,8 +20,8 @@ namespace GeometryTD.UI
[SerializeField] private RepoItemContext _context;
private CanvasGroup _canvasGroup;
private RectTransform _dragRoot;
private GameObject _dragGhostObject;
private RectTransform _dragGhostRect;
protected GameObject _dragGhostObject;
protected RectTransform _dragGhostRect;
private bool _isSelected;
private bool _isDragging;
private bool _dropHandled;
@ -29,6 +29,24 @@ namespace GeometryTD.UI
public RepoItemContext Context => _context;
public long InstanceId => _context != null ? _context.InstanceId : 0;
bool IRepoDragItemView.CanDrag => _context != null && _context.CanDrag;
public TowerCompSlotType ComponentSlotType =>
_context != null ? _context.ComponentSlotType : TowerCompSlotType.None;
public RepoItemClickActionType ClickActionType =>
_context != null ? _context.ClickActionType : RepoItemClickActionType.OpenDetail;
public RepoItemContext ComponentContext => _context;
protected IconArea IconArea => _iconArea;
protected Image BackgroundImage => _bgImage;
protected RectTransform DragRoot => _dragRoot;
private void Awake()
{
_canvasGroup = GetComponent<CanvasGroup>();
@ -43,7 +61,7 @@ namespace GeometryTD.UI
ResetDragState();
}
public void OnInit(RepoItemContext context)
public virtual void OnInit(RepoItemContext context)
{
if (context == null)
{
@ -52,14 +70,13 @@ namespace GeometryTD.UI
}
_context = context;
_iconArea.OnInit(context.IconAreaContext);
SetSelected(false);
ResetDragState();
}
public void OnReset()
public virtual void OnReset()
{
_context = null;
_iconArea.OnReset();
@ -165,6 +182,7 @@ namespace GeometryTD.UI
{
_canvasGroup.blocksRaycasts = true;
}
DestroyDragGhost();
_dragRoot = null;
@ -232,7 +250,7 @@ namespace GeometryTD.UI
return canvas.rootCanvas.transform as RectTransform;
}
private bool CreateDragGhost()
protected virtual bool CreateDragGhost()
{
DestroyDragGhost();
@ -246,7 +264,6 @@ namespace GeometryTD.UI
Material iconMaterial = _iconArea != null ? _iconArea.CurrentIconMaterial : null;
Vector2 iconSize = _iconArea != null ? _iconArea.CurrentIconSize : Vector2.zero;
// Towers may not have an icon sprite; fall back to background sprite so drag still works.
if (iconSprite == null && _bgImage != null)
{
iconSprite = _bgImage.sprite;
@ -260,7 +277,8 @@ namespace GeometryTD.UI
return false;
}
_dragGhostObject = new GameObject("RepoItemDragGhost", typeof(RectTransform), typeof(CanvasGroup), typeof(Image));
_dragGhostObject = new GameObject("RepoItemDragGhost", typeof(RectTransform), typeof(CanvasGroup),
typeof(Image));
_dragGhostObject.layer = gameObject.layer;
_dragGhostRect = _dragGhostObject.GetComponent<RectTransform>();
@ -273,6 +291,7 @@ namespace GeometryTD.UI
{
iconSize = DefaultDragGhostSize;
}
_dragGhostRect.sizeDelta = iconSize;
Image ghostImage = _dragGhostObject.GetComponent<Image>();
@ -290,7 +309,7 @@ namespace GeometryTD.UI
return true;
}
private void UpdateDragGhostPosition(PointerEventData eventData)
protected virtual void UpdateDragGhostPosition(PointerEventData eventData)
{
if (_dragGhostRect == null || _dragRoot == null || eventData == null)
{
@ -304,7 +323,7 @@ namespace GeometryTD.UI
}
}
private void DestroyDragGhost()
protected virtual void DestroyDragGhost()
{
if (_dragGhostObject != null)
{
@ -329,3 +348,4 @@ namespace GeometryTD.UI
}
}
}

View File

@ -0,0 +1,109 @@
using UnityEngine;
using UnityEngine.UI;
namespace GeometryTD.UI
{
public class TowerRepoItem : RepoItem
{
private static readonly Vector2 DefaultTowerDragGhostSize = new Vector2(64f, 64f);
public new TowerRepoItemContext Context => base.Context as TowerRepoItemContext;
public void OnInit(TowerRepoItemContext context)
{
base.OnInit(context);
}
protected override bool CreateDragGhost()
{
DestroyDragGhost();
if (DragRoot == null)
{
return false;
}
TowerIconArea towerIconArea = IconArea as TowerIconArea;
if (towerIconArea == null)
{
return base.CreateDragGhost();
}
_dragGhostObject = new GameObject("TowerRepoItemDragGhost", typeof(RectTransform), typeof(CanvasGroup));
_dragGhostObject.layer = gameObject.layer;
_dragGhostRect = _dragGhostObject.GetComponent<RectTransform>();
_dragGhostRect.SetParent(DragRoot, false);
_dragGhostRect.anchorMin = new Vector2(0.5f, 0.5f);
_dragGhostRect.anchorMax = new Vector2(0.5f, 0.5f);
_dragGhostRect.pivot = new Vector2(0.5f, 0.5f);
Vector2 iconSize = IconArea != null ? IconArea.CurrentIconSize : Vector2.zero;
if (iconSize.x <= 0f || iconSize.y <= 0f)
{
iconSize = BackgroundImage != null ? BackgroundImage.rectTransform.rect.size : DefaultTowerDragGhostSize;
}
if (iconSize.x <= 0f || iconSize.y <= 0f)
{
iconSize = DefaultTowerDragGhostSize;
}
_dragGhostRect.sizeDelta = iconSize;
bool hasAnyLayer = false;
hasAnyLayer |= TryCreateLayer("Base", towerIconArea.BaseIconSprite, towerIconArea.BaseIconColor,
towerIconArea.BaseIconMaterial, _dragGhostRect, 0);
hasAnyLayer |= TryCreateLayer("Bearing", towerIconArea.BearingIconSprite, towerIconArea.BearingIconColor,
towerIconArea.BearingIconMaterial, _dragGhostRect, 1);
hasAnyLayer |= TryCreateLayer("Muzzle", towerIconArea.MuzzleIconSprite, towerIconArea.MuzzleIconColor,
towerIconArea.MuzzleIconMaterial, _dragGhostRect, 2);
if (!hasAnyLayer)
{
DestroyDragGhost();
return base.CreateDragGhost();
}
CanvasGroup ghostCanvasGroup = _dragGhostObject.GetComponent<CanvasGroup>();
ghostCanvasGroup.blocksRaycasts = false;
ghostCanvasGroup.interactable = false;
_dragGhostObject.transform.SetAsLastSibling();
return true;
}
private static bool TryCreateLayer(
string layerName,
Sprite sprite,
Color color,
Material material,
RectTransform parent,
int siblingIndex)
{
if (parent == null || sprite == null)
{
return false;
}
GameObject layerObject = new GameObject($"TowerGhost{layerName}", typeof(RectTransform), typeof(Image));
layerObject.layer = parent.gameObject.layer;
RectTransform layerRect = layerObject.GetComponent<RectTransform>();
layerRect.SetParent(parent, false);
layerRect.anchorMin = Vector2.zero;
layerRect.anchorMax = Vector2.one;
layerRect.offsetMin = Vector2.zero;
layerRect.offsetMax = Vector2.zero;
layerRect.SetSiblingIndex(siblingIndex);
Image layerImage = layerObject.GetComponent<Image>();
layerImage.raycastTarget = false;
layerImage.sprite = sprite;
layerImage.color = color;
layerImage.material = material;
layerImage.preserveAspect = true;
return true;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: caf7b65cc179a5d46828128f574ed63e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,21 @@
using System;
using GeometryTD.Definition;
using UnityEngine;
namespace GeometryTD.UI
{
[Serializable]
public class TowerIconAreaContext : IconAreaContext
{
public Color MuzzleColor = Color.white;
public Color BearingColor = Color.white;
public Color BaseColor = Color.white;
public TowerIconAreaContext()
{
ComponentSlotType = TowerCompSlotType.None;
Color = Color.white;
Icon = null;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e3576597006db5b458566429f98a6f43
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,4 +1,3 @@
using System;
using GeometryTD.Definition;
using UnityEngine;
using UnityEngine.UI;
@ -14,15 +13,17 @@ namespace GeometryTD.UI
private IconAreaContext _context;
public Sprite CurrentIconSprite => _icon != null ? _icon.sprite : null;
public virtual Sprite CurrentIconSprite => _icon != null ? _icon.sprite : null;
public Color CurrentIconColor => _icon != null ? _icon.color : Color.white;
public virtual Color CurrentIconColor => _icon != null ? _icon.color : Color.white;
public Vector2 CurrentIconSize => _icon != null ? _icon.rectTransform.rect.size : Vector2.zero;
public virtual Vector2 CurrentIconSize => _icon != null ? _icon.rectTransform.rect.size : Vector2.zero;
public Material CurrentIconMaterial => _icon != null ? _icon.material : null;
public virtual Material CurrentIconMaterial => _icon != null ? _icon.material : null;
public void OnInit(IconAreaContext context)
public virtual RectTransform IconRectTransform => _icon != null ? _icon.rectTransform : null;
public virtual void OnInit(IconAreaContext context)
{
if (context == null)
{
@ -46,9 +47,10 @@ namespace GeometryTD.UI
SetRarity(_context.Rarity);
SetIconColor(_context.Color);
SetIconVisible(true);
}
public void SetIcon(Sprite sprite)
public virtual void SetIcon(Sprite sprite)
{
if (_icon != null)
{
@ -56,7 +58,7 @@ namespace GeometryTD.UI
}
}
public void SetRarity(RarityType rarity)
public virtual void SetRarity(RarityType rarity)
{
if (_board == null)
{
@ -74,7 +76,7 @@ namespace GeometryTD.UI
};
}
public void SetIconColor(Color color)
public virtual void SetIconColor(Color color)
{
if (_icon == null)
{
@ -84,11 +86,20 @@ namespace GeometryTD.UI
_icon.color = color;
}
public void OnReset()
public virtual void SetIconVisible(bool visible)
{
if (_icon != null)
{
_icon.enabled = visible;
}
}
public virtual void OnReset()
{
SetIcon(null);
SetRarity(RarityType.None);
SetIconColor(Color.clear);
SetIconVisible(true);
}
}
}

View File

@ -0,0 +1,72 @@
using UnityEngine;
using UnityEngine.UI;
namespace GeometryTD.UI
{
public class TowerIconArea : IconArea
{
[SerializeField] private Image _baseIcon;
[SerializeField] private Image _bearingIcon;
[SerializeField] private Image _muzzleIcon;
public Sprite BaseIconSprite => _baseIcon != null ? _baseIcon.sprite : null;
public Sprite BearingIconSprite => _bearingIcon != null ? _bearingIcon.sprite : null;
public Sprite MuzzleIconSprite => _muzzleIcon != null ? _muzzleIcon.sprite : null;
public Color BaseIconColor => _baseIcon != null ? _baseIcon.color : Color.white;
public Color BearingIconColor => _bearingIcon != null ? _bearingIcon.color : Color.white;
public Color MuzzleIconColor => _muzzleIcon != null ? _muzzleIcon.color : Color.white;
public Material BaseIconMaterial => _baseIcon != null ? _baseIcon.material : null;
public Material BearingIconMaterial => _bearingIcon != null ? _bearingIcon.material : null;
public Material MuzzleIconMaterial => _muzzleIcon != null ? _muzzleIcon.material : null;
public override void OnInit(IconAreaContext context)
{
if (!(context is TowerIconAreaContext towerContext))
{
base.OnInit(context);
return;
}
SetRarity(towerContext.Rarity);
SetIconVisible(false);
SetLayerColor(_baseIcon, towerContext.BaseColor);
SetLayerColor(_bearingIcon, towerContext.BearingColor);
SetLayerColor(_muzzleIcon, towerContext.MuzzleColor);
}
public void OnInit(TowerIconAreaContext context)
{
OnInit((IconAreaContext)context);
}
public override void OnReset()
{
base.OnReset();
SetLayerColor(_baseIcon, Color.clear);
SetLayerColor(_bearingIcon, Color.clear);
SetLayerColor(_muzzleIcon, Color.clear);
SetIconVisible(false);
}
private static void SetLayerColor(Image icon, Color color)
{
if (icon == null)
{
return;
}
icon.color = color;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 33a1436bff53c844e858f3bced1565ca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,4 +1,4 @@
using System;
using System;
using GeometryTD.Definition;
using UnityEngine;
@ -162,7 +162,9 @@ namespace GeometryTD.CustomUtility
MuzzleComponentInstanceId = source.MuzzleComponentInstanceId,
BearingComponentInstanceId = source.BearingComponentInstanceId,
BaseComponentInstanceId = source.BaseComponentInstanceId,
Stats = CloneTowerStats(source.Stats)
Stats = CloneTowerStats(source.Stats),
ComposedIconSprite = source.ComposedIconSprite,
ComposedIconKey = source.ComposedIconKey
};
}
@ -205,3 +207,4 @@ namespace GeometryTD.CustomUtility
}

View File

@ -19,41 +19,12 @@ namespace GeometryTD.CustomUtility
Rarity = RarityType.Green,
Endurance = 90f,
IsAssembledIntoTower = true,
AttackDamage = new[] { 20, 30, 40, 50, 80 },
AttackDamage = new[] { 200, 300, 400, 500, 800 },
DamageRandomRate = 0.05f,
AttackMethodType = AttackMethodType.NormalBullet,
Constraint = string.Empty,
Tags = new[] { TagType.Fire }
};
inventory.MuzzleComponents.Add(muzzle);
inventory.MuzzleComponents.Add(new MuzzleCompItemData
{
InstanceId = 10002,
ConfigId = 2,
Name = "控制枪口",
Rarity = RarityType.Blue,
Endurance = 80,
IsAssembledIntoTower = false,
AttackDamage = new[] { 30, 50, 70, 90, 100 },
DamageRandomRate = 0.01f,
AttackMethodType = AttackMethodType.NormalBullet,
Constraint = string.Empty,
Tags = new[] { TagType.Ice, TagType.FreezeMask }
});
inventory.MuzzleComponents.Add(new MuzzleCompItemData
{
InstanceId = 10003,
ConfigId = 3,
Name = "穿透枪口",
Rarity = RarityType.Purple,
Endurance = 97f,
IsAssembledIntoTower = false,
AttackDamage = new[] { 50, 55, 60, 80, 90 },
DamageRandomRate = 0.02f,
AttackMethodType = AttackMethodType.NormalBullet,
Constraint = string.Empty,
Tags = new[] { TagType.Pierce, TagType.Crit }
});
BearingCompItemData bearing = new BearingCompItemData
{
@ -63,38 +34,11 @@ namespace GeometryTD.CustomUtility
Rarity = RarityType.Green,
Endurance = 1f,
IsAssembledIntoTower = true,
RotateSpeed = new[] { 10f, 12f, 13f, 14f, 15f },
AttackRange = new[] { 2f, 2f, 2f, 2f, 2f },
RotateSpeed = new[] { 100f, 120f, 130f, 140f, 150f },
AttackRange = new[] { 3f, 4f, 5f, 6f, 8f },
Constraint = string.Empty,
Tags = new[] { TagType.Fire }
};
inventory.BearingComponents.Add(bearing);
inventory.BearingComponents.Add(new BearingCompItemData
{
InstanceId = 20002,
ConfigId = 2,
Name = "控制轴承",
Rarity = RarityType.Blue,
Endurance = 20,
IsAssembledIntoTower = false,
RotateSpeed = new[] { 20f, 25f, 30f, 32f, 35f },
AttackRange = new[] { 6f, 6.5f, 7f, 8f, 8f },
Constraint = string.Empty,
Tags = new[] { TagType.Ice, TagType.Shatter }
});
inventory.BearingComponents.Add(new BearingCompItemData
{
InstanceId = 20003,
ConfigId = 3,
Name = "穿透轴承",
Rarity = RarityType.Purple,
Endurance = 96f,
IsAssembledIntoTower = false,
RotateSpeed = new[] { 60f, 70f, 80f, 90f, 100f },
AttackRange = new[] { 4f, 4.5f, 5f, 5.5f, 6f },
Constraint = string.Empty,
Tags = new[] { TagType.Pierce, TagType.Overpenetrate }
});
BaseCompItemData baseComp = new BaseCompItemData
{
@ -104,38 +48,11 @@ namespace GeometryTD.CustomUtility
Rarity = RarityType.Green,
Endurance = 88f,
IsAssembledIntoTower = true,
AttackSpeed = new[] { 2f, 1.5f, 1f, 0.8f, 0.7f },
AttackSpeed = new[] { 1f, 2f, 3f, 3.5f, 0.7f },
AttackPropertyType = AttackPropertyType.Fire,
Constraint = string.Empty,
Tags = new[] { TagType.Fire }
};
inventory.BaseComponents.Add(baseComp);
inventory.BaseComponents.Add(new BaseCompItemData
{
InstanceId = 30002,
ConfigId = 2,
Name = "控制底座",
Rarity = RarityType.Blue,
Endurance = 50f,
IsAssembledIntoTower = false,
AttackSpeed = new[] { 4f, 4.2f, 4.4f, 4.6f, 4.8f },
AttackPropertyType = AttackPropertyType.Ice,
Constraint = string.Empty,
Tags = new[] { TagType.Ice, TagType.AbsoluteZero }
});
inventory.BaseComponents.Add(new BaseCompItemData
{
InstanceId = 30003,
ConfigId = 3,
Name = "穿透底座",
Rarity = RarityType.Purple,
Endurance = 30f,
IsAssembledIntoTower = false,
AttackSpeed = new[] { 1f, 1f, 1f, 1f, 1f },
AttackPropertyType = AttackPropertyType.Physics,
Constraint = string.Empty,
Tags = new[] { TagType.Pierce, TagType.Execution }
});
TowerItemData tower = new TowerItemData
{
@ -151,35 +68,103 @@ namespace GeometryTD.CustomUtility
AttackDamage = new[] { 200, 220, 240, 260, 300 },
DamageRandomRate = 0f,
RotateSpeed = new[] { 200f, 210f, 220f, 230f, 240f },
AttackRange = new[] { 4.5f, 4.7f, 4.9f, 5.1f, 5.3f },
AttackSpeed = new[] { 1.5f, 1.2f, 1.1f, 1.0f, 0.8f },
AttackRange = new[] { 4.5f, 4.5f, 4.5f, 4.5f, 4.5f },
AttackSpeed = new[] { 1.0f, 1.2f, 1.3f, 1.4f, 0.5f },
AttackMethodType = AttackMethodType.NormalBullet,
AttackPropertyType = AttackPropertyType.Fire,
Tags = new[] { TagType.Fire, TagType.BurnSpread }
}
};
inventory.MuzzleComponents.Add(muzzle);
inventory.BaseComponents.Add(baseComp);
inventory.BearingComponents.Add(bearing);
inventory.Towers.Add(tower);
inventory.Towers.Add(new TowerItemData
inventory.MuzzleComponents.Add(new MuzzleCompItemData
{
InstanceId = 90002,
Name = "测试防御塔-B",
InstanceId = 10002,
ConfigId = 2,
Name = "控制枪口",
Rarity = RarityType.Blue,
IsParticipatingInCombat = false,
MuzzleComponentInstanceId = 0,
BearingComponentInstanceId = 0,
BaseComponentInstanceId = 0,
Stats = new TowerStatsData
{
AttackDamage = new[] { 200, 220, 240, 260, 300 },
DamageRandomRate = 0.1f,
RotateSpeed = new[] { 200f, 210f, 220f, 230f, 240f },
AttackRange = new[] { 4.5f, 4.7f, 4.9f, 5.1f, 5.3f },
AttackSpeed = new[] { 1.5f, 1.2f, 1.1f, 1.0f, 0.8f },
AttackMethodType = AttackMethodType.NormalBullet,
AttackPropertyType = AttackPropertyType.Physics,
Tags = new[] { TagType.Pierce }
}
Endurance = 80,
IsAssembledIntoTower = false,
AttackDamage = new[] { 200, 300, 400, 500, 600 },
DamageRandomRate = 0.01f,
AttackMethodType = AttackMethodType.NormalBullet,
Constraint = string.Empty,
Tags = new[] { TagType.Ice, TagType.FreezeMask }
});
inventory.MuzzleComponents.Add(new MuzzleCompItemData
{
InstanceId = 10003,
ConfigId = 3,
Name = "穿透枪口",
Rarity = RarityType.Purple,
Endurance = 97f,
IsAssembledIntoTower = false,
AttackDamage = new[] { 50, 55, 60, 80, 90 },
DamageRandomRate = 0.02f,
AttackMethodType = AttackMethodType.NormalBullet,
Constraint = string.Empty,
Tags = new[] { TagType.Pierce, TagType.Crit }
});
inventory.BearingComponents.Add(new BearingCompItemData
{
InstanceId = 20002,
ConfigId = 2,
Name = "控制轴承",
Rarity = RarityType.Blue,
Endurance = 20,
IsAssembledIntoTower = false,
RotateSpeed = new[] { 200f, 250f, 300f, 320f, 350f },
AttackRange = new[] { 6f, 6.5f, 7f, 8f, 8f },
Constraint = string.Empty,
Tags = new[] { TagType.Ice, TagType.Shatter }
});
inventory.BearingComponents.Add(new BearingCompItemData
{
InstanceId = 20003,
ConfigId = 3,
Name = "穿透轴承",
Rarity = RarityType.Purple,
Endurance = 96f,
IsAssembledIntoTower = false,
RotateSpeed = new[] { 60f, 70f, 80f, 90f, 100f },
AttackRange = new[] { 4f, 4.5f, 5f, 5.5f, 6f },
Constraint = string.Empty,
Tags = new[] { TagType.Pierce, TagType.Overpenetrate }
});
inventory.BaseComponents.Add(new BaseCompItemData
{
InstanceId = 30002,
ConfigId = 2,
Name = "控制底座",
Rarity = RarityType.Blue,
Endurance = 50f,
IsAssembledIntoTower = false,
AttackSpeed = new[] { 4f, 4.2f, 4.4f, 4.6f, 4.8f },
AttackPropertyType = AttackPropertyType.Ice,
Constraint = string.Empty,
Tags = new[] { TagType.Ice, TagType.AbsoluteZero }
});
inventory.BaseComponents.Add(new BaseCompItemData
{
InstanceId = 30003,
ConfigId = 3,
Name = "穿透底座",
Rarity = RarityType.Purple,
Endurance = 30f,
IsAssembledIntoTower = false,
AttackSpeed = new[] { 1f, 1f, 1f, 1f, 1f },
AttackPropertyType = AttackPropertyType.Physics,
Constraint = string.Empty,
Tags = new[] { TagType.Pierce, TagType.Execution }
});
inventory.ParticipantTowerInstanceIds.Add(90001);

View File

@ -0,0 +1,130 @@
using System.Collections.Generic;
using GeometryTD.Definition;
using UnityEngine;
namespace GeometryTD.CustomUtility
{
public static class TowerComposedIconCacheUtility
{
private const string MuzzleAssetName = "Muzzle";
private const string BearingAssetName = "Bearing";
private const string BaseAssetName = "Base";
private static Sprite _muzzleSprite;
private static Sprite _bearingSprite;
private static Sprite _baseSprite;
private static bool s_RequestedMuzzle;
private static bool s_RequestedBearing;
private static bool s_RequestedBase;
public static Sprite ResolveTowerIconSprite(
TowerItemData tower,
IReadOnlyDictionary<long, MuzzleCompItemData> muzzleMap,
IReadOnlyDictionary<long, BearingCompItemData> bearingMap,
IReadOnlyDictionary<long, BaseCompItemData> baseMap)
{
if (tower == null)
{
return null;
}
if (!TryGetComponents(tower, muzzleMap, bearingMap, baseMap,
out MuzzleCompItemData muzzleComp,
out BearingCompItemData bearingComp,
out BaseCompItemData baseComp))
{
return null;
}
Color muzzleColor = IconColorGenerator.GenerateForComponent(muzzleComp);
Color bearingColor = IconColorGenerator.GenerateForComponent(bearingComp);
Color baseColor = IconColorGenerator.GenerateForComponent(baseComp);
string cacheKey = TowerIconComposeUtility.BuildCacheKey(
tower.MuzzleComponentInstanceId,
tower.BearingComponentInstanceId,
tower.BaseComponentInstanceId,
muzzleColor,
bearingColor,
baseColor);
if (tower.ComposedIconSprite != null && string.Equals(tower.ComposedIconKey, cacheKey))
{
return tower.ComposedIconSprite;
}
EnsureBaseSpritesRequested();
if (_muzzleSprite == null || _bearingSprite == null || _baseSprite == null)
{
return null;
}
Sprite composedSprite = TowerIconComposeUtility.Compose(
_muzzleSprite,
muzzleColor,
_bearingSprite,
bearingColor,
_baseSprite,
baseColor);
if (composedSprite == null)
{
return null;
}
tower.ComposedIconSprite = composedSprite;
tower.ComposedIconKey = cacheKey;
return composedSprite;
}
private static bool TryGetComponents(
TowerItemData tower,
IReadOnlyDictionary<long, MuzzleCompItemData> muzzleMap,
IReadOnlyDictionary<long, BearingCompItemData> bearingMap,
IReadOnlyDictionary<long, BaseCompItemData> baseMap,
out MuzzleCompItemData muzzleComp,
out BearingCompItemData bearingComp,
out BaseCompItemData baseComp)
{
muzzleComp = null;
bearingComp = null;
baseComp = null;
if (tower == null || muzzleMap == null || bearingMap == null || baseMap == null)
{
return false;
}
return muzzleMap.TryGetValue(tower.MuzzleComponentInstanceId, out muzzleComp) &&
bearingMap.TryGetValue(tower.BearingComponentInstanceId, out bearingComp) &&
baseMap.TryGetValue(tower.BaseComponentInstanceId, out baseComp) &&
muzzleComp != null && bearingComp != null && baseComp != null;
}
private static void EnsureBaseSpritesRequested()
{
if (GameEntry.SpriteCache == null)
{
return;
}
if (!s_RequestedMuzzle)
{
s_RequestedMuzzle = true;
GameEntry.SpriteCache.GetSprite(MuzzleAssetName, sprite => { _muzzleSprite = sprite; });
}
if (!s_RequestedBearing)
{
s_RequestedBearing = true;
GameEntry.SpriteCache.GetSprite(BearingAssetName, sprite => { _bearingSprite = sprite; });
}
if (!s_RequestedBase)
{
s_RequestedBase = true;
GameEntry.SpriteCache.GetSprite(BaseAssetName, sprite => { _baseSprite = sprite; });
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a705ccdd02d2d3440934d4ab06228547
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,148 @@
using System;
using System.Globalization;
using UnityEngine;
namespace GeometryTD.CustomUtility
{
public static class TowerIconComposeUtility
{
public static Sprite Compose(
Sprite muzzleSprite,
Color muzzleColor,
Sprite bearingSprite,
Color bearingColor,
Sprite baseSprite,
Color baseColor)
{
if (muzzleSprite == null || bearingSprite == null || baseSprite == null)
{
return null;
}
Sprite referenceSprite = muzzleSprite ?? bearingSprite ?? baseSprite;
if (referenceSprite == null)
{
return null;
}
int width = Mathf.RoundToInt(referenceSprite.rect.width);
int height = Mathf.RoundToInt(referenceSprite.rect.height);
if (width <= 0 || height <= 0)
{
return null;
}
return ComposeWithRenderTexture(
muzzleSprite,
muzzleColor,
bearingSprite,
bearingColor,
baseSprite,
baseColor,
width,
height,
referenceSprite);
}
public static string BuildCacheKey(
long muzzleId,
long bearingId,
long baseId,
Color muzzleColor,
Color bearingColor,
Color baseColor)
{
return string.Format(
CultureInfo.InvariantCulture,
"v2|{0}|{1}|{2}|{3}|{4}|{5}",
muzzleId,
bearingId,
baseId,
ToColorKey(muzzleColor),
ToColorKey(bearingColor),
ToColorKey(baseColor));
}
private static Sprite ComposeWithRenderTexture(
Sprite muzzleSprite,
Color muzzleColor,
Sprite bearingSprite,
Color bearingColor,
Sprite baseSprite,
Color baseColor,
int width,
int height,
Sprite referenceSprite)
{
RenderTexture rt = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.ARGB32);
RenderTexture previous = RenderTexture.active;
try
{
RenderTexture.active = rt;
GL.PushMatrix();
GL.LoadPixelMatrix(0f, width, 0f, height);
GL.Clear(true, true, Color.clear);
DrawSpriteToRenderTarget(baseSprite, baseColor, width, height);
DrawSpriteToRenderTarget(bearingSprite, bearingColor, width, height);
DrawSpriteToRenderTarget(muzzleSprite, muzzleColor, width, height);
GL.PopMatrix();
Texture2D composedTexture = new Texture2D(width, height, TextureFormat.RGBA32, false);
composedTexture.ReadPixels(new Rect(0f, 0f, width, height), 0, 0);
composedTexture.Apply(false, false);
return CreateSprite(composedTexture, referenceSprite);
}
catch (Exception)
{
return null;
}
finally
{
RenderTexture.active = previous;
RenderTexture.ReleaseTemporary(rt);
}
}
private static void DrawSpriteToRenderTarget(Sprite sprite, Color color, int width, int height)
{
if (sprite == null || sprite.texture == null)
{
return;
}
Rect textureRect = sprite.textureRect;
Texture texture = sprite.texture;
Rect uvRect = new Rect(
textureRect.x / texture.width,
textureRect.y / texture.height,
textureRect.width / texture.width,
textureRect.height / texture.height);
Graphics.DrawTexture(new Rect(0f, 0f, width, height), texture, uvRect, 0, 0, 0, 0, color);
}
private static Sprite CreateSprite(Texture2D texture, Sprite referenceSprite)
{
if (texture == null || referenceSprite == null)
{
return null;
}
float width = Mathf.Max(1f, referenceSprite.rect.width);
float height = Mathf.Max(1f, referenceSprite.rect.height);
Vector2 pivot = new Vector2(referenceSprite.pivot.x / width, referenceSprite.pivot.y / height);
return Sprite.Create(texture, new Rect(0f, 0f, texture.width, texture.height), pivot, referenceSprite.pixelsPerUnit);
}
private static string ToColorKey(Color color)
{
Color32 c = color;
return c.r.ToString("X2", CultureInfo.InvariantCulture) +
c.g.ToString("X2", CultureInfo.InvariantCulture) +
c.b.ToString("X2", CultureInfo.InvariantCulture) +
c.a.ToString("X2", CultureInfo.InvariantCulture);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d9256e2c4f74b7448afbdbac8f7cb26f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -976,6 +976,17 @@ PrefabInstance:
serializedVersion: 3
m_TransformParent: {fileID: 1714606292658179489}
m_Modifications:
- target: {fileID: 272351400812969041, guid: b656295a0a0134840bdcd41e203f12c7,
type: 3}
propertyPath: m_Type
value: 1
objectReference: {fileID: 0}
- target: {fileID: 272351400812969041, guid: b656295a0a0134840bdcd41e203f12c7,
type: 3}
propertyPath: m_Sprite
value:
objectReference: {fileID: 21300000, guid: 9f847ec5e66e03e4ead1d3c5f7b510e8,
type: 3}
- target: {fileID: 274828358581623048, guid: b656295a0a0134840bdcd41e203f12c7,
type: 3}
propertyPath: m_Pivot.x

View File

@ -52,6 +52,8 @@ MonoBehaviour:
_content: {fileID: 1805918912036091081}
_itemTemplate: {fileID: 8394974685918372820, guid: 2ead8e403e355dd4b9296a9d0a871a83,
type: 3}
_towerItemTemplate: {fileID: 4730609612906943122, guid: 81bda3e30070fa34884bafbe9a9c72f9,
type: 3}
_instancePoolCapacity: 64
--- !u!1 &2380285751925872027
GameObject:
@ -181,7 +183,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
_content: {fileID: 6811784024412969593}
_itemTemplate: {fileID: 8394974685918372820, guid: 2ead8e403e355dd4b9296a9d0a871a83,
_towerItemTemplate: {fileID: 4730609612906943122, guid: 81bda3e30070fa34884bafbe9a9c72f9,
type: 3}
_instancePoolCapacity: 8
--- !u!222 &5388327515888957795

View File

@ -0,0 +1,447 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &177671855419091867
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3323726282767525619}
- component: {fileID: 399955496901366910}
- component: {fileID: 7579875247493712075}
m_Layer: 5
m_Name: TowerIconArea
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3323726282767525619
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 177671855419091867}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1038851730778667217}
- {fileID: 2859743021803601866}
- {fileID: 6845015578436394914}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: -20, y: -20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &399955496901366910
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 177671855419091867}
m_CullTransparentMesh: 1
--- !u!114 &7579875247493712075
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 177671855419091867}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 33a1436bff53c844e858f3bced1565ca, type: 3}
m_Name:
m_EditorClassIdentifier:
_board: {fileID: 1792178769172340962}
_icon: {fileID: 4918346613506060866}
_baseIcon: {fileID: 7285567316465127825}
_bearingIcon: {fileID: 4366841213109481872}
_muzzleIcon: {fileID: 4666251790512386674}
--- !u!1 &803783036851305114
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2859743021803601866}
- component: {fileID: 4968140022138979945}
- component: {fileID: 4918346613506060866}
m_Layer: 5
m_Name: Image
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2859743021803601866
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 803783036851305114}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3323726282767525619}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4968140022138979945
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 803783036851305114}
m_CullTransparentMesh: 1
--- !u!114 &4918346613506060866
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 803783036851305114}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &1636419954436272212
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 9145919182730712671}
- component: {fileID: 2651698208426096613}
- component: {fileID: 4366841213109481872}
m_Layer: 5
m_Name: Bearing
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &9145919182730712671
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1636419954436272212}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 1
m_Children:
- {fileID: 6782923152009204558}
m_Father: {fileID: 6845015578436394914}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2651698208426096613
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1636419954436272212}
m_CullTransparentMesh: 1
--- !u!114 &4366841213109481872
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1636419954436272212}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: -2413806693520163455, guid: e31321df62f1587469b0733897970679,
type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &2318020840094036371
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6782923152009204558}
- component: {fileID: 3207702065525898594}
- component: {fileID: 4666251790512386674}
m_Layer: 5
m_Name: Muzzle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6782923152009204558
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2318020840094036371}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 1
m_Children: []
m_Father: {fileID: 9145919182730712671}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 29.586662}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.2886667}
--- !u!222 &3207702065525898594
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2318020840094036371}
m_CullTransparentMesh: 1
--- !u!114 &4666251790512386674
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2318020840094036371}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 0.24213827, b: 0.24213827, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 7482667652216324306, guid: 5ba74e3a185274149b15c24b321bead2,
type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &5542159351280798647
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1038851730778667217}
- component: {fileID: 2454678530691112152}
- component: {fileID: 1792178769172340962}
m_Layer: 5
m_Name: board
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1038851730778667217
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5542159351280798647}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3323726282767525619}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 20, y: 20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2454678530691112152
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5542159351280798647}
m_CullTransparentMesh: 1
--- !u!114 &1792178769172340962
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5542159351280798647}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: a8c07bbe04fdaf04b80e27f651a8edd6, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &5919608345427997939
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6845015578436394914}
- component: {fileID: 1519331956184262112}
- component: {fileID: 7285567316465127825}
m_Layer: 5
m_Name: Base
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6845015578436394914
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5919608345427997939}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 1
m_Children:
- {fileID: 9145919182730712671}
m_Father: {fileID: 3323726282767525619}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1519331956184262112
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5919608345427997939}
m_CullTransparentMesh: 1
--- !u!114 &7285567316465127825
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5919608345427997939}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.13836467, g: 0.13836467, b: 0.13836467, a: 1}
m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 7482667652216324306, guid: 80a3790c48fc91d4ebcb4d7e2efbb8c8,
type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ab6ee7e8b2a678544af490543d99f665
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,356 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1986516583823050331
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6860417479053386125}
- component: {fileID: 8570341357903165526}
- component: {fileID: 5089068592453588603}
m_Layer: 5
m_Name: bg
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6860417479053386125
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1986516583823050331}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8349727755164431499}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8570341357903165526
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1986516583823050331}
m_CullTransparentMesh: 1
--- !u!114 &5089068592453588603
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1986516583823050331}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 9f847ec5e66e03e4ead1d3c5f7b510e8, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &3287359693314616602
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7253748148476290235}
- component: {fileID: 412242389824419156}
- component: {fileID: 4730609612906943122}
m_Layer: 5
m_Name: TowerRepoItem
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7253748148476290235
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3287359693314616602}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8349727755164431499}
- {fileID: 884849595327022251}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 160, y: 160}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &412242389824419156
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3287359693314616602}
m_CullTransparentMesh: 1
--- !u!114 &4730609612906943122
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3287359693314616602}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: caf7b65cc179a5d46828128f574ed63e, type: 3}
m_Name:
m_EditorClassIdentifier:
_bgImage: {fileID: 5089068592453588603}
_iconArea: {fileID: 5428668331781712531}
_context:
InstanceId: 0
CanDrag: 0
EnduranceRate01: 0
ClickActionType: 0
ComponentSlotType: 0
IconAreaContext:
Rarity: 0
ComponentSlotType: 0
Color: {r: 1, g: 1, b: 1, a: 1}
Icon: {fileID: 0}
--- !u!1 &5586290829740215320
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8349727755164431499}
- component: {fileID: 8024563988191439697}
m_Layer: 5
m_Name: CommonButton
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8349727755164431499
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5586290829740215320}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6860417479053386125}
m_Father: {fileID: 7253748148476290235}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &8024563988191439697
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5586290829740215320}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a5079836f95c2a44b96fa331487ebb70, type: 3}
m_Name:
m_EditorClassIdentifier:
_onHover:
m_PersistentCalls:
m_Calls: []
_onClick:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 4730609612906943122}
m_TargetAssemblyTypeName: GeometryTD.UI.TowerRepoItem, Assembly-CSharp
m_MethodName: OnClick
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 10001
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
_onHoverEnd:
m_PersistentCalls:
m_Calls: []
_allowFade: 1
--- !u!1001 &2479127645651034712
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 7253748148476290235}
m_Modifications:
- target: {fileID: 177671855419091867, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_Name
value: TowerIconArea
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_Pivot.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_Pivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMax.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMax.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMin.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_SizeDelta.x
value: -20
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_SizeDelta.y
value: -20
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: ab6ee7e8b2a678544af490543d99f665, type: 3}
--- !u!224 &884849595327022251 stripped
RectTransform:
m_CorrespondingSourceObject: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
m_PrefabInstance: {fileID: 2479127645651034712}
m_PrefabAsset: {fileID: 0}
--- !u!114 &5428668331781712531 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 7579875247493712075, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
m_PrefabInstance: {fileID: 2479127645651034712}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 33a1436bff53c844e858f3bced1565ca, type: 3}
m_Name:
m_EditorClassIdentifier:

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 81bda3e30070fa34884bafbe9a9c72f9
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,80 +1,5 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &5412566102378209566
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4152009404387722330}
- component: {fileID: 3873445585384354699}
- component: {fileID: 272351400812969041}
m_Layer: 5
m_Name: Icon
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4152009404387722330
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5412566102378209566}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8201350274026178469}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 80, y: 80}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &3873445585384354699
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5412566102378209566}
m_CullTransparentMesh: 1
--- !u!114 &272351400812969041
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5412566102378209566}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300146, guid: 29c9cded5e558164aaf8c9bf08aa1510, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &6361423396692704141
GameObject:
m_ObjectHideFlags: 0
@ -100,7 +25,7 @@ RectTransform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6361423396692704141}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
@ -179,8 +104,9 @@ RectTransform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8201350274026178469}
- {fileID: 28444767019028035}
- {fileID: 2412538576477069160}
- {fileID: 8201350274026178469}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
@ -200,9 +126,158 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 4da5ef45ee18db44ebe3c015dddb61d6, type: 3}
m_Name:
m_EditorClassIdentifier:
_icon: {fileID: 272351400812969041}
_icon: {fileID: 5411719625189444569}
_price: {fileID: 6134693184638222351}
_button: {fileID: 8644563062325311724}
_towerIconArea: {fileID: 7379728654387442000}
--- !u!1001 &1106531443240827291
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 274828358581623048}
m_Modifications:
- target: {fileID: 177671855419091867, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_Name
value: TowerIconArea
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_Pivot.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_Pivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMax.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMax.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMin.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_SizeDelta.x
value: -20
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_SizeDelta.y
value: -20
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: ab6ee7e8b2a678544af490543d99f665, type: 3}
--- !u!224 &2412538576477069160 stripped
RectTransform:
m_CorrespondingSourceObject: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
m_PrefabInstance: {fileID: 1106531443240827291}
m_PrefabAsset: {fileID: 0}
--- !u!114 &5411719625189444569 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 4918346613506060866, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
m_PrefabInstance: {fileID: 1106531443240827291}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &7379728654387442000 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 7579875247493712075, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
m_PrefabInstance: {fileID: 1106531443240827291}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 33a1436bff53c844e858f3bced1565ca, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1001 &5730140866277425490
PrefabInstance:
m_ObjectHideFlags: 0
@ -216,6 +291,11 @@ PrefabInstance:
propertyPath: m_Name
value: CommonButton
objectReference: {fileID: 0}
- target: {fileID: 1341699087252484061, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_Color.a
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1920576543566152029, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_text
@ -351,34 +431,24 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_AnchorMax.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_AnchorMin.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_SizeDelta.y
value: 60
value: -50.000023
objectReference: {fileID: 0}
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_AnchoredPosition.y
value: -80
value: -75.000015
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects:
- {fileID: 7888786393168201163, guid: 2307f223279813546a43b221ddd496cc, type: 3}
m_AddedGameObjects:
- targetCorrespondingSourceObject: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
insertIndex: -1
addedObject: {fileID: 4152009404387722330}
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 2307f223279813546a43b221ddd496cc, type: 3}
--- !u!114 &6134693184638222351 stripped