Initial commit: Star of Words Unity project

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>
This commit is contained in:
portakal 2026-07-05 15:31:20 +03:00
commit ecb1c9edea
1455 changed files with 933295 additions and 0 deletions

View file

@ -0,0 +1,177 @@
using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class Mod6Resume : MonoBehaviour
{
[Header("UI TEXTS")]
public TMP_Text scoreText; // Toplam skor
public TMP_Text maxScoreText; // En yüksek skor
public TMP_Text correctText; // Doğru sayısı
public TMP_Text wrongText; // Yanlış sayısı
[Header("BUTTONS")]
public Button retryButton;
public Button exitButton;
[Header("AUDIO")]
public AudioSource sfx;
public AudioClip clickSound;
[Header("━━━ ANIMATION SETTINGS ━━━━━━━━━━━━━━━━━")]
public float countUpDuration = 0.8f;
public float popInDelay = 0.08f;
public float popInTime = 0.3f;
// Mod6 PlayerPrefs Key
private string modKey = "Mod6";
private int score;
private int maxScore;
private int correct;
private int wrong;
// ============================================================
void Start()
{
LoadResults();
PrepareTexts();
// Retry
if (retryButton != null)
retryButton.onClick.AddListener(() =>
{
PlaySFX();
Retry();
});
// Exit
if (exitButton != null)
exitButton.onClick.AddListener(() =>
{
PlaySFX();
ExitToMenu();
});
StartCoroutine(PlayRevealSequence());
}
// ============================================================
void LoadResults()
{
score = PlayerPrefs.GetInt(modKey + "_LastScore", 0);
maxScore = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
correct = PlayerPrefs.GetInt(modKey + "_Correct", 0);
wrong = PlayerPrefs.GetInt(modKey + "_Wrong", 0);
Debug.Log($"[MOD6 RESULT] Score={score} | Max={maxScore} | Correct={correct} | Wrong={wrong}");
}
// ============================================================
void PrepareTexts()
{
SetTextZero(scoreText);
SetTextZero(maxScoreText);
SetTextZero(correctText);
SetTextZero(wrongText);
}
void SetTextZero(TMP_Text txt)
{
if (txt == null) return;
txt.text = "0";
txt.transform.localScale = Vector3.zero;
}
// ============================================================
IEnumerator PlayRevealSequence()
{
yield return StartCoroutine(RevealStat(scoreText, score));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(maxScoreText, maxScore));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(correctText, correct));
yield return new WaitForSeconds(popInDelay);
yield return StartCoroutine(RevealStat(wrongText, wrong));
}
IEnumerator RevealStat(TMP_Text txt, int targetValue)
{
if (txt == null) yield break;
// pop-in scale
Vector3 normal = Vector3.one;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.01f, popInTime);
txt.transform.localScale = Vector3.Lerp(Vector3.zero, normal, EaseOutBack(t));
if (targetValue == 0)
txt.text = "0";
yield return null;
}
txt.transform.localScale = normal;
// count-up
if (targetValue > 0)
{
float ct = 0f;
while (ct < 1f)
{
ct += Time.deltaTime / Mathf.Max(0.01f, countUpDuration);
int shown = Mathf.RoundToInt(Mathf.Lerp(0, targetValue, EaseOutQuad(ct)));
txt.text = shown.ToString();
yield return null;
}
}
txt.text = targetValue.ToString();
}
// ============================================================
void PlaySFX()
{
if (sfx && clickSound)
sfx.PlayOneShot(clickSound);
}
// ============================================================
void Retry()
{
SceneManager.LoadScene("Mod6");
}
// ============================================================
void ExitToMenu()
{
SceneManager.LoadScene("Anamen");
}
// ============================================================
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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7732f4a1c046d054cadae9b2b5482c31

View file

