added main menu

This commit is contained in:
MrTorex committed 2026-01-30 17:55:55 +03:00
1 parent b94c6e87c9
commit 12ec4f72f5
686 files changed
+128307 -817

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 282b3d6d5de69601aaa8b4b14c4087dc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+18
View File
@@ -0,0 +1,18 @@
using Code.Input;
using UnityEngine;
using UnityEngine.InputSystem;
namespace Code.DI
{
public class Bootstrapper : MonoBehaviour
{
[SerializeField] private InputActionAsset inputActionAsset;
private void Awake()
{
var container = new GameObject("DIContainer").AddComponent<DIContainer>();
container.Register<IInputService>(new InputService(inputActionAsset));
}
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bab224e8fceb40c6af7375345e959535
timeCreated: 1769783643
+35
View File
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Code.DI
{
public class DIContainer : MonoBehaviour
{
private readonly Dictionary<Type, object> _services = new();
private void Awake()
{
DontDestroyOnLoad(gameObject);
}
public void Register<T>(T service)
{
var type = typeof(T);
if (!_services.TryAdd(type, service))
{
Debug.LogWarning($"Service {type} is already registered.");
}
}
public T Resolve<T>()
{
var type = typeof(T);
if (_services.TryGetValue(type, out var service))
{
return (T)service;
}
throw new Exception($"Service {type} not found.");
}
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1bdc3ec8ff3c4ceea4f305ac78efa03f
timeCreated: 1769783677
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c439fbf21b9eba844adc11d172971f49
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+9
View File
@@ -0,0 +1,9 @@
namespace Code.Input
{
public enum ActionMapping
{
MainMenu,
Gameplay,
UI
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4d4c6fff3fc3400383bf26fb7e794adb
timeCreated: 1769783705
+22
View File
@@ -0,0 +1,22 @@
using System;
using UnityEngine;
using UnityEngine.InputSystem;
namespace Code.Input
{
public interface IInputService
{
void EnableMap(ActionMapping actionMap);
void DisableMap(ActionMapping actionMap);
Vector2 MainMenuParalax { get; }
Vector2 LookInput { get; }
Vector2 MoveInput { get; }
bool SwitchCameraPressed { get; }
void DebugBindAction(int mapId, int actionId, Action<InputAction.CallbackContext> action);
void DebugUnbindAction(int mapId, int actionId, Action<InputAction.CallbackContext> action);
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c6e38cb038374afcb252feccd9a67d96
timeCreated: 1769783664
+81
View File
@@ -0,0 +1,81 @@
using UnityEngine;
using UnityEngine.InputSystem;
namespace Code.Input
{
public class InputService : IInputService
{
private readonly InputActionAsset _inputActionAsset;
private InputAction _lmbInteractAction;
public Vector2 MainMenuParalax { get; private set; }
public Vector2 LookInput { get; private set; }
public Vector2 MoveInput { get; private set; }
public bool SwitchCameraPressed { get; private set; }
public InputService(InputActionAsset inputActionAsset)
{
_inputActionAsset = inputActionAsset;
SetupInputCallbacks();
}
private void SetupInputCallbacks()
{
SetupMainMenuInputCallbacks();
SetupGameplayInputCallbacks();
}
private void SetupGameplayInputCallbacks()
{
var map = _inputActionAsset.actionMaps[(int)ActionMapping.Gameplay];
BindVector2(map, "Look", v => LookInput = v);
BindVector2(map, "Move", v => MoveInput = v);
BindButton(map, "SwitchCamera", v => SwitchCameraPressed = v);
}
private void SetupMainMenuInputCallbacks()
{
var map = _inputActionAsset.actionMaps[(int)ActionMapping.MainMenu];
BindVector2(map, "Parallax", v => MainMenuParalax = v);
}
private void BindButton(InputActionMap map, string actionName, System.Action<bool> setter)
{
var action = map.FindAction(actionName);
if (action == null)
return;
action.performed += _ => setter(true);
action.canceled += _ => setter(false);
}
private void BindVector2(InputActionMap map, string actionName, System.Action<Vector2> setter)
{
var action = map.FindAction(actionName);
if (action == null)
return;
action.performed += ctx => setter(ctx.ReadValue<Vector2>());
action.canceled += _ => setter(Vector2.zero);
}
public void EnableMap(ActionMapping actionMap)
{
_inputActionAsset.actionMaps[(int)actionMap].Enable();
}
public void DisableMap(ActionMapping actionMap)
{
_inputActionAsset.actionMaps[(int)actionMap].Disable();
}
public void DebugBindAction(int mapId, int actionId, System.Action<InputAction.CallbackContext> action) =>
_inputActionAsset.actionMaps[mapId].actions[actionId].performed += action;
public void DebugUnbindAction(int mapId, int actionId, System.Action<InputAction.CallbackContext> action) =>
_inputActionAsset.actionMaps[mapId].actions[actionId].performed -= action;
}
}
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a0247f3e157a49e4a5fba94586bf7ac6
timeCreated: 1769783734
+3
View File
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 24dec3ba40524868a1a3f3f9c2cae101
timeCreated: 1769783798
+160
View File
@@ -0,0 +1,160 @@
using Code.DI;
using Code.Input;
using DG.Tweening;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace Code.UI
{
public class MainMenuController : MonoBehaviour
{
[SerializeField] private TMP_Text logotype;
[SerializeField] private Button startGameButton;
[SerializeField] private Button exitButton;
[SerializeField] private Transform parallaxRoot;
[SerializeField] private Image fader;
[SerializeField] private Image backgroundImage;
[SerializeField] private float parallaxStrength = 15f;
[SerializeField] private float parallaxSmoothTime = 0.1f;
private Vector3 _targetParallaxOffset;
private Vector3 _currentParallaxOffset;
private IInputService _inputService;
private AudioSource _audioSource;
private void Start()
{
var container = FindFirstObjectByType<DIContainer>();
_inputService = container.Resolve<IInputService>();
_inputService.EnableMap(ActionMapping.MainMenu);
_audioSource = FindFirstObjectByType<AudioSource>();
SetupButtons();
AnimateLogo();
AnimateBackground();
FadeIn();
}
private void SetupButtons()
{
startGameButton.onClick.AddListener(OnStartGameClicked);
exitButton.onClick.AddListener(OnExitButtonClicked);
}
private void AnimateLogo()
{
var rect = logotype.rectTransform;
var originalColor = logotype.color;
rect.localScale = Vector3.zero;
rect.rotation = Quaternion.Euler(0, 0, -20f);
logotype.color = new Color(originalColor.r, originalColor.g, originalColor.b, 0f);
var logoSequence = DOTween.Sequence();
logoSequence.Append(rect.DOScale(Vector3.one * 1.2f, 0.6f).SetEase(Ease.OutBack))
.Join(rect.DORotate(Vector3.zero, 0.6f).SetEase(Ease.OutSine))
.Join(logotype.DOColor(originalColor, 0.6f));
logoSequence.OnComplete(() =>
{
rect.DOScale(new Vector3(1.08f, 1.08f, 1f), 5f)
.SetLoops(-1, LoopType.Yoyo)
.SetEase(Ease.InOutSine);
logotype.DOColor(new Color(originalColor.r, originalColor.g, originalColor.b, 0.6f), 3f)
.SetLoops(-1, LoopType.Yoyo)
.SetEase(Ease.InOutSine);
});
}
private void AnimateBackground()
{
if (backgroundImage == null) return;
var rect = backgroundImage.rectTransform;
rect.DOScale(1.2f, 25f)
.SetLoops(-1, LoopType.Yoyo)
.SetEase(Ease.InOutSine);
}
private void FadeIn()
{
_audioSource.volume = 0f;
_audioSource.DOFade(1f, 1f).SetEase(Ease.Linear);
fader.color = new Color(0, 0, 0, 1f);
fader.DOFade(0f, 1f).SetEase(Ease.Linear);
fader.raycastTarget = false;
}
private void Update()
{
HandleParallax();
}
private void HandleParallax()
{
if (!parallaxRoot) return;
var mousePos = _inputService.MainMenuParalax;
var center = new Vector2(Screen.width / 2f, Screen.height / 2f);
if (center.x == 0 || center.y == 0) return;
var offset = (mousePos - center) / center;
_targetParallaxOffset = new Vector3(
-offset.x * parallaxStrength,
-offset.y * parallaxStrength,
0f
);
_currentParallaxOffset = Vector3.Lerp(
_currentParallaxOffset,
_targetParallaxOffset,
Time.deltaTime / parallaxSmoothTime
);
parallaxRoot.localPosition = _currentParallaxOffset;
}
private void OnStartGameClicked() => FadeOutAndLoad("Gameplay");
private void OnExitButtonClicked() => FadeOutAndQuit();
private void FadeOutAndLoad(string sceneName)
{
fader.raycastTarget = true;
_audioSource.DOFade(0, 0.8f).SetEase(Ease.Linear);
fader.DOFade(1f, 0.8f).OnComplete(() =>
{
SceneManager.LoadScene(sceneName);
});
}
private void FadeOutAndQuit()
{
fader.raycastTarget = true;
_audioSource.DOFade(0, 0.8f).SetEase(Ease.Linear);
fader.DOFade(1f, 0.8f).OnComplete(() =>
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying = false;
#else
Application.Quit();
#endif
});
}
private void OnDestroy()
{
_inputService?.DisableMap(ActionMapping.MainMenu);
_inputService?.DisableMap(ActionMapping.Gameplay);
startGameButton?.onClick.RemoveListener(OnStartGameClicked);
exitButton?.onClick.RemoveListener(OnExitButtonClicked);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 34911a55498746b4af30b7fa41f9238a
timeCreated: 1769783809