chip-gameV3/Assets/Scripts/Gameplay/Avatars/DualAvatarController.cs

197 lines
6.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<GameObject> _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<Team, PvpCharacter> _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<Animator>(true);
if (animator == null)
throw new InvalidOperationException($"У PvP-персонажа {prefab.name} отсутствует Animator.");
MessageBox messageBox = characterObject.GetComponentInChildren<MessageBox>(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; }
}
}