using System; using System.Collections; using System.Collections.Generic; using CharacterSystem; using UnityEngine; using UnityEngine.Serialization; public class DualAvatarController : MonoBehaviour { [SerializeField, FormerlySerializedAs("characterPrefabs")] private List _characterPrefabs; [SerializeField, FormerlySerializedAs("AvatarsParent")] private Transform _avatarsParent; [SerializeField, FormerlySerializedAs("baseHiddenLocalPosition")] private Vector2 _player1HiddenLocalPosition; [SerializeField, FormerlySerializedAs("baseShownLocalPosition")] private Vector2 _player1ShownLocalPosition; [SerializeField] private Vector2 _player2HiddenLocalPosition = new(27f, -5.86f); [SerializeField] private Vector2 _player2ShownLocalPosition = new(11.4f, -5.86f); [SerializeField] private float _characterScale = 10f; [SerializeField, FormerlySerializedAs("CharacterMovementSpeed")] private float _characterMovementSpeed = 15f; private const string AppearTrigger = "Appear"; private const string SleepTrigger = "Sleep"; private const string WinTrigger = "Win"; private readonly Dictionary _characters = new(); private Coroutine _player1Movement; private Coroutine _player2Movement; private bool _isShowing; private bool _isVisible; public static DualAvatarController Instance { get; private set; } public void Initialize() { Instance = this; if (_characters.Count > 0) return; if (_characterPrefabs == null || _characterPrefabs.Count < 2 || _characterPrefabs[0] == null || _characterPrefabs[1] == null) { Debug.LogError("Для PvP не назначены персонажи 6 и 7.", this); return; } _characters[Team.Player1] = CreateCharacter(_characterPrefabs[0], Team.Player1); _characters[Team.Player2] = CreateCharacter(_characterPrefabs[1], Team.Player2); } public void ShowCharacters() { if (_characters.Count < 2 || _isVisible || _isShowing) return; StopMovement(); _isShowing = true; PrepareForAppearance(_characters[Team.Player1]); PrepareForAppearance(_characters[Team.Player2]); int appearedCharacters = 0; Action onAppeared = () => { appearedCharacters++; if (appearedCharacters < 2) return; _isShowing = false; _isVisible = true; }; _player1Movement = StartCoroutine(MoveLocal( _characters[Team.Player1], GetShownPosition(Team.Player1), true, onAppeared)); _player2Movement = StartCoroutine(MoveLocal( _characters[Team.Player2], GetShownPosition(Team.Player2), true, onAppeared)); } public void PlayWin(Team winner) { if (!_characters.TryGetValue(winner, out PvpCharacter character) || !character.Animator.enabled) return; character.Animator.ResetTrigger(WinTrigger); character.Animator.SetTrigger(WinTrigger); } public void HideCharacters() { if (_characters.Count < 2) return; StopMovement(); _isShowing = false; _isVisible = false; _player1Movement = StartCoroutine(MoveLocal( _characters[Team.Player1], GetHiddenPosition(Team.Player1), false, null)); _player2Movement = StartCoroutine(MoveLocal( _characters[Team.Player2], GetHiddenPosition(Team.Player2), false, null)); } private PvpCharacter CreateCharacter(GameObject prefab, Team team) { GameObject characterObject = Instantiate(prefab, _avatarsParent); Animator animator = characterObject.GetComponentInChildren(true); if (animator == null) throw new InvalidOperationException($"У PvP-персонажа {prefab.name} отсутствует Animator."); MessageBox messageBox = characterObject.GetComponentInChildren(true); if (messageBox != null) messageBox.gameObject.SetActive(false); characterObject.transform.localScale = new Vector3(_characterScale, _characterScale, 1f); characterObject.transform.localPosition = GetHiddenPosition(team); animator.enabled = false; return new PvpCharacter(characterObject.transform, animator); } private void PrepareForAppearance(PvpCharacter character) { character.Animator.enabled = true; character.Animator.ResetTrigger(AppearTrigger); character.Animator.ResetTrigger(WinTrigger); character.Animator.ResetTrigger(SleepTrigger); character.Animator.SetTrigger(SleepTrigger); } private void StopMovement() { if (_player1Movement != null) StopCoroutine(_player1Movement); if (_player2Movement != null) StopCoroutine(_player2Movement); _player1Movement = null; _player2Movement = null; } private Vector3 GetHiddenPosition(Team team) => team == Team.Player1 ? _player1HiddenLocalPosition : _player2HiddenLocalPosition; private Vector3 GetShownPosition(Team team) => team == Team.Player1 ? _player1ShownLocalPosition : _player2ShownLocalPosition; private IEnumerator MoveLocal( PvpCharacter character, Vector3 targetLocalPosition, bool playAppear, Action onComplete) { while (character.Transform.localPosition != targetLocalPosition) { character.Transform.localPosition = Vector3.MoveTowards( character.Transform.localPosition, targetLocalPosition, _characterMovementSpeed * Time.deltaTime); yield return null; } if (playAppear) { character.Animator.ResetTrigger(AppearTrigger); character.Animator.SetTrigger(AppearTrigger); } else { character.Animator.enabled = false; } onComplete?.Invoke(); } private sealed class PvpCharacter { public PvpCharacter(Transform transform, Animator animator) { Transform = transform; Animator = animator; } public Transform Transform { get; } public Animator Animator { get; } } }