@ -0,0 +1,897 @@
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.SceneManagement;
public class WordMatchMod : MonoBehaviour
{
[Header("UI - QUESTIONS (LEFT)")]
[SerializeField] private Button[] questionButtons;
[SerializeField] private TMP_Text[] questionTexts;
[Header("UI - ANSWERS (RIGHT)")]
[SerializeField] private Button[] answerButtons;
[SerializeField] private TMP_Text[] answerTexts;
[Header("UI - OTHER")]
[SerializeField] private Button submitButton;
[SerializeField] private TMP_Text scoreText;
[SerializeField] private TMP_Text comboText;
[SerializeField] private TMP_Text timeText;
[SerializeField] private TMP_Text feedbackText;
[Header("━━━ BACK BUTTON ━━━━━━━━━━━━━━━━━━━━━━━━")]
public Button backButton;
public string backSceneName = "ModSec 6";
[Header("WORD DATA")]
[SerializeField] private TextAsset wordFile;
[Header("COLORS")]
public Color baseColor = new Color32(230, 230, 230, 255);
public Color[] pairColors = new Color[]
{
new Color32(120,180,255,255),
new Color32(255,200,120,255),
new Color32(160,255,160,255),
new Color32(255,150,150,255),
new Color32(210,150,255,255),
};
public Color correctColor = new Color32(0, 160, 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;
Dictionary<string, string> activeMap = new Dictionary<string, string>();
List<KeyValuePair<string, string>> selectedPairs = new List<KeyValuePair<string, string>>();
private int[] questionToAnswer = new int[5];
private int[] questionColorIdx = new int[5];
private int[] answerColorIdx = new int[5];
private int selectedQuestion = -1;
// 🔥 90 saniyelik toplam süre, round başına sıfırlanmıyor
private float timeLeft = 90f;
private int score = 0;
private int combo = 0;
private int correctCount = 0;
private int wrongCount = 0;
// Durum kontrolü
private bool isTimeUp = false; // süre tamamen bitti mi?
private bool isRoundProcessing = false; // bu round için submit işlemi devam ediyor mu?
// PlayerPrefs Key
private string modKey = "Mod6";
private string qLang;
private string aLang;
readonly Color timerNormalColor = Color.white;
readonly Color timerWarnColor = new Color32(255, 80, 80, 255);
Vector3[] questionOriginalScales;
Vector3[] answerOriginalScales;
Vector3[] questionOriginalPositions;
Vector3[] answerOriginalPositions;
Coroutine[] questionScaleCo;
Coroutine[] answerScaleCo;
Coroutine[] questionEnterCo;
Coroutine[] answerEnterCo;
Coroutine feedbackCo;
//---------------------------------------------------------
void Start()
{
qLang = PlayerPrefs.GetString("QuestionLangCode", "en");
aLang = PlayerPrefs.GetString("AnswerLangCode", "tr");
LoadWordFile();
CacheButtonData();
PrepareFeedbackText();
if (submitButton != null)
{
submitButton.onClick.RemoveAllListeners();
submitButton.onClick.AddListener(OnSubmit);
}
if (backButton != null)
{
backButton.onClick.RemoveAllListeners();
backButton.onClick.AddListener(() => SceneManager.LoadScene(backSceneName));
}
LoadRound();
ResetColorMaps();
// Oyun başlangıcı süresi
timeLeft = 90f;
isTimeUp = false;
isRoundProcessing = false;
scoreText.text = score.ToString();
comboText.text = combo + "x";
}
//---------------------------------------------------------
void Update()
{
if (isTimeUp) // süre bittiyse artık hiçbir şey yapma
{
UpdateTimerUI();
return;
}
timeLeft -= Time.deltaTime;
if (timeLeft < 0f) timeLeft = 0f;
UpdateTimerUI();
if (!isTimeUp && timeLeft <= 0f)
{
// Süre ilk kez bitti
isTimeUp = true;
ProcessSubmit(true); // timeout'tan gelen submit
StartCoroutine(GoResume()); // sonuç sahnesine git
}
}
//---------------------------------------------------------
void UpdateTimerUI()
{
if (timeText == null) return;
timeText.text = Mathf.CeilToInt(timeLeft).ToString();
if (timeLeft <= 10f)
{
timeText.color = FullAlpha(Color.Lerp(timerWarnColor, Color.white, Mathf.PingPong(Time.time * 3f, 1f)));
timeText.transform.localScale = Vector3.one * (1f + Mathf.Sin(Time.time * 10f) * 0.05f);
}
else
{
timeText.color = FullAlpha(timerNormalColor);
timeText.transform.localScale = Vector3.one;
}
}
//---------------------------------------------------------
void LoadWordFile()
{
activeMap.Clear();
string[] lines = wordFile.text.Split('\n');
int qi = LangIndex(qLang);
int ai = LangIndex(aLang);
foreach (string raw in lines)
{
string line = raw.Trim();
if (string.IsNullOrWhiteSpace(line)) continue;
if (!line.Contains(",")) continue;
string[] p = line.Split(',');
if (p.Length < 6) continue;
string q = p[qi].Trim();
string a = p[ai].Trim();
if (!activeMap.ContainsKey(q))
activeMap.Add(q, a);
}
}
int LangIndex(string c)
{
switch (c)
{
case "tr": return 0;
case "en": return 1;
case "es": return 2;
case "de": return 3;
case "fr": return 4;
case "pt": return 5;
}
return 1;
}
//---------------------------------------------------------
void CacheButtonData()
{
int n = questionButtons.Length;
questionOriginalScales = new Vector3[n];
answerOriginalScales = new Vector3[n];
questionOriginalPositions = new Vector3[n];
answerOriginalPositions = new Vector3[n];
questionScaleCo = new Coroutine[n];
answerScaleCo = new Coroutine[n];
questionEnterCo = new Coroutine[n];
answerEnterCo = new Coroutine[n];
for (int i = 0; i < n; i++)
{
if (questionButtons[i] != null)
{
questionOriginalScales[i] = questionButtons[i].transform.localScale;
questionOriginalPositions[i] = questionButtons[i].transform.localPosition;
questionButtons[i].transition = Selectable.Transition.None;
}
if (answerButtons[i] != null)
{
answerOriginalScales[i] = answerButtons[i].transform.localScale;
answerOriginalPositions[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;
}
//---------------------------------------------------------
void LoadRound()
{
ResetVisuals();
ResetColorMaps();
isRoundProcessing = false; // yeni round için submit tekrar aktif
var all = activeMap.ToList();
Shuffle(all);
selectedPairs = all.Take(5).ToList();
// Questions
for (int i = 0; i < 5; i++)
{
questionTexts[i].text = selectedPairs[i].Key;
int id = i;
questionButtons[i].onClick.RemoveAllListeners();
questionButtons[i].onClick.AddListener(() => SelectQuestion(id));
}
// Answers
List<string> answers = selectedPairs.Select(x => x.Value).ToList();
Shuffle(answers);
for (int i = 0; i < 5; i++)
{
answerTexts[i].text = answers[i];
int id = i;
answerButtons[i].onClick.RemoveAllListeners();
answerButtons[i].onClick.AddListener(() => SelectAnswer(id));
}
// Enter animasyonları
for (int i = 0; i < 5; i++)
{
if (questionEnterCo[i] != null) StopCoroutine(questionEnterCo[i]);
questionEnterCo[i] = StartCoroutine(ButtonEnterAnim(questionButtons[i], questionOriginalScales[i], questionOriginalPositions[i], i, -1));
if (answerEnterCo[i] != null) StopCoroutine(answerEnterCo[i]);
answerEnterCo[i] = StartCoroutine(ButtonEnterAnim(answerButtons[i], answerOriginalScales[i], answerOriginalPositions[i], i, 1));
if (questionTexts[i] != null) StartCoroutine(FadeInText(questionTexts[i]));
if (answerTexts[i] != null) StartCoroutine(FadeInText(answerTexts[i]));
}
}
//---------------------------------------------------------
void ResetVisuals()
{
for (int i = 0; i < 5; i++)
{
StopButtonAnims(i);
questionButtons[i].image.color = FullAlpha(baseColor);
answerButtons[i].image.color = FullAlpha(baseColor);
questionButtons[i].transform.localScale = questionOriginalScales[i];
answerButtons[i].transform.localScale = answerOriginalScales[i];
questionButtons[i].transform.localPosition = questionOriginalPositions[i];
answerButtons[i].transform.localPosition = answerOriginalPositions[i];
}
feedbackText.text = "";
}
void StopButtonAnims(int i)
{
if (questionScaleCo[i] != null) { StopCoroutine(questionScaleCo[i]); questionScaleCo[i] = null; }
if (answerScaleCo[i] != null) { StopCoroutine(answerScaleCo[i]); answerScaleCo[i] = null; }
if (questionEnterCo[i] != null) { StopCoroutine(questionEnterCo[i]); questionEnterCo[i] = null; }
if (answerEnterCo[i] != null) { StopCoroutine(answerEnterCo[i]); answerEnterCo[i] = null; }
}
void ResetColorMaps()
{
for (int i = 0; i < 5; i++)
{
questionToAnswer[i] = -1;
questionColorIdx[i] = -1;
answerColorIdx[i] = -1;
}
}
//---------------------------------------------------------
void SelectQuestion(int q)
{
if (isRoundProcessing || isTimeUp) return;
selectedQuestion = q;
StartScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, q, questionOriginalScales[q] * selectedScale);
}
//---------------------------------------------------------
void SelectAnswer(int a)
{
if (isRoundProcessing || isTimeUp) return;
if (selectedQuestion == -1)
return;
int prevQuestion = selectedQuestion;
// Aynı cevabı tekrar tıklarsa iptal et
if (questionToAnswer[selectedQuestion] == a)
{
questionToAnswer[selectedQuestion] = -1;
questionColorIdx[selectedQuestion] = -1;
answerColorIdx[a] = -1;
RefreshColors();
selectedQuestion = -1;
ResetScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, prevQuestion);
ResetScaleAnim(answerButtons, answerScaleCo, answerOriginalScales, a);
return;
}
// Bu cevap başka bir soruya atanmışsa oradan kaldır
for (int i = 0; i < 5; i++)
{
if (questionToAnswer[i] == a && i != selectedQuestion)
{
questionToAnswer[i] = -1;
questionColorIdx[i] = -1;
ResetScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, i);
}
}
// Önceden seçilmiş cevabı temizle
int oldAns = questionToAnswer[selectedQuestion];
if (oldAns != -1)
{
answerColorIdx[oldAns] = -1;
ResetScaleAnim(answerButtons, answerScaleCo, answerOriginalScales, oldAns);
}
// Yeni eşleşmeyi ata
questionToAnswer[selectedQuestion] = a;
int colorIdx = selectedQuestion;
questionColorIdx[selectedQuestion] = colorIdx;
answerColorIdx[a] = colorIdx;
RefreshColors();
// pair pulse animasyonu
StartCoroutine(PairPulse(prevQuestion, a));
ResetScaleAnim(questionButtons, questionScaleCo, questionOriginalScales, prevQuestion);
selectedQuestion = -1;
}
//---------------------------------------------------------
void RefreshColors()
{
for (int i = 0; i < 5; i++)
{
questionButtons[i].image.color =
questionColorIdx[i] == -1 ? FullAlpha(baseColor) : FullAlpha(pairColors[questionColorIdx[i]]);
answerButtons[i].image.color =
answerColorIdx[i] == -1 ? FullAlpha(baseColor) : FullAlpha(pairColors[answerColorIdx[i]]);
}
}
//---------------------------------------------------------
// Butondan gelen submit
void OnSubmit()
{
// Eğer bu round zaten işleniyorsa veya süre bittiyse tekrar işleme
if (isRoundProcessing || isTimeUp)
return;
ProcessSubmit(false);
}
// Asıl hesaplamayı yapan fonksiyon
void ProcessSubmit(bool fromTimeout)
{
isRoundProcessing = true;
int roundCorrect = 0;
for (int q = 0; q < 5; q++)
{
int a = questionToAnswer[q];
if (a == -1)
{
questionButtons[q].image.color = FullAlpha(wrongColor);
StartCoroutine(ShakeButton(questionButtons[q], questionOriginalPositions[q]));
wrongCount++;
continue;
}
string qWord = questionTexts[q].text;
string correctA = activeMap[qWord];
string chosen = answerTexts[a].text;
if (chosen == correctA)
{
roundCorrect++;
correctCount++;
questionButtons[q].image.color = FullAlpha(correctColor);
answerButtons[a].image.color = FullAlpha(correctColor);
StartCoroutine(CorrectPulse(questionButtons[q], questionOriginalScales[q]));
StartCoroutine(CorrectPulse(answerButtons[a], answerOriginalScales[a]));
}
else
{
wrongCount++;
questionButtons[q].image.color = FullAlpha(wrongColor);
answerButtons[a].image.color = FullAlpha(wrongColor);
StartCoroutine(ShakeButton(questionButtons[q], questionOriginalPositions[q]));
StartCoroutine(ShakeButton(answerButtons[a], answerOriginalPositions[a]));
}
}
// Her doğru 20 puan
int gainedScore = roundCorrect * 20;
score += gainedScore;
Color feedbackColor;
if (roundCorrect == 5)
{
combo++;
feedbackText.text = combo >= 2 ? $"PERFECT! {combo}x COMBO!" : "PERFECT!";
feedbackColor = correctColor;
}
else if (roundCorrect > 0)
{
combo = 0;
feedbackText.text = "+" + gainedScore + " Puan";
feedbackColor = correctColor;
}
else
{
combo = 0;
feedbackText.text = "Try again!";
feedbackColor = wrongColor;
}
feedbackText.color = FullAlpha(feedbackColor);
if (feedbackOnTop)
{
Vector3 pos = feedbackText.transform.localPosition;
pos.y = feedbackTopY;
feedbackText.transform.localPosition = pos;
}
if (feedbackCo != null) StopCoroutine(feedbackCo);
feedbackCo = StartCoroutine(FeedbackAnim(feedbackText));
scoreText.text = score.ToString();
comboText.text = combo + "x";
if (scoreText != null) StartCoroutine(ScorePopAnim(scoreText));
if (combo > 0 && comboText != null) StartCoroutine(ComboAnim(comboText));
SaveProgress();
// Eğer bu timeout değilse ve oyun tamamen bitmediyse yeni round
if (!fromTimeout && !isTimeUp)
{
StartCoroutine(NextRound());
}
}
//---------------------------------------------------------
void SaveProgress()
{
// 🔥 Mod Select / Leaderboard ekranına direkt bağlanacak basit key
PlayerPrefs.SetInt("Mod6Skor", score);
PlayerPrefs.SetInt(modKey + "_LastScore", score);
int maxScore = PlayerPrefs.GetInt(modKey + "_MaxScore", 0);
if (score > maxScore)
PlayerPrefs.SetInt(modKey + "_MaxScore", score);
PlayerPrefs.SetInt(modKey + "_Correct", correctCount);
PlayerPrefs.SetInt(modKey + "_Wrong", wrongCount);
PlayerPrefs.Save();
}
//---------------------------------------------------------
IEnumerator NextRound()
{
yield return new WaitForSeconds(0.8f);
LoadRound();
}
IEnumerator GoResume()
{
yield return new WaitForSeconds(1f);
SceneManager.LoadScene("Mod6Resume");
}
//---------------------------------------------------------
void Shuffle<T>(List<T> list)
{
for (int i = list.Count - 1; i > 0; i--)
{
int j = Random.Range(0, i + 1);
(list[i], list[j]) = (list[j], list[i]);
}
}
// ================== ANIMATION HELPERS ==================
void StartScaleAnim(Button[] buttons, Coroutine[] coArr, Vector3[] originalScales, int idx, Vector3 targetScale)
{
if (idx < 0 || idx >= buttons.Length || buttons[idx] == null) return;
if (coArr[idx] != null)
StopCoroutine(coArr[idx]);
coArr[idx] = StartCoroutine(ScaleButton(buttons[idx], targetScale, idx, coArr));
}
void ResetScaleAnim(Button[] buttons, Coroutine[] coArr, Vector3[] originalScales, int idx)
{
if (idx < 0 || idx >= buttons.Length || buttons[idx] == null) return;
StartScaleAnim(buttons, coArr, originalScales, idx, originalScales[idx]);
}
IEnumerator ScaleButton(Button btn, Vector3 targetScale, int idx, Coroutine[] coArr)
{
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;
coArr[idx] = null;
}
IEnumerator ButtonEnterAnim(Button btn, Vector3 targetScale, Vector3 targetPos, int delayIndex, int sideSign)
{
if (btn == null) yield break;
yield return new WaitForSeconds(delayIndex * 0.05f);
Vector3 startPos = targetPos + new Vector3(sideSign * 40f, 0f, 0f);
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 PairPulse(int questionIdx, int answerIdx)
{
if (questionIdx >= 0 && questionIdx < questionButtons.Length)
yield return StartCoroutine(QuickPulse(questionButtons[questionIdx].transform, questionOriginalScales[questionIdx]));
if (answerIdx >= 0 && answerIdx < answerButtons.Length)
yield return StartCoroutine(QuickPulse(answerButtons[answerIdx].transform, answerOriginalScales[answerIdx]));
}
IEnumerator QuickPulse(Transform tr, Vector3 normal)
{
if (tr == null) yield break;
Vector3 big = normal * 1.08f;
float t = 0f;
while (t < 1f)
{
t += Time.deltaTime / 0.08f;
tr.localScale = Vector3.Lerp(normal, big, EaseOutQuad(t));
yield return null;
}
t = 0f;
while (t < 1f)
{
t += Time.deltaTime / 0.08f;
tr.localScale = Vector3.Lerp(big, normal, EaseOutQuad(t));
yield return null;
}
tr.localScale = normal;
}
IEnumerator CorrectPulse(Button btn, Vector3 normal)
{
if (btn == null) yield break;
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, Vector3 origin)
{
if (btn == null) yield break;
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 baseC = 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(baseC, 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, baseC, t));
yield return null;
}
txt.transform.localScale = original;
txt.color = baseC;
}
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);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8009dfdd6ea39fb4e8299d3815d05377