TH1/My project/Assets/Scripts/TH1Renderer/ProjectileRenderer.cs
2025-06-19 21:07:02 +08:00

218 lines
9.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using TMPro;
using RuntimeData;
using Logic;
namespace TH1Renderer
{
public class ProjectileRenderer
{
private MapData _mapData;
private Main _main;
private GameObject _ROprojectile;
private ProjectileData _projectileData;
//------- Update缓存数据 -------//
private UnitData _unitData;
private GridData _gridData;
private PlayerData _playerData;
// 移动相关变量
private bool _needMove = false;
private Vector3 moveStartPos;
private Vector3 moveEndPos;
private float moveTime = 0f;
private float moveFullTime = 1f;
public ProjectileRenderer(GameObject prefab,Transform father, ProjectileData projectileData, MapData mapData, Main main)
{
_mapData = mapData;
_main = main;
_projectileData = projectileData;
_ROprojectile = GameObject.Instantiate(prefab, projectileData.StartPos, Quaternion.identity, father);
//每个projectile从创生就要开始move
_needMove = true;
moveTime = 0f;
moveStartPos = projectileData.StartPos;
moveEndPos = projectileData.EndPos;
foreach (Transform child in _ROprojectile.transform)
child.gameObject.SetActive(false);
if (projectileData.ProjectileType == ProjectileType.Arrow)
{
_ROprojectile.transform.Find("Arrow").gameObject.SetActive(true);
moveFullTime = Table.Instance.AnimDataAssets.ProjectileMoveTime;
}
else if (projectileData.ProjectileType == ProjectileType.Bomb)
{
_ROprojectile.transform.Find("Bomb").gameObject.SetActive(true);
moveFullTime = Table.Instance.AnimDataAssets.ProjectileBombMoveTime;
}
else if (projectileData.ProjectileType == ProjectileType.CityExp)
{
_ROprojectile.transform.Find("CityExp").gameObject.SetActive(true);
moveFullTime = Table.Instance.AnimDataAssets.ProjectileCityExpMoveTime;
}
else if (projectileData.ProjectileType == ProjectileType.Coin)
{
_ROprojectile.transform.Find("Coin").gameObject.SetActive(true);
moveFullTime = Table.Instance.AnimDataAssets.ProjectileCoinMoveTime;
}
}
public GameObject GetROUnit() { return _ROprojectile; }
public void Die()
{
GameObject.Destroy(_ROprojectile.gameObject);
}
public void Update()
{
// 如果需要移动
if (_needMove)
{
float parabola_height = 0f;
float time_para = 1f;
if (_projectileData.ProjectileMoveType == ProjectileMoveType.Parabola)
parabola_height = 0.3f;
if (_projectileData.ProjectileMoveType == ProjectileMoveType.HighParabola)
parabola_height = 0.5f;
if (_projectileData.ProjectileMoveType == ProjectileMoveType.CityExpHighParabola)
parabola_height = 0.6f;
if (_projectileData.ProjectileMoveType == ProjectileMoveType.CoinParabola)
parabola_height = -0.1f;
Vector3 linearPos;
Vector3 finalPos;
float arcHeight;
float arcOffset;
float t;
//如果是coin 完全单独处理
if (_projectileData.ProjectileMoveType == ProjectileMoveType.CoinParabola)
{
var startPos = moveStartPos;
startPos.y -= 5f;
var middlePos = startPos;
middlePos.y -= 2f;
// 增加时间
moveTime += Time.deltaTime / moveFullTime;
float showTime = 0.3f;
//前showTime%的时间轻微移动
if (moveTime < showTime)
{
t = Mathf.Clamp01(moveTime/showTime);
// 计算水平线性插值位置
linearPos = Vector3.Lerp(startPos, middlePos, t);
// 添加抛物线效果 (在y轴方向)
// 使用sin函数创建一个弧形在中间点达到最高
arcHeight = Vector3.Distance(startPos, middlePos) * parabola_height; // 弧高为距离的20%
arcOffset = Mathf.Sin(t * Mathf.PI) * arcHeight;
// 最终位置 = 线性插值位置 + 抛物线高度偏移
finalPos = new Vector3(
linearPos.x,
linearPos.y + arcOffset,
linearPos.z
);
// 设置投射物位置
_ROprojectile.transform.position = finalPos;
}
//后70%的时间才做抛物线
else
{
// 计算当前位置的插值因子 (0到1之间)
t = Mathf.Clamp01((moveTime - showTime) / (1f - showTime));
// 计算水平线性插值位置
linearPos = Vector3.Lerp(middlePos, moveEndPos, t);
// 添加抛物线效果 (在y轴方向)
// 使用sin函数创建一个弧形在中间点达到最高
arcHeight = Vector3.Distance(middlePos, moveEndPos) * parabola_height; // 弧高为距离的20%
arcOffset = Mathf.Sin(t * Mathf.PI) * arcHeight;
// 最终位置 = 线性插值位置 + 抛物线高度偏移
finalPos = new Vector3(
linearPos.x,
linearPos.y + arcOffset,
linearPos.z
);
// 设置投射物位置
_ROprojectile.transform.position = finalPos;
}
// 如果移动完成
if (moveTime >= 1.0f)
{
_needMove = false;
// 延迟销毁投射物
GameObject.Destroy(_ROprojectile);
}
return;
}
//处理其他的运动曲线
// 增加时间
moveTime += Time.deltaTime / moveFullTime;
// 计算当前位置的插值因子 (0到1之间)
t = Mathf.Clamp01(moveTime);
// 计算水平线性插值位置
linearPos = Vector3.Lerp(moveStartPos, moveEndPos, t);
// 添加抛物线效果 (在y轴方向)
// 使用sin函数创建一个弧形在中间点达到最高
arcHeight = Vector3.Distance(moveStartPos, moveEndPos) * parabola_height; // 弧高为距离的20%
arcOffset = Mathf.Sin(t * Mathf.PI) * arcHeight;
// 最终位置 = 线性插值位置 + 抛物线高度偏移
finalPos = new Vector3(
linearPos.x,
linearPos.y + arcOffset,
linearPos.z
);
// 设置投射物位置
_ROprojectile.transform.position = finalPos;
// 根据移动方向更新投射物的旋转
if (_projectileData.ProjectileMoveType != ProjectileMoveType.CityExpHighParabola && t < 0.99f) // 避免在最后时刻计算方向
{
Vector3 direction = (t < 0.98f) ?
(_ROprojectile.transform.position - _ROprojectile.transform.position - _ROprojectile.transform.forward) :
(moveEndPos - _ROprojectile.transform.position).normalized;
if (direction != Vector3.zero)
{
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
_ROprojectile.transform.rotation = Quaternion.Euler(0, 0, angle - 90); // 假设精灵默认朝上
}
}
// 如果移动完成
if (moveTime >= 1.0f)
{
_needMove = false;
// 延迟销毁投射物
GameObject.Destroy(_ROprojectile);
}
}
}
}
}