using UnityEngine; using TMPro; using RuntimeData; using Logic; namespace TH1Renderer { public class ProjectileRenderer { 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) { _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.PatchouliAttack) { _ROprojectile.transform.Find("PatchouliAttack").gameObject.SetActive(true); moveFullTime = Table.Instance.AnimDataAssets.ProjectileMoveTime; } if (projectileData.ProjectileType == ProjectileType.RemiliaAttack) { _ROprojectile.transform.Find("RemiliaAttack").gameObject.SetActive(true); moveFullTime = Table.Instance.AnimDataAssets.ProjectileMoveTime; } 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; } else if (projectileData.ProjectileType == ProjectileType.Faith) { _ROprojectile.transform.Find("Faith").gameObject.SetActive(true); moveFullTime = Table.Instance.AnimDataAssets.ProjectileCoinMoveTime; } } public GameObject GetROProjectile() { 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; if (_projectileData.ProjectileType == ProjectileType.Faith) parabola_height = 0f; } Vector3 linearPos; Vector3 finalPos; float arcHeight; float arcOffset; float t; //如果是coin 或者 faith 完全单独处理 if (_projectileData.ProjectileMoveType == ProjectileMoveType.CoinParabola) { var startPos = moveStartPos; startPos.y -= 5f; if (_projectileData.ProjectileType == ProjectileType.Faith) startPos.y += 5f; var middlePos = startPos; middlePos.y += 1f; // 增加时间 moveTime += Time.deltaTime / moveFullTime; float showTime = 0.3f; if (_projectileData.ProjectileType == ProjectileType.Faith) showTime = 0.5f; //前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); } } } } }