Отрефакторить переход меню - геймплей

This commit is contained in:
Сергей Бондарь 2026-08-18 14:10:45 +03:00
parent d14f231f5f
commit 044a7affad
17 changed files with 252 additions and 157 deletions

View File

@ -0,0 +1,21 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fb10f9bdeb89ca14d8ed3d5824e2651d, type: 3}
m_Name: ReplicasContainer
m_EditorClassIdentifier: Assembly-CSharp::CharacterSystem.ReplicasContainer
_appearReplicas: {fileID: 0}
_playerTurnReplicas: {fileID: 0}
_botTurnReplicas: {fileID: 0}
_playerWinReplicas: {fileID: 0}
_botWinReplicas: {fileID: 0}
_returnReplicas: {fileID: 0}
_drawReplicas: {fileID: 0}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4285456e97dd68d4d92902191c1fe701
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

26
Assets/ReplicasSet.asset Normal file
View File

@ -0,0 +1,26 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fa12b3e0d4165b445af7f483b7c509b7, type: 3}
m_Name: ReplicasSet
m_EditorClassIdentifier: Assembly-CSharp::CharacterSystem.ReplicasSet
type: 0
_referenceList:
- clip: {fileID: 0}
text:
- clip: {fileID: 0}
text:
- clip: {fileID: 0}
text:
- clip: {fileID: 0}
text:
- clip: {fileID: 0}
text:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cba7014c36d4dd84fad6793dbd3723aa
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -403,7 +403,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 7238525776732110314, guid: d2448bca251e50a4ebaae923084264a0, type: 3}
propertyPath: m_IsActive
value: 1
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
@ -493,7 +493,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 3388591762507178167, guid: 7702b7919503a1e479151e8fecd78924, type: 3}
propertyPath: m_IsActive
value: 0
value: 1
objectReference: {fileID: 0}
- target: {fileID: 8604408698177003535, guid: 7702b7919503a1e479151e8fecd78924, type: 3}
propertyPath: m_LocalPosition.x

View File

@ -779,8 +779,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: abfc53344afd3dd46b1dcb865ac37f9c, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::MenuGameplayTransit
menu: {fileID: 1122363137}
gameplay: {fileID: 1081324698}
_menu: {fileID: 1122363137}
_gameplay: {fileID: 1081324698}
--- !u!4 &29868613
Transform:
m_ObjectHideFlags: 0
@ -16116,17 +16116,19 @@ MonoBehaviour:
m_GameObject: {fileID: 1122363131}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f9e06af6eabacd64b9e9fd01adb2f197, type: 3}
m_Script: {fileID: 11500000, guid: 04aecb4a37e115f42bd22caaae082c18, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::MenuLayoutController
_panels:
- {fileID: 5981068812792107924}
- {fileID: 6662214523308698939}
- {fileID: 6662214523308698938}
_leftPanel: {fileID: 6665465969600127458}
_rightPanel: {fileID: 558601564}
_transitionDuration: 0.5
_ease: 5
menuAnimator:
_leftPanel: {fileID: 6665465969600127458}
_rightPanel: {fileID: 558601564}
_duration: 1
_ease: 7
menuPanelManager:
_panels:
- {fileID: 5981068812792107924}
- {fileID: 6662214523308698939}
- {fileID: 6662214523308698938}
--- !u!1 &1124603895
GameObject:
m_ObjectHideFlags: 0

View File

@ -24,7 +24,7 @@ public class Bootstrap : MonoBehaviour
[SerializeField] private Defender defender;
[SerializeField] private ControlsPerformer controlsPerformer;
[SerializeField] private MenuLayoutController menu;
[SerializeField] private Menu menu;
[SerializeField] private SettingsScheme defaultSettings;

View File

@ -19,27 +19,34 @@ public class GameplayLayoutController : MonoBehaviour
[SerializeField] private Ease _boardOpenEase;
[SerializeField] private Ease _boardCloseEase;
public Sequence GetOpenSequence() => GetSequenceByState(true);
public Sequence GetCloseSequence() => GetSequenceByState(false);
private Sequence GetSequenceByState(bool open)
public void Open(Action callback)
{
float leftTarget = open ? _leftOpenedPosition : 0;
float boardTarget = open ? _boardOpenedY : _boardClosedY;
Ease boardEase = open ? _boardOpenEase : _boardCloseEase;
Ease panelsEase = open ? _panelsOpenEase : _panelsCloseEase;
return GetTransitionSequence(leftTarget, boardTarget, boardEase, panelsEase);
Sequence seq = GetSequenceByState(open: true);
seq.onComplete += () => callback?.Invoke();
seq.PlayForward();
}
private Sequence GetTransitionSequence(float targetLeftX, float targetBoardY, Ease boardEase, Ease panelsEase)
public void Close(Action callback)
{
Sequence seq = GetSequenceByState(open: false);
seq.onComplete += () => callback?.Invoke();
seq.PlayForward();
}
private Sequence GetSequenceByState(bool open)
{
if (_leftPanel == null || _board == null)
throw new Exception("Панели или доска не назначены!");
float leftTarget = open ? _leftOpenedPosition : 0;
float boardTarget = open ? _boardOpenedY : _boardClosedY;
Ease boardEase = open ? _boardOpenEase : _boardCloseEase;
Ease panelsEase = open ? _panelsOpenEase : _panelsCloseEase;
var sequence = DOTween.Sequence();
Tween left = _leftPanel.DOAnchorPosX(targetLeftX, _panelsTransitionDuration)
Tween left = _leftPanel.DOAnchorPosX(leftTarget, _panelsTransitionDuration)
.SetEase(panelsEase);
Tween board = _board.DOMoveY(targetBoardY, _boardTransitionDuration)
Tween board = _board.DOMoveY(boardTarget, _boardTransitionDuration)
.SetEase(boardEase);
sequence.Append(left);
@ -47,4 +54,4 @@ public class GameplayLayoutController : MonoBehaviour
return sequence;
}
}
}

