using JetBrains.Annotations; using UnityEngine; using UnityEngine.UI; using TMPro; public class archievePrefab : MonoBehaviour { [Header("Inspector")] public Image archieve_btmImage; public TextMeshProUGUI archieve_name; public TextMeshProUGUI archieve_description; [Header("Rarity Background Sprites")] public Sprite whiteLevelSprite; public Sprite greenLevelSprite; public Sprite blueLevelSprite; public Sprite purpleLevelSprite; public Sprite goldenLevelSprite; public Sprite redLevelSprite; public Sprite colorfulLevelSprite; [Header("Name Text Colors")] public Color whiteNameColor = Color.black; public Color greenNameColor = Color.black; public Color blueNameColor = Color.white; public Color purpleNameColor = Color.white; public Color goldenNameColor = Color.black; public Color redNameColor = Color.white; public Color colorfulNameColor = Color.black; [Header("Description Gradient Colors")] public bool overrideDescriptionToBlack = false; public Gradient whiteDescGradient; public bool whiteHorizontal; public Gradient greenDescGradient; public bool greenHorizontal; public Gradient blueDescGradient; public bool blueHorizontal; public Gradient purpleDescGradient; public bool purpleHorizontal; public Gradient goldenDescGradient; public bool goldenHorizontal; public Gradient redDescGradient; public bool redHorizontal; public Gradient colorfulDescGradient; public bool colorfulHorizontal; public void Setup(AchievementLevel level) { if (archieve_name != null) archieve_name.text = level.levelName; if (archieve_description != null) archieve_description.text = level.description; SetRarityVisuals(level.rarity); } private void SetRarityVisuals(AchievementRarity rarity) { if (archieve_btmImage == null) return; Sprite targetSprite = whiteLevelSprite; Color targetNameColor = whiteNameColor; Gradient targetGradient = whiteDescGradient; bool isHorizontal = whiteHorizontal; switch (rarity) { case AchievementRarity.Common: targetSprite = whiteLevelSprite; targetNameColor = whiteNameColor; targetGradient = whiteDescGradient; isHorizontal = whiteHorizontal; break; case AchievementRarity.Advanced: targetSprite = greenLevelSprite; targetNameColor = greenNameColor; targetGradient = greenDescGradient; isHorizontal = greenHorizontal; break; case AchievementRarity.Rare: targetSprite = blueLevelSprite; targetNameColor = blueNameColor; targetGradient = blueDescGradient; isHorizontal = blueHorizontal; break; case AchievementRarity.Epic: targetSprite = purpleLevelSprite; targetNameColor = purpleNameColor; targetGradient = purpleDescGradient; isHorizontal = purpleHorizontal; break; case AchievementRarity.Legendary: targetSprite = goldenLevelSprite; targetNameColor = goldenNameColor; targetGradient = goldenDescGradient; isHorizontal = goldenHorizontal; break; case AchievementRarity.Mythic: targetSprite = redLevelSprite; targetNameColor = redNameColor; targetGradient = redDescGradient; isHorizontal = redHorizontal; break; case AchievementRarity.Exquisite: targetSprite = colorfulLevelSprite; targetNameColor = colorfulNameColor; targetGradient = colorfulDescGradient; isHorizontal = colorfulHorizontal; break; } // 1. 替换底图图片 (archieve_btmImage) if (targetSprite != null) { archieve_btmImage.sprite = targetSprite; archieve_btmImage.color = Color.white; } // 2. 设置成就名字颜色 (archieve_name) if (archieve_name != null) { archieve_name.color = targetNameColor; } // 3. 设置描述文本渐变颜色 (archieve_description) if (archieve_description != null && targetGradient != null) { ApplyGlobalGradient(archieve_description, targetGradient, isHorizontal); } } /// /// 将渐变色应用到整个文本对象,而不是单个字符 /// private void ApplyGlobalGradient(TextMeshProUGUI textComponent, Gradient gradient, bool isHorizontal) { if (overrideDescriptionToBlack) { textComponent.color = Color.black; textComponent.enableVertexGradient = false; // 如果处于覆盖模式,直接返回,不执行复杂的顶点渐变逻辑 return; } // 必须先强制更新网格以获取正确的顶点数据 textComponent.ForceMeshUpdate(); TMP_TextInfo textInfo = textComponent.textInfo; int characterCount = textInfo.characterCount; if (characterCount == 0) return; // 获取文本的边界(用于计算比例) float minPos = isHorizontal ? textInfo.meshInfo[0].vertices[0].x : textInfo.meshInfo[0].vertices[0].y; float maxPos = minPos; for (int i = 0; i < characterCount; i++) { if (!textInfo.characterInfo[i].isVisible) continue; int materialIndex = textInfo.characterInfo[i].materialReferenceIndex; int vertexIndex = textInfo.characterInfo[i].vertexIndex; Vector3[] vertices = textInfo.meshInfo[materialIndex].vertices; for (int j = 0; j < 4; j++) { float pos = isHorizontal ? vertices[vertexIndex + j].x : vertices[vertexIndex + j].y; if (pos < minPos) minPos = pos; if (pos > maxPos) maxPos = pos; } } float range = maxPos - minPos; if (range < 0.001f) range = 1f; // 再次遍历并应用颜色 for (int i = 0; i < characterCount; i++) { if (!textInfo.characterInfo[i].isVisible) continue; int materialIndex = textInfo.characterInfo[i].materialReferenceIndex; int vertexIndex = textInfo.characterInfo[i].vertexIndex; Color32[] colors = textInfo.meshInfo[materialIndex].colors32; Vector3[] vertices = textInfo.meshInfo[materialIndex].vertices; for (int j = 0; j < 4; j++) { float pos = isHorizontal ? vertices[vertexIndex + j].x : vertices[vertexIndex + j].y; // 计算该顶点在整个范围内的 normalized 位置 (0-1) float t = (pos - minPos) / range; // 如果是垂直渐变,通常是从上到下,而 Y 轴向上,所以需要反转 t if (!isHorizontal) t = 1f - t; colors[vertexIndex + j] = gradient.Evaluate(t); } } // 更新网格颜色 textComponent.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32); } }