修复旋转问题 + 防御塔范围可视化

- BasicBearingComp 和 ShooterBullet 的旋转由之前的 3D 方式调整为只旋转 Z 轴
- DefenseTowerController 通过 LineRenderer 添加了攻击范围可视化
This commit is contained in:
SepComet
2026-03-02 10:15:13 +08:00
parent 564817d752
commit 344191a91c
11 changed files with 324 additions and 35 deletions
@@ -1,5 +1,6 @@
using Components;
using GeometryTD.Entity.EntityData;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace GeometryTD.Entity
@@ -36,6 +37,7 @@ namespace GeometryTD.Entity
return;
}
ConstrainToZRotation();
_shooterBullet.OnShow(bulletData);
if (_shooterBullet.TryConsumeDespawnRequest())
{
@@ -64,5 +66,11 @@ namespace GeometryTD.Entity
_shooterBullet?.OnReset();
base.OnHide(isShutdown, userData);
}
private void ConstrainToZRotation()
{
Vector3 localEulerAngles = CachedTransform.localEulerAngles;
CachedTransform.localRotation = Quaternion.Euler(0f, 0f, localEulerAngles.z);
}
}
}
@@ -8,6 +8,11 @@ namespace GeometryTD.Entity
{
private DefenseTowerController _towerController;
public void SetAttackRangeVisible(bool visible)
{
_towerController?.SetAttackRangeVisible(visible);
}
protected override void OnInit(object userData)
{
base.OnInit(userData);
@@ -48,6 +53,7 @@ namespace GeometryTD.Entity
protected override void OnHide(bool isShutdown, object userData)
{
_towerController?.SetAttackRangeVisible(false);
_towerController?.OnReset();
base.OnHide(isShutdown, userData);
}
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using GeometryTD.Definition;
using GeometryTD.Entity.EntityData;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace GeometryTD.Entity
{
@@ -116,11 +117,14 @@ namespace GeometryTD.Entity
_currentHealth = Mathf.Max(0, _currentHealth - damage);
if (_maxHealth > 0)
{
GameEntry.HPBar?.ShowHPBar(this, (float)previousHealth / _maxHealth, (float)_currentHealth / _maxHealth);
GameEntry.HPBar?.ShowHPBar(this, (float)previousHealth / _maxHealth,
(float)_currentHealth / _maxHealth);
Log.Info($"ShowBar: {_currentHealth}/{_maxHealth}");
}
if (_currentHealth <= 0)
{
Log.Info("Enemy Dead");
_killedEnemyEntityIds.Add(Id);
RequestDespawn();
}
@@ -192,4 +196,4 @@ namespace GeometryTD.Entity
GameEntry.Entity.HideEntity(Entity);
}
}
}
}
@@ -55,7 +55,6 @@ namespace GeometryTD.Entity
Name = Utility.Text.Format("[Entity {0}]", Id);
CachedTransform.localPosition = _entityData.Position;
CachedTransform.localRotation = _entityData.Rotation;
CachedTransform.localScale = Vector3.one;
}
#if UNITY_2017_3_OR_NEWER
@@ -46,6 +46,7 @@ namespace GeometryTD.Entity
private bool _hasSelectedFoundationCell;
private Vector3Int _selectedFoundationCell;
private int _selectedTowerEntityId;
private int _attackRangeVisibleTowerEntityId;
public IReadOnlyList<Vector3Int> PathCells => _pathCells;
public IReadOnlyList<Vector3Int> FoundationCells => _foundationCells;
@@ -486,6 +487,8 @@ namespace GeometryTD.Entity
ClearSelectedObject();
break;
}
UpdateTowerAttackRangeDisplay(_selectedTowerEntityId);
}
private bool TryBuildTower(int buildIndex)
@@ -517,6 +520,7 @@ namespace GeometryTD.Entity
_foundationCellByTowerEntityId[towerEntityId] = _selectedFoundationCell;
_towerStatsByEntityId[towerEntityId] = CloneTowerStats(towerStats);
_selectedTowerEntityId = towerEntityId;
UpdateTowerAttackRangeDisplay(_selectedTowerEntityId);
return true;
}
@@ -552,6 +556,11 @@ namespace GeometryTD.Entity
_foundationCellByTowerEntityId[fallbackTowerEntityId] = foundationCell;
_towerStatsByEntityId[fallbackTowerEntityId] = CloneTowerStats(oldStats);
_selectedTowerEntityId = fallbackTowerEntityId;
UpdateTowerAttackRangeDisplay(_selectedTowerEntityId);
}
else
{
UpdateTowerAttackRangeDisplay(0);
}
GameEntry.CombatNode?.AddCoin(upgradeCost);
@@ -564,6 +573,7 @@ namespace GeometryTD.Entity
_hasSelectedFoundationCell = true;
_selectedFoundationCell = foundationCell;
_selectedTowerEntityId = newTowerEntityId;
UpdateTowerAttackRangeDisplay(_selectedTowerEntityId);
return true;
}
@@ -664,11 +674,54 @@ namespace GeometryTD.Entity
private void ClearSelectedObject()
{
UpdateTowerAttackRangeDisplay(0);
_hasSelectedFoundationCell = false;
_selectedFoundationCell = default;
_selectedTowerEntityId = 0;
}
private void UpdateTowerAttackRangeDisplay(int towerEntityId)
{
if (_attackRangeVisibleTowerEntityId != 0 && _attackRangeVisibleTowerEntityId != towerEntityId)
{
SetTowerAttackRangeVisible(_attackRangeVisibleTowerEntityId, false);
_attackRangeVisibleTowerEntityId = 0;
}
if (towerEntityId == 0)
{
if (_attackRangeVisibleTowerEntityId != 0)
{
SetTowerAttackRangeVisible(_attackRangeVisibleTowerEntityId, false);
_attackRangeVisibleTowerEntityId = 0;
}
return;
}
if (SetTowerAttackRangeVisible(towerEntityId, true))
{
_attackRangeVisibleTowerEntityId = towerEntityId;
}
}
private static bool SetTowerAttackRangeVisible(int towerEntityId, bool visible)
{
if (towerEntityId == 0 || GameEntry.Entity == null)
{
return false;
}
EntityBase gameEntity = GameEntry.Entity.GetGameEntity(towerEntityId);
if (gameEntity is not DefenseTowerEntity towerEntity)
{
return false;
}
towerEntity.SetAttackRangeVisible(visible);
return true;
}
private int GetBuildTowerCost(int buildIndex)
{
if (_buildTowerCosts == null || buildIndex < 0 || buildIndex >= _buildTowerCosts.Length)
@@ -707,7 +760,7 @@ namespace GeometryTD.Entity
case 0:
return new DefenseTowerStatsData
{
AttackDamage = 10,
AttackDamage = 100,
DamageRandomRate = 0f,
RotateSpeed = 200f,
AttackRange = 4.5f,
@@ -755,7 +808,7 @@ namespace GeometryTD.Entity
default:
return new DefenseTowerStatsData
{
AttackDamage = 10,
AttackDamage = 100,
DamageRandomRate = 0f,
RotateSpeed = 180f,
AttackRange = 5f,