View File

@ -0,0 +1,33 @@
using DG.Tweening;
using System;
using UnityEngine;
public class Menu : MonoBehaviour, IControlable
{
public MenuAnimator menuAnimator;
public MenuPanelManager menuPanelManager;
public bool ControlsEnabled { get; set; }
public void Initialize()
{
menuAnimator.Initialize();
menuPanelManager.Initialize();
ControlsEnabled = true;
}
public void UpdateControls()
{
int direction_horizontal = In.GetAxis(Axis.Horizontal, JoystickSide.Both);
menuPanelManager.SwitchPanel(direction_horizontal);
bool action = In.GetButtonDownAnyPlayer(PlayerAction.action);
if (action) menuPanelManager.InteractCurrent();
}
public void Open(Action callback)
=> menuAnimator.Open(callback);
public void Close(Action callback)
=> menuAnimator.Close(callback);
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 04aecb4a37e115f42bd22caaae082c18

View File

@ -0,0 +1,62 @@
using DG.Tweening;
using System;
using UnityEngine;
[Serializable]
public class MenuAnimator
{
[SerializeField] private RectTransform _leftPanel;
[SerializeField] private RectTransform _rightPanel;
[SerializeField] private float _duration;
[SerializeField] private Ease _ease;
private float _leftOpenedPosition;
private float _rightOpenedPosition;
public void Initialize()
{
_leftOpenedPosition = _leftPanel.anchoredPosition.x;
_rightOpenedPosition = _rightPanel.anchoredPosition.x;
}
public void Close(Action callback)
{
Sequence menuCloseSeq = GetCloseSequence();
menuCloseSeq.onComplete += () => callback?.Invoke();
menuCloseSeq.PlayForward();
}
public void Open(Action callback)
{
Sequence menuOpenSeq = GetCloseSequence();
menuOpenSeq.onComplete += () => callback?.Invoke();
menuOpenSeq.PlayForward();
}
public Sequence GetOpenSequence() => GetSequenceByState(true);
public Sequence GetCloseSequence() => GetSequenceByState(false);
private Sequence GetSequenceByState(bool open)
{
float leftTarget = open ? _leftOpenedPosition : 0;
float rightTarget = open ? _rightOpenedPosition : 0;
return GetTransitionSequence(leftTarget, rightTarget);
}
private Sequence GetTransitionSequence(float targetLeftX, float targetRightX)
{
if (_leftPanel == null || _rightPanel == null)
throw new Exception("Панели не назначены!");
var sequence = DOTween.Sequence();
Tween left = _leftPanel.DOAnchorPosX(targetLeftX, _duration)
.SetEase(_ease);
Tween right = _rightPanel.DOAnchorPosX(targetRightX, _duration)
.SetEase(_ease);
sequence.Join(left);
sequence.Join(right);
return sequence;
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0fc7aadab83529b48864952efffcb0df

View File

@ -1,84 +0,0 @@
using DG.Tweening;
using System;
using System.Collections.Generic;
using UnityEngine;
public class MenuLayoutController : MonoBehaviour, IControlable
{
[Header("Панели")]
[SerializeField] List<MenuPanel> _panels;
int _panelIndex = 0;
[Header("Анимация открытия/закрытия")]
[SerializeField] private RectTransform _leftPanel;
[SerializeField] private RectTransform _rightPanel;
[SerializeField] private float _transitionDuration;
[SerializeField] private Ease _ease;
private float _leftOpenedPosition;
private float _rightOpenedPosition;
public bool ControlsEnabled { get; set; }
public void Initialize()
{
foreach (var panel in _panels)
{
panel.Initialize();
panel.Disable(0);
}
_panels[_panelIndex].Enable(0, 0);
ControlsEnabled = true;
_leftOpenedPosition = _leftPanel.anchoredPosition.x;
_rightOpenedPosition = _rightPanel.anchoredPosition.x;
}
public void UpdateControls()
{
int direction = In.GetAxis(Axis.Horizontal, JoystickSide.Both);
int newPanelIndex = Mathf.Clamp(_panelIndex + direction, 0, 2);
bool indexChanged = newPanelIndex != _panelIndex;
var currentPanel = _panels[_panelIndex];
if (indexChanged)
{
var nextPanel = _panels[newPanelIndex];
currentPanel.Disable(0);
nextPanel.Enable(0, 0);
_panelIndex = newPanelIndex;
}
if (In.GetButtonDownAnyPlayer(PlayerAction.action))
currentPanel.Interact();
}
public Sequence GetOpenSequence() => GetSequenceByState(true);
public Sequence GetCloseSequence() => GetSequenceByState(false);
private Sequence GetSequenceByState(bool open)
{
float leftTarget = open ? _leftOpenedPosition : 0;
float rightTarget = open ? _rightOpenedPosition : 0;
return GetTransitionSequence(leftTarget, rightTarget);
}
private Sequence GetTransitionSequence(float targetLeftX, float targetRightX)
{
if (_leftPanel == null || _rightPanel == null)
throw new Exception("Панели не назначены!");
var sequence = DOTween.Sequence();
Tween left = _leftPanel.DOAnchorPosX(targetLeftX, _transitionDuration)
.SetEase(_ease);
Tween right = _rightPanel.DOAnchorPosX(targetRightX, _transitionDuration)
.SetEase(_ease);
sequence.Join(left);
sequence.Join(right);
return sequence;
}
}

View File

@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: f9e06af6eabacd64b9e9fd01adb2f197

View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class MenuPanelManager
{
[SerializeField] List<MenuPanel> _panels;
int _currentIndex = 0;
private MenuPanel CurrentPanel => _panels[_currentIndex];
public void Initialize()
{
foreach (var panel in _panels)
{
panel.Initialize();
panel.Disable(0);
}
_panels[_currentIndex].Enable(0, 0);
}
public void SwitchPanel(int direction)
{
//Считаем новый индекс панели
int newIndex = Mathf.Clamp(_currentIndex + direction, 0, _panels.Count - 1);
//Если индекс не поменялся, выход
bool indexChanged = newIndex != _currentIndex;
if (indexChanged == false)
return;
//Выкл старую, Вкл новую
CurrentPanel.Disable(0);
_currentIndex = newIndex;
CurrentPanel.Enable(0, 0);
}
public void InteractCurrent()
=> CurrentPanel.Interact();
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b4d7ec08028d9584f9e666b76c6f5014

View File

@ -1,59 +1,25 @@
using DG.Tweening;
using System;
using System;
using UnityEngine;
public class MenuGameplayTransit : MonoBehaviour
{
[SerializeField] MenuLayoutController menu;
[SerializeField] GameplayLayoutController gameplay;
[SerializeField] private Menu _menu;
[SerializeField] private GameplayLayoutController _gameplay;
public event Action GameplayOpened;
Sequence _sequence;
bool locked = false;
public void GotoGameplay()
{
Lock();
if (_sequence != null)
{
_sequence.Kill();
_sequence = null;
}
_sequence = DOTween.Sequence();
_sequence.Append(menu.GetCloseSequence());
_sequence.Append(gameplay.GetOpenSequence());
_sequence.onComplete += Unlock;
_sequence.onComplete += NotifyGameplayOpened;
_sequence.PlayForward();
}
private void NotifyGameplayOpened()
{
GameplayOpened?.Invoke();
_menu.Close(callback: OnMenuClosed);
}
public void GotoMenu()
{
Lock();
if (_sequence != null)
{
_sequence.Kill();
_sequence = null;
}
_sequence = DOTween.Sequence();
_sequence.Append(gameplay.GetCloseSequence());
_sequence.Append(menu.GetOpenSequence());
_sequence.AppendCallback(() => ControlsPerformer.Instance.SetControlable(menu));
_sequence.onComplete += Unlock;
_sequence.PlayForward();
_gameplay.Close(callback: OnGameplayClosed);
}
private void Lock() => locked = true;
private void Unlock() => locked = false;
}
private void OnGameplayOpened() => GameplayOpened?.Invoke();
private void OnMenuOpened() => ControlsPerformer.Instance.SetControlable(_menu);
private void OnMenuClosed() => _gameplay.Open(OnGameplayOpened);
private void OnGameplayClosed() => _menu.Open(callback: OnMenuOpened);
}