Snapshot of the existing Unity 6 language-learning word game before any refactoring. Adds Unity .gitignore and .gitattributes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
846 lines
No EOL
24 KiB
C#
846 lines
No EOL
24 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
using UnityEngine.SceneManagement;
|
||
using UnityEngine.UI;
|
||
|
||
public class AnalogyLogicGameScene : MonoBehaviour
|
||
{
|
||
[Header("TXT (6 Language Analogy Data)")]
|
||
public TextAsset analogyFile;
|
||
|
||
[Header("UI")]
|
||
public TMP_Text questionText;
|
||
public TMP_Text[] answerTexts;
|
||
public Button[] answerButtons;
|
||
public Button submitButton;
|
||
|
||
public TMP_Text feedbackText;
|
||
public TMP_Text scoreText;
|
||
public TMP_Text comboText;
|
||
public TMP_Text timerText;
|
||
public TMP_Text selectedWordsText;
|
||
|
||
[Header("EXTRAS")]
|
||
public Button extraTimeButton;
|
||
public Button extraHintButton;
|
||
public Button extraSkipButton;
|
||
|
||
[Header("━━━ BACK BUTTON ━━━━━━━━━━━━━━━━━━━━━━━━")]
|
||
public Button backButton;
|
||
public string backSceneName = "ModSec 11";
|
||
|
||
[Header("COLORS")]
|
||
public Color normalColor = new Color32(255, 255, 255, 70);
|
||
public Color selectedColor = new Color32(60, 110, 200, 255);
|
||
public Color correctColor = new Color32(0, 200, 0, 255);
|
||
public Color wrongColor = new Color32(200, 0, 0, 255);
|
||
|
||
[Header("━━━ FEEDBACK TEXT SETTINGS ━━━━━━━━━━━━━")]
|
||
public bool feedbackOnTop = true;
|
||
public float feedbackTopY = 400f;
|
||
public float feedbackFontSize = 72f;
|
||
|
||
[Header("━━━ ANIMATION SETTINGS ━━━━━━━━━━━━━━━━━")]
|
||
[Range(0.80f, 1f)] public float selectedScale = 0.94f;
|
||
public float selectAnimTime = 0.10f;
|
||
public float enterAnimTime = 0.22f;
|
||
|
||
// 0=TR, 1=EN, 2=ES, 3=DE, 4=FR, 5=PT
|
||
private string langCode; // "tr","en"...
|
||
private int langIndex; // 0–5
|
||
|
||
private class AnalogyQ
|
||
{
|
||
// data[language, field] -> 0:A 1:B 2:C 3:COR 4:W1 5:W2 6:W3
|
||
public string[,] data = new string[6, 7];
|
||
}
|
||
|
||
private List<AnalogyQ> questions = new List<AnalogyQ>();
|
||
|
||
private int correctIndex = -1;
|
||
private int selectedIndex = -1;
|
||
private bool locked = false;
|
||
private int lastQ = -1;
|
||
|
||
private int score = 0;
|
||
private int combo = 0;
|
||
private int correctCount = 0;
|
||
private int wrongCount = 0;
|
||
|
||
private float timeLeft = 60f;
|
||
private float nextTimer = 0f;
|
||
|
||
private string modKey = "Mod11";
|
||
|
||
readonly Color timerNormalColor = Color.white;
|
||
readonly Color timerWarnColor = new Color32(255, 80, 80, 255);
|
||
|
||
Vector3[] originalButtonScales;
|
||
Vector3[] originalButtonPositions;
|
||
Coroutine[] buttonScaleCoroutines;
|
||
Coroutine[] buttonEnterCoroutines;
|
||
|
||
Coroutine feedbackCo;
|
||
|
||
// ================================================================
|
||
void Start()
|
||
{
|
||
// Uses the same system as SentenceOrderGameScene
|
||
langCode = PlayerPrefs.GetString("QuestionLangCode", "en");
|
||
langIndex = GetLangIndex();
|
||
|
||
if (analogyFile == null)
|
||
{
|
||
Debug.LogError("AnalogyLogicGameScene: analogyFile is not assigned!");
|
||
if (questionText != null)
|
||
questionText.text = "TXT NOT FOUND!";
|
||
enabled = false;
|
||
return;
|
||
}
|
||
|
||
LoadTXT6Lang(analogyFile.text);
|
||
|
||
if (questions.Count == 0)
|
||
{
|
||
Debug.LogError("AnalogyLogicGameScene: TXT is empty or invalid!");
|
||
if (questionText != null)
|
||
questionText.text = "EMPTY FILE!";
|
||
enabled = false;
|
||
return;
|
||
}
|
||
|
||
if (answerButtons == null || answerButtons.Length < 4 ||
|
||
answerTexts == null || answerTexts.Length < 4)
|
||
{
|
||
Debug.LogError("AnalogyLogicGameScene: 4 answerButtons / answerTexts are required.");
|
||
enabled = false;
|
||
return;
|
||
}
|
||
|
||
CacheButtonData();
|
||
PrepareFeedbackText();
|
||
|
||
Shuffle(questions);
|
||
|
||
if (submitButton != null)
|
||
submitButton.onClick.AddListener(OnSubmit);
|
||
if (extraTimeButton != null)
|
||
extraTimeButton.onClick.AddListener(() => timeLeft += 5f);
|
||
if (extraHintButton != null)
|
||
extraHintButton.onClick.AddListener(OnHint);
|
||
if (extraSkipButton != null)
|
||
extraSkipButton.onClick.AddListener(NextQuestion);
|
||
|
||
if (backButton != null)
|
||
{
|
||
backButton.onClick.RemoveAllListeners();
|
||
backButton.onClick.AddListener(() => SceneManager.LoadScene(backSceneName));
|
||
}
|
||
|
||
if (scoreText != null)
|
||
scoreText.text = "0";
|
||
if (comboText != null)
|
||
comboText.text = "0x";
|
||
|
||
NextQuestion();
|
||
}
|
||
|
||
// ================================================================
|
||
void CacheButtonData()
|
||
{
|
||
if (answerButtons == null) return;
|
||
|
||
int len = answerButtons.Length;
|
||
originalButtonScales = new Vector3[len];
|
||
originalButtonPositions = new Vector3[len];
|
||
buttonScaleCoroutines = new Coroutine[len];
|
||
buttonEnterCoroutines = new Coroutine[len];
|
||
|
||
for (int i = 0; i < len; i++)
|
||
{
|
||
if (answerButtons[i] == null) continue;
|
||
|
||
originalButtonScales[i] = answerButtons[i].transform.localScale;
|
||
originalButtonPositions[i] = answerButtons[i].transform.localPosition;
|
||
|
||
answerButtons[i].transition = Selectable.Transition.None;
|
||
}
|
||
}
|
||
|
||
void PrepareFeedbackText()
|
||
{
|
||
if (feedbackText == null) return;
|
||
|
||
if (feedbackOnTop)
|
||
{
|
||
Vector3 pos = feedbackText.transform.localPosition;
|
||
pos.y = feedbackTopY;
|
||
feedbackText.transform.localPosition = pos;
|
||
}
|
||
|
||
feedbackText.alignment = TextAlignmentOptions.Center;
|
||
feedbackText.fontSize = Mathf.Max(feedbackText.fontSize, feedbackFontSize);
|
||
feedbackText.text = "";
|
||
|
||
Color c = feedbackText.color;
|
||
c.a = 1f;
|
||
feedbackText.color = c;
|
||
}
|
||
|
||
// ================================================================
|
||
// 6-LANGUAGE BLOCK TXT READER
|
||
// Each question: 6 lines (TR, EN, ES, DE, FR, PT)
|
||
// Line format: A,B,C,COR,W1,W2,W3
|
||
// ================================================================
|
||
void LoadTXT6Lang(string raw)
|
||
{
|
||
string[] lines = raw.Split('\n');
|
||
|
||
for (int i = 0; i < lines.Length;)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(lines[i]))
|
||
{
|
||
i++;
|
||
continue;
|
||
}
|
||
|
||
if (i + 5 >= lines.Length)
|
||
break;
|
||
|
||
AnalogyQ q = new AnalogyQ();
|
||
bool validBlock = true;
|
||
|
||
for (int L = 0; L < 6; L++)
|
||
{
|
||
string line = lines[i + L].Trim('\r', '\n', ' ');
|
||
if (string.IsNullOrEmpty(line))
|
||
{
|
||
validBlock = false;
|
||
break;
|
||
}
|
||
|
||
string[] p = line.Split(',');
|
||
if (p.Length != 7)
|
||
{
|
||
Debug.LogWarning($"AnalogyLogicGameScene: line {i + L} does not contain 7 parts, block skipped.");
|
||
validBlock = false;
|
||
break;
|
||
}
|
||
|
||
for (int k = 0; k < 7; k++)
|
||
q.data[L, k] = p[k].Trim();
|
||
}
|
||
|
||
if (validBlock)
|
||
questions.Add(q);
|
||
|
||
i += 6;
|
||
}
|
||
}
|
||
|
||
// ================================================================
|
||
void Update()
|
||
{
|
||
if (!locked)
|
||
{
|
||
timeLeft -= Time.deltaTime;
|
||
if (timeLeft <= 0f)
|
||
{
|
||
timeLeft = 0f;
|
||
GameOver();
|
||
}
|
||
}
|
||
|
||
UpdateTimerUI();
|
||
|
||
if (locked && nextTimer > 0f)
|
||
{
|
||
nextTimer -= Time.deltaTime;
|
||
if (nextTimer <= 0f)
|
||
NextQuestion();
|
||
}
|
||
}
|
||
|
||
// ================================================================
|
||
void UpdateTimerUI()
|
||
{
|
||
if (timerText == null) return;
|
||
|
||
timerText.text = Mathf.Ceil(timeLeft).ToString();
|
||
|
||
if (timeLeft <= 10f)
|
||
{
|
||
timerText.color = FullAlpha(Color.Lerp(timerWarnColor, Color.white, Mathf.PingPong(Time.time * 3f, 1f)));
|
||
timerText.transform.localScale = Vector3.one * (1f + Mathf.Sin(Time.time * 10f) * 0.05f);
|
||
}
|
||
else
|
||
{
|
||
timerText.color = FullAlpha(timerNormalColor);
|
||
timerText.transform.localScale = Vector3.one;
|
||
}
|
||
}
|
||
|
||
// ================================================================
|
||
void NextQuestion()
|
||
{
|
||
locked = false;
|
||
selectedIndex = -1;
|
||
nextTimer = 0f;
|
||
|
||
if (selectedWordsText != null)
|
||
selectedWordsText.text = "";
|
||
if (feedbackText != null)
|
||
feedbackText.text = "";
|
||
|
||
for (int i = 0; i < answerButtons.Length; i++)
|
||
{
|
||
if (answerButtons[i] == null) continue;
|
||
|
||
StopButtonCoroutines(i);
|
||
|
||
answerButtons[i].interactable = true;
|
||
answerButtons[i].transform.localScale = originalButtonScales[i];
|
||
answerButtons[i].transform.localPosition = originalButtonPositions[i];
|
||
|
||
if (answerButtons[i].image != null)
|
||
answerButtons[i].image.color = FullAlpha(normalColor);
|
||
}
|
||
|
||
if (questions.Count == 0)
|
||
{
|
||
GameOver();
|
||
return;
|
||
}
|
||
|
||
int id = Random.Range(0, questions.Count);
|
||
if (id == lastQ && questions.Count > 1)
|
||
id = (id + 1) % questions.Count;
|
||
|
||
lastQ = id;
|
||
AnalogyQ q = questions[id];
|
||
|
||
string A = q.data[langIndex, 0];
|
||
string B = q.data[langIndex, 1];
|
||
string C = q.data[langIndex, 2];
|
||
string COR = q.data[langIndex, 3];
|
||
string W1 = q.data[langIndex, 4];
|
||
string W2 = q.data[langIndex, 5];
|
||
string W3 = q.data[langIndex, 6];
|
||
|
||
if (questionText != null)
|
||
{
|
||
questionText.text = $"{A} : {B} = {C} : ?";
|
||
StartCoroutine(FadeInText(questionText));
|
||
}
|
||
|
||
List<string> opts = new List<string> { COR, W1, W2, W3 };
|
||
Shuffle(opts);
|
||
|
||
correctIndex = opts.IndexOf(COR);
|
||
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
if (answerTexts[i] != null)
|
||
answerTexts[i].text = opts[i];
|
||
|
||
int x = i;
|
||
if (answerButtons[i] != null)
|
||
{
|
||
answerButtons[i].onClick.RemoveAllListeners();
|
||
answerButtons[i].onClick.AddListener(() => OnSelect(x));
|
||
|
||
buttonEnterCoroutines[i] = StartCoroutine(ButtonEnterAnim(answerButtons[i], i));
|
||
}
|
||
}
|
||
}
|
||
|
||
// ================================================================
|
||
void OnSelect(int id)
|
||
{
|
||
if (locked) return;
|
||
if (selectedIndex == id) return;
|
||
|
||
if (selectedIndex >= 0 && selectedIndex < answerButtons.Length && answerButtons[selectedIndex] != null)
|
||
{
|
||
if (answerButtons[selectedIndex].image != null)
|
||
answerButtons[selectedIndex].image.color = FullAlpha(normalColor);
|
||
|
||
StartScaleAnim(selectedIndex, originalButtonScales[selectedIndex]);
|
||
}
|
||
|
||
selectedIndex = id;
|
||
|
||
if (answerButtons[id] != null)
|
||
{
|
||
if (answerButtons[id].image != null)
|
||
answerButtons[id].image.color = FullAlpha(selectedColor);
|
||
|
||
StartScaleAnim(id, originalButtonScales[id] * selectedScale);
|
||
}
|
||
|
||
if (selectedWordsText != null && answerTexts[id] != null)
|
||
selectedWordsText.text = answerTexts[id].text;
|
||
}
|
||
|
||
// ================================================================
|
||
void OnSubmit()
|
||
{
|
||
if (locked) return;
|
||
if (selectedIndex == -1) return;
|
||
|
||
locked = true;
|
||
|
||
bool ok = (selectedIndex == correctIndex);
|
||
|
||
foreach (var b in answerButtons)
|
||
if (b != null) b.interactable = false;
|
||
|
||
if (ok)
|
||
{
|
||
correctCount++;
|
||
combo++;
|
||
score += 50 + combo * 10;
|
||
timeLeft += 2f;
|
||
|
||
if (answerButtons[selectedIndex] != null && answerButtons[selectedIndex].image != null)
|
||
answerButtons[selectedIndex].image.color = FullAlpha(correctColor);
|
||
|
||
StartCoroutine(CorrectPulse(answerButtons[selectedIndex], selectedIndex));
|
||
|
||
SetFeedback(combo >= 3 ? $"{Local("correct")} {combo}x COMBO!" : Local("correct"), correctColor);
|
||
|
||
if (comboText != null) StartCoroutine(ComboAnim(comboText));
|
||
}
|
||
else
|
||
{
|
||
wrongCount++;
|
||
combo = 0;
|
||
score -= 20;
|
||
if (score < 0) score = 0;
|
||
|
||
if (answerButtons[selectedIndex] != null && answerButtons[selectedIndex].image != null)
|
||
answerButtons[selectedIndex].image.color = FullAlpha(wrongColor);
|
||
|
||
StartCoroutine(ShakeButton(answerButtons[selectedIndex], selectedIndex));
|
||
|
||
if (correctIndex >= 0 && correctIndex < answerButtons.Length &&
|
||
answerButtons[correctIndex] != null && answerButtons[correctIndex].image != null)
|
||
{
|
||
answerButtons[correctIndex].image.color = FullAlpha(correctColor);
|
||
StartCoroutine(CorrectPulse(answerButtons[correctIndex], correctIndex));
|
||
}
|
||
|
||
SetFeedback(Local("wrong"), wrongColor);
|
||
}
|
||
|
||
if (scoreText != null)
|
||
{
|
||
scoreText.text = score.ToString();
|
||
StartCoroutine(ScorePopAnim(scoreText));
|
||
}
|
||
|
||
if (comboText != null)
|
||
comboText.text = combo + "x";
|
||
|
||
nextTimer = 1f;
|
||
}
|
||
|
||
// ================================================================
|
||
void OnHint()
|
||
{
|
||
if (locked) return;
|
||
if (lastQ < 0 || lastQ >= questions.Count) return;
|
||
|
||
string hint = questions[lastQ].data[langIndex, 3]; // correct answer
|
||
|
||
if (!string.IsNullOrEmpty(hint))
|
||
hint = hint.Length > 1 ? hint[0] + "..." : hint;
|
||
|
||
SetFeedback("Hint: " + hint, selectedColor);
|
||
}
|
||
|
||
// ================================================================
|
||
void SetFeedback(string msg, Color c)
|
||
{
|
||
if (feedbackText == null) return;
|
||
|
||
feedbackText.text = msg;
|
||
feedbackText.color = FullAlpha(c);
|
||
|
||
if (feedbackOnTop)
|
||
{
|
||
Vector3 pos = feedbackText.transform.localPosition;
|
||
pos.y = feedbackTopY;
|
||
feedbackText.transform.localPosition = pos;
|
||
}
|
||
|
||
if (feedbackCo != null) StopCoroutine(feedbackCo);
|
||
feedbackCo = StartCoroutine(FeedbackAnim(feedbackText));
|
||
}
|
||
|
||
// ================================================================
|
||
void GameOver()
|
||
{
|
||
// 🔥 Simple key that the Mod Select / Leaderboard screen can bind to directly
|
||
PlayerPrefs.SetInt("Mod11Skor", score);
|
||
|
||
PlayerPrefs.SetString("LastPlayedMod", modKey);
|
||
PlayerPrefs.SetInt(modKey + "_LastScore", score);
|
||
|
||
int best = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
|
||
if (score > best)
|
||
PlayerPrefs.SetInt(modKey + "_MaxScore", score);
|
||
|
||
PlayerPrefs.SetInt(modKey + "_Correct", correctCount);
|
||
PlayerPrefs.SetInt(modKey + "_Wrong", wrongCount);
|
||
|
||
PlayerPrefs.Save();
|
||
|
||
SceneManager.LoadScene("Mod11Resume");
|
||
}
|
||
|
||
// ================================================================
|
||
int GetLangIndex()
|
||
{
|
||
return langCode switch
|
||
{
|
||
"tr" => 1,
|
||
"en" => 0,
|
||
"es" => 2,
|
||
"de" => 3,
|
||
"fr" => 4,
|
||
"pt" => 5,
|
||
_ => 1 // default EN
|
||
};
|
||
}
|
||
|
||
// ================================================================
|
||
string Local(string key)
|
||
{
|
||
int L = GetLangIndex(); // Same as QuestionLangCode
|
||
|
||
switch (key)
|
||
{
|
||
case "correct":
|
||
return new[]
|
||
{
|
||
"Correct!", "Correct!", "Correct!", "Correct!", "Correct!", "Correct!"
|
||
}[L];
|
||
|
||
case "wrong":
|
||
return new[]
|
||
{
|
||
"Wrong!", "Wrong!", "Wrong!", "Wrong!", "Wrong!", "Wrong!"
|
||
}[L];
|
||
}
|
||
|
||
return key;
|
||
}
|
||
|
||
// ================================================================
|
||
void Shuffle<T>(IList<T> arr)
|
||
{
|
||
for (int i = 0; i < arr.Count; i++)
|
||
{
|
||
int r = Random.Range(i, arr.Count);
|
||
(arr[i], arr[r]) = (arr[r], arr[i]);
|
||
}
|
||
}
|
||
|
||
// ================== ANIMATION HELPERS ==================
|
||
|
||
void StartScaleAnim(int index, Vector3 targetScale)
|
||
{
|
||
if (index < 0 || index >= answerButtons.Length) return;
|
||
if (answerButtons[index] == null) return;
|
||
|
||
if (buttonScaleCoroutines[index] != null)
|
||
StopCoroutine(buttonScaleCoroutines[index]);
|
||
|
||
buttonScaleCoroutines[index] = StartCoroutine(ScaleButton(answerButtons[index], targetScale));
|
||
}
|
||
|
||
void StopButtonCoroutines(int index)
|
||
{
|
||
if (buttonScaleCoroutines != null && index < buttonScaleCoroutines.Length && buttonScaleCoroutines[index] != null)
|
||
{
|
||
StopCoroutine(buttonScaleCoroutines[index]);
|
||
buttonScaleCoroutines[index] = null;
|
||
}
|
||
|
||
if (buttonEnterCoroutines != null && index < buttonEnterCoroutines.Length && buttonEnterCoroutines[index] != null)
|
||
{
|
||
StopCoroutine(buttonEnterCoroutines[index]);
|
||
buttonEnterCoroutines[index] = null;
|
||
}
|
||
}
|
||
|
||
IEnumerator ScaleButton(Button btn, Vector3 targetScale)
|
||
{
|
||
if (btn == null) yield break;
|
||
|
||
Vector3 startScale = btn.transform.localScale;
|
||
float t = 0f;
|
||
|
||
while (t < 1f)
|
||
{
|
||
t += Time.deltaTime / Mathf.Max(0.01f, selectAnimTime);
|
||
btn.transform.localScale = Vector3.Lerp(startScale, targetScale, EaseOutQuad(t));
|
||
yield return null;
|
||
}
|
||
|
||
btn.transform.localScale = targetScale;
|
||
}
|
||
|
||
IEnumerator ButtonEnterAnim(Button btn, int delayIndex)
|
||
{
|
||
if (btn == null) yield break;
|
||
|
||
int idx = System.Array.IndexOf(answerButtons, btn);
|
||
if (idx < 0) yield break;
|
||
|
||
yield return new WaitForSeconds(delayIndex * 0.06f);
|
||
|
||
Vector3 targetPos = originalButtonPositions[idx];
|
||
Vector3 startPos = targetPos + Vector3.up * 35f;
|
||
|
||
Vector3 targetScale = originalButtonScales[idx];
|
||
Vector3 startScale = targetScale * 0.85f;
|
||
|
||
btn.transform.localPosition = startPos;
|
||
btn.transform.localScale = startScale;
|
||
|
||
float t = 0f;
|
||
|
||
while (t < 1f)
|
||
{
|
||
t += Time.deltaTime / Mathf.Max(0.01f, enterAnimTime);
|
||
|
||
float ease = EaseOutBack(t);
|
||
|
||
btn.transform.localPosition = Vector3.Lerp(startPos, targetPos, ease);
|
||
btn.transform.localScale = Vector3.Lerp(startScale, targetScale, ease);
|
||
|
||
yield return null;
|
||
}
|
||
|
||
btn.transform.localPosition = targetPos;
|
||
btn.transform.localScale = targetScale;
|
||
}
|
||
|
||
IEnumerator CorrectPulse(Button btn, int idx)
|
||
{
|
||
if (btn == null) yield break;
|
||
if (idx < 0 || idx >= originalButtonScales.Length) yield break;
|
||
|
||
Vector3 normal = originalButtonScales[idx];
|
||
Vector3 big = normal * 1.12f;
|
||
|
||
float t = 0f;
|
||
|
||
while (t < 1f)
|
||
{
|
||
t += Time.deltaTime / 0.12f;
|
||
btn.transform.localScale = Vector3.Lerp(normal, big, EaseOutQuad(t));
|
||
yield return null;
|
||
}
|
||
|
||
t = 0f;
|
||
|
||
while (t < 1f)
|
||
{
|
||
t += Time.deltaTime / 0.12f;
|
||
btn.transform.localScale = Vector3.Lerp(big, normal, EaseOutQuad(t));
|
||
yield return null;
|
||
}
|
||
|
||
btn.transform.localScale = normal;
|
||
}
|
||
|
||
IEnumerator ShakeButton(Button btn, int idx)
|
||
{
|
||
if (btn == null) yield break;
|
||
if (idx < 0 || idx >= originalButtonPositions.Length) yield break;
|
||
|
||
Vector3 origin = originalButtonPositions[idx];
|
||
|
||
float duration = 0.35f;
|
||
float magnitude = 12f;
|
||
float elapsed = 0f;
|
||
|
||
while (elapsed < duration)
|
||
{
|
||
float power = 1f - elapsed / duration;
|
||
float x = Random.Range(-1f, 1f) * magnitude * power;
|
||
|
||
btn.transform.localPosition = origin + new Vector3(x, 0f, 0f);
|
||
|
||
elapsed += Time.deltaTime;
|
||
yield return null;
|
||
}
|
||
|
||
btn.transform.localPosition = origin;
|
||
}
|
||
|
||
IEnumerator FeedbackAnim(TMP_Text txt)
|
||
{
|
||
if (txt == null) yield break;
|
||
|
||
Vector3 originalScale = Vector3.one;
|
||
Vector3 bigScale = originalScale * 1.18f;
|
||
|
||
Color c = FullAlpha(txt.color);
|
||
c.a = 0f;
|
||
txt.color = c;
|
||
|
||
Vector3 originalPos = txt.transform.localPosition;
|
||
Vector3 startPos = originalPos + Vector3.down * 18f;
|
||
|
||
txt.transform.localPosition = startPos;
|
||
|
||
float t = 0f;
|
||
|
||
while (t < 1f)
|
||
{
|
||
t += Time.deltaTime / 0.16f;
|
||
|
||
float ease = EaseOutBack(t);
|
||
|
||
txt.transform.localScale = Vector3.Lerp(originalScale, bigScale, ease);
|
||
txt.transform.localPosition = Vector3.Lerp(startPos, originalPos, ease);
|
||
|
||
c.a = Mathf.Clamp01(t);
|
||
txt.color = c;
|
||
|
||
yield return null;
|
||
}
|
||
|
||
c.a = 1f;
|
||
txt.color = c;
|
||
txt.transform.localPosition = originalPos;
|
||
|
||
t = 0f;
|
||
|
||
while (t < 1f)
|
||
{
|
||
t += Time.deltaTime / 0.12f;
|
||
txt.transform.localScale = Vector3.Lerp(bigScale, originalScale, EaseOutQuad(t));
|
||
yield return null;
|
||
}
|
||
|
||
txt.transform.localScale = originalScale;
|
||
feedbackCo = null;
|
||
}
|
||
|
||
IEnumerator ComboAnim(TMP_Text txt)
|
||
{
|
||
if (txt == null) yield break;
|
||
|
||
Vector3 original = Vector3.one;
|
||
Vector3 big = original * 1.22f;
|
||
|
||
Color baseColor = FullAlpha(txt.color);
|
||
Color highlight = new Color32(255, 220, 50, 255);
|
||
|
||
float t = 0f;
|
||
|
||
while (t < 1f)
|
||
{
|
||
t += Time.deltaTime / 0.12f;
|
||
|
||
txt.transform.localScale = Vector3.Lerp(original, big, EaseOutBack(t));
|
||
txt.color = FullAlpha(Color.Lerp(baseColor, highlight, t));
|
||
|
||
yield return null;
|
||
}
|
||
|
||
t = 0f;
|
||
|
||
while (t < 1f)
|
||
{
|
||
t += Time.deltaTime / 0.14f;
|
||
|
||
txt.transform.localScale = Vector3.Lerp(big, original, EaseOutQuad(t));
|
||
txt.color = FullAlpha(Color.Lerp(highlight, baseColor, t));
|
||
|
||
yield return null;
|
||
}
|
||
|
||
txt.transform.localScale = original;
|
||
txt.color = baseColor;
|
||
}
|
||
|
||
IEnumerator ScorePopAnim(TMP_Text txt)
|
||
{
|
||
if (txt == null) yield break;
|
||
|
||
Vector3 original = Vector3.one;
|
||
Vector3 big = original * 1.18f;
|
||
|
||
float t = 0f;
|
||
|
||
while (t < 1f)
|
||
{
|
||
t += Time.deltaTime / 0.10f;
|
||
txt.transform.localScale = Vector3.Lerp(original, big, EaseOutQuad(t));
|
||
yield return null;
|
||
}
|
||
|
||
t = 0f;
|
||
|
||
while (t < 1f)
|
||
{
|
||
t += Time.deltaTime / 0.12f;
|
||
txt.transform.localScale = Vector3.Lerp(big, original, EaseOutQuad(t));
|
||
yield return null;
|
||
}
|
||
|
||
txt.transform.localScale = original;
|
||
}
|
||
|
||
IEnumerator FadeInText(TMP_Text txt)
|
||
{
|
||
if (txt == null) yield break;
|
||
|
||
Color c = FullAlpha(txt.color);
|
||
c.a = 0f;
|
||
txt.color = c;
|
||
|
||
float t = 0f;
|
||
|
||
while (t < 1f)
|
||
{
|
||
t += Time.deltaTime / 0.18f;
|
||
c.a = EaseOutQuad(t);
|
||
txt.color = c;
|
||
yield return null;
|
||
}
|
||
|
||
c.a = 1f;
|
||
txt.color = c;
|
||
}
|
||
|
||
Color FullAlpha(Color c)
|
||
{
|
||
c.a = 1f;
|
||
return c;
|
||
}
|
||
|
||
float EaseOutBack(float t)
|
||
{
|
||
t = Mathf.Clamp01(t);
|
||
|
||
float c1 = 1.70158f;
|
||
float c3 = c1 + 1f;
|
||
|
||
return 1f + c3 * Mathf.Pow(t - 1f, 3f) + c1 * Mathf.Pow(t - 1f, 2f);
|
||
}
|
||
|
||
float EaseOutQuad(float t)
|
||
{
|
||
t = Mathf.Clamp01(t);
|
||
return 1f - (1f - t) * (1f - t);
|
||
}
|
||
} |