using System.Collections; using System.Collections.Generic; using System.Text; using UnityEngine; using PrizeSystem; public class CharacterController : MonoBehaviour { #region PRIVATE_FIELDS [SerializeField] private Transform charactersContainer; [SerializeField] private Transform charactersPool; [SerializeField] private List characterPrefabs; public Character[] characters; [SerializeField] private Vector2 hiddenLocalPosition; [SerializeField] private Vector2 shownLocalPosition; private bool charactersActivated = false; private int currentIndex = 0; [SerializeField] private float speed; public static CharacterController I; #endregion public static int CharactersAmount => I.characters.Length; public static Sprite CurrentChipImage => CurrentCharacter.chipImage; public static Character CurrentCharacter => I.characters[I.currentIndex]; public static Character NextCharacter { get { if (I.currentIndex + 1 < I.characters.Length) { return I.characters[I.currentIndex + 1]; } else return null; } } //================================= start: PUBLIC API =================================// public void SetAllCharactersPrizeAvailable(bool value) { foreach (Character character in I.characters) { character.HasPrize = value; } } public static void ResetCharactersDifficulty() { foreach (Character ch in I.characters) { ch.currentDifficulty = ch.CurrenDifficultyList.Count / 2; //берем средню сложность изначально } } //Задвинуть контейнер за экран public static void HideCharacter() { CurrentCharacter?.UnbindEvents(); I.StopAllCoroutines(); I.StartCoroutine(I.MoveLocal(I.charactersContainer, I.hiddenLocalPosition, I.speed)); } //задвинуть одного, показать другого public static void SwitchToCharacter(int index) { I.StopAllCoroutines(); I.StartCoroutine(I.TransitionToCharacter(index)); } public static void ResetState() { I.StopAllCoroutines(); I.charactersContainer.transform.localPosition = I.hiddenLocalPosition; I.ClearContainer(); I.charactersActivated = false; I.currentIndex = 0; } //Вывести контейнер на экран public static void ShowCharacter() { I.StopAllCoroutines(); I.StartCoroutine(I.MoveLocal(I.charactersContainer, I.shownLocalPosition, I.speed)); } //================================= end : PUBLIC API =================================// private void Awake() => I = this; private void Start() => SetupCharacters(); private void SetupCharacters() { //обрабатвыаем некорректные вводные if (GameManager.instance.botsAmount <= 0) throw new System.Exception("Некорректное количество ботов в менеджере"); if (characterPrefabs.Count <= 0) throw new System.Exception("Не заданы боты в контроллере"); int botsToSpawn = Mathf.Min(GameManager.instance.botsAmount, characterPrefabs.Count); GameManager.instance.botsAmount = botsToSpawn; //characters = new Character[GameManager.instance.botsAmount]; characters = new Character[botsToSpawn]; for (int i = 0; i < characters.Length; i++) { var go = Instantiate(characterPrefabs[i], charactersPool); go.transform.localPosition = hiddenLocalPosition; var ch = go.GetComponent(); ch.Animator.SetTrigger("PreAppear"); characters[i] = ch; } ClearContainer(); RefreshPrizes(); } public void RefreshPrizes() { List prizes = PrizeSerializer.LoadPrizes(); for (int i = 0; i < characters.Length; i++) { characters[i].prize = prizes[i]; } } private void ClearContainer() { for (int i = charactersContainer.childCount - 1; i >= 0; i--) { var child = charactersContainer.transform.GetChild(i); child.SetParent(charactersPool); } } //Замена префаба private void SetCharacter(int index) { ClearContainer(); if (index < 0 || index >= CharactersAmount) index = 0; var newCharacter = characters[index]; //сажаем нового в контейнер newCharacter.transform.SetParent(charactersContainer); newCharacter.transform.localPosition = newCharacter.CharacterLocalPosition; newCharacter.Animator.SetTrigger("PreAppear"); //animator.ResetTrigger("Throw"); newCharacter.BindEvents(); } //Перемещение объекта по локальным координатам private IEnumerator MoveLocal(Transform t, Vector3 targetLocalPos, float speed) { while (t.localPosition != targetLocalPos) { t.localPosition = Vector3.MoveTowards(t.localPosition, targetLocalPos, speed * Time.deltaTime); yield return null; } } //Анимация смены персонажей private IEnumerator TransitionToCharacter(int newIndex) { int oldIndex = currentIndex; currentIndex = newIndex; LightUtility.Character(characters[newIndex]); //Отсекаем попытку переключиться на того же персонажа if (newIndex == oldIndex && charactersActivated) yield break; // тостер отсекается. надо решать charactersActivated = true; //чтобы тостер тоже приходил иначе старт 0, запрашиваем 0 персонажа -> тостер отсекся //сразу отвязываем реплики старого персонажа characters[oldIndex]?.UnbindEvents(); Transform container = charactersContainer; //Уводим контейнер за экран yield return MoveLocal(charactersContainer, hiddenLocalPosition, speed); characters[oldIndex].Animator.SetTrigger("PreAppear"); //Сажаем нового персонажа SetCharacter(newIndex); yield return new WaitForSeconds(0.1f); //Выводим на экран yield return MoveLocal(charactersContainer, shownLocalPosition, speed); //дергаем появление CharacterEventBus.Instance.OnCharacterAppeared?.Invoke(); //понижение уровня if (newIndex < oldIndex) CharacterEventBus.Instance.OnLevelDown?.Invoke(); } void printPresetsInfo() { StringBuilder sb = new StringBuilder(); foreach (Character character in characters) { sb.Append(character.name + "\n"); List> lists = new List>(); lists.Add(character.difficultyPresetsEasy); lists.Add(character.difficultyPresetsMedium); lists.Add(character.difficultyPresetsHard); for (int i = 0; i < 3; i++) { List list = lists[i]; if (i == 0) sb.Append("Легкий\n"); if (i == 1) sb.Append("Средний\n"); if (i == 2) sb.Append("Сложный\n"); int presetindex = 0; foreach (DifficultyPreset preset in list) { sb.Append(presetindex.ToString() + "\n"); sb.Append("Описание: " + preset.Description + "\n"); sb.Append("Глубина поиска: " + preset.Depth + "\n"); sb.Append("Бонус победы: " + preset.WinBonus + "\n"); sb.Append("Бонус 2 в ряд: " + preset.RowOfTwoBonus + "\n"); sb.Append("Бонус 3 в ряд: " + preset.RowOfThree + "\n"); sb.Append("Бонус центр: " + preset.CenterBonus + "\n"); sb.Append("Бонус блок: " + preset.BlockBonus + "\n"); sb.Append("Случайный ход: " + preset.RandomMoveRate + "\n"); sb.Append("Ошибочный ход: " + preset.MistakeRate + "\n"); sb.Append("Температура: " + preset.Temperature + "\n"); sb.Append("Сигма-шум: " + preset.ScoreNoiseSigma + "\n"); sb.Append("Количество вариантов для выбора по софтмаксу: " + preset.TopK + "\n"); sb.Append("\n\n"); presetindex++; } } Debug.Log(sb.ToString()); sb.Clear(); } } public static void ExportCharactersReplicas() { StringBuilder sb = new StringBuilder(); foreach (Character character in I.characters) { // Заголовок с именем персонажа sb.AppendLine($"=={character.name}=="); // Появление sb.AppendLine("Появление"); for (int i = 0; i < character.appearReplicas.Count; i++) { sb.AppendLine($"{i + 1}. {character.appearReplicas[i].text}"); } sb.AppendLine(); // Ход игрока sb.AppendLine("Ход игрока"); for (int i = 0; i < character.playerTurnReplicas.Count; i++) { sb.AppendLine($"{i + 1}. {character.playerTurnReplicas[i].text}"); } sb.AppendLine(); // Ход бота sb.AppendLine("Ход бота"); for (int i = 0; i < character.botTurnReplicas.Count; i++) { sb.AppendLine($"{i + 1}. {character.botTurnReplicas[i].text}"); } sb.AppendLine(); // Игрок выиграл sb.AppendLine("Игрок выиграл"); for (int i = 0; i < character.playerWinReplicas.Count; i++) { sb.AppendLine($"{i + 1}. {character.playerWinReplicas[i].text}"); } sb.AppendLine(); // Бот выиграл sb.AppendLine("Бот выиграл"); for (int i = 0; i < character.botWinReplicas.Count; i++) { sb.AppendLine($"{i + 1}. {character.botWinReplicas[i].text}"); } sb.AppendLine(); // Вернулись на предыдущий уровень sb.AppendLine("Вернулись на предыдущий уровень"); for (int i = 0; i < character.returnReplicas.Count; i++) { sb.AppendLine($"{i + 1}. {character.returnReplicas[i].text}"); } sb.AppendLine(); // Ничья sb.AppendLine("Ничья"); for (int i = 0; i < character.drawReplicas.Count; i++) { sb.AppendLine($"{i + 1}. {character.drawReplicas[i].text}"); } sb.AppendLine(); sb.AppendLine(); } // Сохранение в файл string filePath = Application.dataPath + "/CharactersReplicas.txt"; System.IO.File.WriteAllText(filePath, sb.ToString()); Debug.Log($"Реплики персонажей экспортированы в: {filePath}"); } }