Платформер враги, инфраструктура, герой

This commit is contained in:
ThomasCharester committed 2026-03-09 16:28:40 +03:00
1 parent 28125eb382
commit 93819c1dd3
61 files changed
+1463 -423

No files matched your search

@@ -13,14 +13,15 @@ namespace Code.Example.Platformer.Entity.Enemies
protected override void Move()
{
if (_target)
{
_directionRight = (transform.position - _target.position).magnitude < float.Epsilon;
_directionRight = ((_target.position - transform.position)).x > float.Epsilon;
UnityEngine.Debug.DrawLine(transform.position, (transform.position + (_target.position - transform.position)), Color.salmon);
CheckupDirection();
rigidbody2D.linearVelocityX = _directionRight ? 0.5f : -0.5f;
rigidbody2D.linearVelocity *= _acceleration;
rigidbody2D.linearVelocityX *= _acceleration;
}
else
{
@@ -14,6 +14,15 @@ namespace Code.Example.Platformer.Entity
[SerializeField] protected Animator animator;
[SerializeField] protected SpriteRenderer spriteRenderer;
[SerializeField] private Vector2 groundPoint;
private EntityHealth _health;
private PlatformerEntityData _data;
public void SetData(PlatformerEntityData data)
{
_data = data;
_health = new(data.maxHealth);
}
protected bool onGround;
@@ -29,7 +38,9 @@ namespace Code.Example.Platformer.Entity
{
onGround = CheckGround();
animator.SetBool(OnGround, onGround);
Move();
if(rigidbody2D.linearVelocity.x is > 0.01f or < -0.01f) HandleFlipX();
}
@@ -40,5 +51,7 @@ namespace Code.Example.Platformer.Entity
}
protected abstract void Move();
public virtual void GetDamage(int damage) => _health.GiveDamage(damage);
}
}
@@ -0,0 +1,27 @@
namespace Code.Example.Platformer.Entity
{
public class EntityHealth
{
private int _health, _maxHealth;
public bool IsDead { get; private set; }
public EntityHealth(int initialHealth)
{
_health = initialHealth;
}
public void GiveDamage(int damage)
{
_health -= damage;
if(_health <= 0) IsDead = true;
}
public void Heal(int heal)
{
if (IsDead) return;
if (_health + heal > _maxHealth) _health = _maxHealth;
else _health += heal;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a3078030faef42b5bddd46a7c5c91d95
timeCreated: 1773058870
@@ -1,32 +1,115 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Code.Infrastructure.Configs;
using Code.Infrastructure.EventBus;
using Code.Infrastructure.Generators;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
namespace Code.Example.Platformer.Entity
{
[Config("Configs/Gameplay/Platformer/EnemySettings", true)]
public class PlatformerEnemySettings
[Config("Configs/Gameplay/Platformer/EntitySettings", true)]
public class PlatformerEntitySettings
{
[ToConfig] public PlatformerEnemyData racerData;
[ToConfig] public PlatformerEntityData EntityData;
[ToConfig] public AssetReference prefabReference;
}
[Serializable]
public struct PlatformerEnemyData
public struct PlatformerEntityData
{
public string name;
public float speed;
public float acceleration;
public int damage;
public PlatformerEnemyType type;
public PlatformerEntityType type;
public int maxHealth;
}
public enum PlatformerEnemyType
public enum PlatformerEntityType
{
Dummy
Player,
Boar,
Bee,
Snail
}
public class PlatformerEnemyFactory
{
private EventBus _eventBus;
private string _enemyConfigsLabel;
private AsyncOperationHandle<IList<PlatformerEntitySettingsConfig>> _enemyConfigsHandle;
private Dictionary<PlatformerEntityType, AsyncOperationHandle<GameObject>> _enemyPrefabsHandle = new();
private Dictionary<PlatformerEntityType, PlatformerEntitySettingsConfig> _enemyConfigs;
public PlatformerEnemyFactory(IConfigLocator configLocator, EventBus eventBus)
{
_eventBus = eventBus;
_enemyConfigsLabel = configLocator.TryGetManyConfigAssetReferences<PlatformerEntitySettingsConfig>();
LoadConfigs().Forget();
}
private async UniTaskVoid LoadConfigs()
{
_enemyConfigsHandle = Addressables.LoadAssetsAsync<PlatformerEntitySettingsConfig>(_enemyConfigsLabel);
await _enemyConfigsHandle.ToUniTask();
_enemyConfigs = _enemyConfigsHandle.Result.ToDictionary(x => x.racerData.type);
_enemyConfigs.Remove(PlatformerEntityType.Player);
_eventBus.RaiseEvent<IPlatformerFactoryInitializedHandle>(x => x.PlatformerFactoryInitialized());
}
public async UniTaskVoid LoadRacer(PlatformerEntityType racerType)
{
if (racerType == PlatformerEntityType.Player) return;
if (_enemyPrefabsHandle.ContainsKey(racerType))
{
_eventBus.RaiseEvent<IPlatformerEnemyLoadedHandle>(x => x.PlatformerEnemyLoaded(racerType, null));
return;
}
UnityEngine.Debug.LogWarning($"Racer loaded {racerType}");
_enemyPrefabsHandle.Add(racerType,
Addressables.LoadAssetAsync<GameObject>(_enemyConfigs[racerType].prefabReference));
await _enemyPrefabsHandle[racerType].ToUniTask();
var racer = _enemyPrefabsHandle[racerType].Result.GetComponent<Entity>();
racer.SetData(_enemyConfigs[racerType].racerData);
_eventBus.RaiseEvent<IPlatformerEnemyLoadedHandle>(x => x.PlatformerEnemyLoaded(racerType, racer));
}
public void ReleaseRacer(PlatformerEntityType racerType)
{
_enemyPrefabsHandle[racerType].Release();
_enemyPrefabsHandle.Remove(racerType);
}
public void Dispose()
{
UnityEngine.Debug.LogWarning($"Racers released");
foreach (var prefab in _enemyPrefabsHandle)
prefab.Value.Release();
_enemyPrefabsHandle.Clear();
_enemyConfigsHandle.Release();
}
}
public interface IPlatformerFactoryInitializedHandle : IGlobalSubscriber
{
public void PlatformerFactoryInitialized();
}
public interface IPlatformerEnemyLoadedHandle : IGlobalSubscriber
{
public void PlatformerEnemyLoaded(PlatformerEntityType type, Entity entity);
}
}
@@ -1,4 +1,6 @@
using System;
using Code.Infrastructure.Audio;
using Code.Infrastructure.Camera;
using Code.Infrastructure.Configs;
using Code.Infrastructure.Input;
using Reflex.Attributes;
using UnityEngine;
@@ -8,34 +10,48 @@ namespace Code.Example.Platformer.Entity
{
public class PlayerEntity : Entity
{
private static readonly int OnAttack = Animator.StringToHash("OnAttack");
private IInputService _inputService;
[Inject]
private void Construct(IInputService inputService)
private void Construct(IInputService inputService, IAudioService audioService)
{
_audioService = audioService;
_inputService = inputService;
_inputService.BindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Move,
_inputService.BindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Move,
MovementPerformed);
_inputService.BindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Move,
_inputService.BindActionCancelled((int)ActionMappings.Platformer, (int)PlatformerActions.Move,
MovementCancelled);
_inputService.BindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, JumpPerformed);
_inputService.BindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Jump, JumpPerformed);
_inputService.BindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Attack, AttackPerformed);
_inputService.BindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Sprint, SprintPerformed);
_inputService.BindActionCancelled((int)ActionMappings.Platformer, (int)PlatformerActions.Sprint, SprintCancelled);
//cameraFactory.GetCinematicCamera(CameraMode.Platformer).Follow = transform; , CameraFactory cameraFactory
}
private void OnDestroy()
{
_inputService.UnbindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Move,
_inputService.UnbindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Move,
MovementPerformed);
_inputService.UnbindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Move,
_inputService.UnbindActionCancelled((int)ActionMappings.Platformer, (int)PlatformerActions.Move,
MovementCancelled);
_inputService.UnbindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, JumpPerformed);
_inputService.UnbindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Jump, JumpPerformed);
_inputService.UnbindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Attack, AttackPerformed);
_inputService.UnbindActionPerformed((int)ActionMappings.Platformer, (int)PlatformerActions.Sprint, SprintPerformed);
_inputService.UnbindActionCancelled((int)ActionMappings.Platformer, (int)PlatformerActions.Sprint, SprintCancelled);
}
private float _acceleration = 1f;
protected override void Move()
{
rigidbody2D.linearVelocityX = _moveDirection.x * 5f;
rigidbody2D.linearVelocityX = _moveDirection.x * 2f * _acceleration;
}
private Vector2 _moveDirection;
private IAudioService _audioService;
private void MovementPerformed(InputAction.CallbackContext callbackContext) =>
_moveDirection = callbackContext.ReadValue<Vector2>();
@@ -46,7 +62,48 @@ namespace Code.Example.Platformer.Entity
private void JumpPerformed(InputAction.CallbackContext callbackContext)
{
if (!onGround) return;
rigidbody2D.AddForceY(100f);
rigidbody2D.AddForceY(150f);
_acceleration = 1f;
}
[SerializeField] private Vector2 attackOffset;
private void AttackPerformed(InputAction.CallbackContext callbackContext)
{
if (!onGround) return;
//
//
_audioService.PlayOneShot(AudioNames.UISounds, 1);
animator.SetBool(OnAttack, true);
}
public void CastAttack()
{
var damagedOnes =
Physics2D.OverlapPointAll((Vector2)transform.position + attackOffset, LayerMasks.Masks[LayerMaskType.PlatformerEnemy]);
if (damagedOnes == null) return;
foreach (var damaged in damagedOnes)
{
damaged.gameObject.GetComponent<Entity>().GetDamage(1);
_audioService.PlayOneShot(AudioNames.UISounds, 2);
}
}
private void SprintPerformed(InputAction.CallbackContext callbackContext)
{
if (!onGround) return;
//
_acceleration = 3f;
}
private void SprintCancelled(InputAction.CallbackContext callbackContext)
{
_acceleration = 1f;
}
public void AttackEnd() => animator.SetBool(OnAttack, false);
}
}
@@ -30,7 +30,7 @@ namespace Code.Example.Platformer
Context.UIService.OpenPanel(UIPanelType.Loading);
Context.SceneLoader.LoadSceneAsync(SceneId.Platformer, LoadSceneMode.Single).Forget();
Context.InputService.EnableMap(ActionMappings.Gameplay);
Context.InputService.EnableMap(ActionMappings.Platformer);
Context.CameraFactory.LoadCinemachineCamera(CameraMode.Platformer).Forget();
}
private Loading _loading;
@@ -45,7 +45,7 @@ namespace Code.Example.Platformer
protected override void OnExitState()
{
Context.CameraFactory.ReleaseCinemachineCamera(CameraMode.Platformer);
Context.InputService.DisableMap(ActionMappings.Gameplay);
Context.InputService.DisableMap(ActionMappings.Platformer);
EventBus.Unsubscribe(this);
}
@@ -15,10 +15,10 @@ namespace Code.Example.Race.Racer.Player
public void Construct(IInputService inputService)
{
_inputService = inputService;
_inputService.BindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Move, MovementPerformed);
_inputService.BindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Move, MovementEnded);
_inputService.BindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, BrakePerformed);
_inputService.BindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, BrakeEnded);
_inputService.BindActionPerformed((int)ActionMappings.Race, (int)RaceActions.Move, MovementPerformed);
_inputService.BindActionCancelled((int)ActionMappings.Race, (int)RaceActions.Move, MovementEnded);
_inputService.BindActionPerformed((int)ActionMappings.Race, (int)RaceActions.Brake, BrakePerformed);
_inputService.BindActionCancelled((int)ActionMappings.Race, (int)RaceActions.Brake, BrakeEnded);
}
private void MovementPerformed(InputAction.CallbackContext context) => MovementInput = context.ReadValue<Vector2>();
@@ -32,10 +32,10 @@ namespace Code.Example.Race.Racer.Player
private void OnDestroy()
{
if (_inputService == null) return;
_inputService.UnbindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Move, MovementPerformed);
_inputService.UnbindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Move, MovementEnded);
_inputService.UnbindActionPerformed((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, BrakePerformed);
_inputService.UnbindActionCancelled((int)ActionMappings.Gameplay, (int)GameplayActions.Brake, BrakeEnded);
_inputService.UnbindActionPerformed((int)ActionMappings.Race, (int)RaceActions.Move, MovementPerformed);
_inputService.UnbindActionCancelled((int)ActionMappings.Race, (int)RaceActions.Move, MovementEnded);
_inputService.UnbindActionPerformed((int)ActionMappings.Race, (int)RaceActions.Brake, BrakePerformed);
_inputService.UnbindActionCancelled((int)ActionMappings.Race, (int)RaceActions.Brake, BrakeEnded);
}
}
}
@@ -8,7 +8,7 @@ using UnityEngine;
namespace Code.Example.Race.UI
{
public class PlayerScoreCounter : UIPanel, IScoreChangedHandle
public partial class PlayerScoreCounter : UIPanel, IScoreChangedHandle
{
[SerializeField] private TMP_Text playerScore;
private EventBus _eventBus;
+1 -1
View File
@@ -8,7 +8,7 @@ using UnityEngine.UI;
namespace Code.Example.Race.UI
{
public class PlayerScores : UIPanel
public partial class PlayerScores : UIPanel
{
[SerializeField] private Image image;
[SerializeField] private TMP_Text scoreText;
+1 -1
View File
@@ -7,7 +7,7 @@ using UnityEngine.UI;
namespace Code.Example.Race.UI
{
public class WinScreen : UIPanel
public partial class WinScreen : UIPanel
{
[SerializeField] private Image image;
[SerializeField] private TMP_Text winText;
+17 -21
View File
@@ -6,6 +6,7 @@ using Code.Infrastructure.Input;
using Code.Infrastructure.Loadings;
using Code.Infrastructure.SceneLoader;
using Code.Infrastructure.UI;
using Code.Infrastructure.UI.Panels;
using Code.Infrastructure.Volume;
using Reflex.Core;
using Reflex.Enums;
@@ -23,7 +24,8 @@ namespace Code.Infrastructure.App
IInputServiceInitializedHandle,
ICameraInitializedHandle,
IUIInitializedHandle,
IUIPanelLoaded,
ILoadingPanelCreatedHandle,
ILogoPanelCreatedHandle,
IVolumesInitializedHandle,
IVolumeLoaded,
IAudioSourcePoolInitializedHandle,
@@ -151,26 +153,8 @@ namespace Code.Infrastructure.App
_ui2CamLoading.DoProgress();
_initialLoading.DoProgress();
_thatRightContainer.Resolve<IUIService>().TryLoadPanel(UIPanelType.Logo);
_thatRightContainer.Resolve<IUIService>().TryLoadPanel(UIPanelType.Loading);
}
public void UILoaded(UIPanelType uiPanelType)
{
switch (uiPanelType)
{
case UIPanelType.Logo:
_thatRightContainer.Resolve<IUIService>().OpenPanel(UIPanelType.Logo);
_initialLoading.DoProgress();
break;
case UIPanelType.Loading:
// _thatRightContainer.Resolve<IUIService>().OpenPanel(UIPanelType.Logo);
break;
default:
Application.Quit();
break;
}
_thatRightContainer.Resolve<IUIService>().TryLoadCreatePanel(UIPanelType.Logo);
_thatRightContainer.Resolve<IUIService>().TryLoadCreatePanel(UIPanelType.Loading);
}
public void VolumesInitialized()
@@ -212,5 +196,17 @@ namespace Code.Infrastructure.App
{
_initialLoading.DoProgress();
}
public void LoadingPanelCreated(UIPanel panel)
{
_thatRightContainer.Resolve<IUIService>().OpenPanel(UIPanelType.Logo);
_initialLoading.DoProgress();
}
public void LogoPanelCreated(UIPanel panel)
{
}
}
}
@@ -1,14 +1,13 @@
using System.Threading;
using Code.Debug;
using Code.Infrastructure.Audio;
using Code.Infrastructure.Generators;
using Code.Infrastructure.UI;
using Code.Infrastructure.UI;
using Code.Infrastructure.UI.Panels;
namespace Code.Infrastructure.App.States
{
[State(typeof(AppStates),typeof(AppStateMachineContext))]
[StateRaisingEvent]
public partial class BootstrapState : IUIPanelLoaded, IReadyToPlayHandle
public partial class BootstrapState : IReadyToPlayHandle, IMenuChoosePanelCreatedHandle
{
private EventBus.EventBus _eventBus;
public BootstrapState(AppStateMachineContext context, EventBus.EventBus eventBus) : base(context,eventBus)
@@ -23,7 +22,7 @@ namespace Code.Infrastructure.App.States
Context.UIService.TryRemovePanel(UIPanelType.Logo);
Context.UIService.TryLoadPanel(UIPanelType.DebugSceneChooser);
Context.UIService.TryLoadCreatePanel(UIPanelType.DebugSceneChooser);
Context.AudioFactory.LoadAudioClips(AudioNames.UISounds);
}
@@ -33,16 +32,16 @@ namespace Code.Infrastructure.App.States
Context.UIService.TryRemovePanel(UIPanelType.DebugSceneChooser);
_eventBus.Unsubscribe(this);
}
public void UILoaded(UIPanelType uiPanelType)
{
if (uiPanelType != UIPanelType.DebugSceneChooser) return;
Context.UIService.OpenPanel(uiPanelType);
}
public void OnReadyToPlay(AudioNames groupName)
{
Context.AudioService.PlayRepeatedly(AudioNames.UISounds,0);
}
public void MenuChoosePanelCreated(UIPanel panel)
{
panel.gameObject.SetActive(true);
panel.Open();
}
}
}
@@ -18,7 +18,7 @@ using Reflex.Core;
using Reflex.Injectors;
using Unity.Cinemachine;
using UnityEngine.SceneManagement;
// Ивенты создания панелей сломаны TODO
namespace Code.Infrastructure.App.States
{
[State(typeof(AppStates), typeof(AppStateMachineContext))]
@@ -27,7 +27,6 @@ namespace Code.Infrastructure.App.States
IOnGameplaySceneLoadedHandler,
IRaceGameHandle,
IRacerFactoryInitializedHandle,
IUIPanelLoaded,
ICinematicMachineHandle
{
public GameplayState(AppStateMachineContext context, EventBus.EventBus eventBus) : base(context, eventBus)
@@ -52,11 +51,11 @@ namespace Code.Infrastructure.App.States
// CinemachineCamera
_gameplayLoading = new Loading(7, GameplayLoadingCompleted);
Context.UIService.TryLoadPanel(UIPanelType.PlayerScoreCounter);
Context.UIService.TryLoadPanel(UIPanelType.WinScreen);
Context.UIService.TryLoadPanel(UIPanelType.PlayerScores);
Context.UIService.TryLoadCreatePanel(UIPanelType.PlayerScoreCounter);
Context.UIService.TryLoadCreatePanel(UIPanelType.WinScreen);
Context.UIService.TryLoadCreatePanel(UIPanelType.PlayerScores);
Context.SceneLoader.LoadSceneAsync(SceneId.Gameplay, LoadSceneMode.Single).Forget();
Context.InputService.EnableMap(ActionMappings.Gameplay);
Context.InputService.EnableMap(ActionMappings.Race);
Context.CameraFactory.LoadCinemachineCamera(CameraMode.ThirdPerson).Forget();
}
@@ -85,7 +84,7 @@ namespace Code.Infrastructure.App.States
Context.UIService.TryRemovePanel(UIPanelType.WinScreen);
Context.UIService.TryRemovePanel(UIPanelType.PlayerScores);
Context.CameraFactory.ReleaseCinemachineCamera(CameraMode.ThirdPerson);
Context.InputService.DisableMap(ActionMappings.Gameplay);
Context.InputService.DisableMap(ActionMappings.Race);
_raceGame = null;
@@ -120,7 +119,7 @@ namespace Code.Infrastructure.App.States
public void RaceGameEnded(RaceScores scores)
{
var winScreen = (WinScreen)Context.UIService.TryGetPanel(UIPanelType.WinScreen);
var winScreen = (WinScreen)Context.UIService.TryGetSinglePanel(UIPanelType.WinScreen);
var id = 0;
var cachedScores = scores.GetScores();
@@ -133,7 +132,7 @@ namespace Code.Infrastructure.App.States
var winText = $@"{id} МЕСТО\n";
winScreen.SetText(winText);
var getPanel = Context.UIService.TryGetPanel(UIPanelType.PlayerScores);
var getPanel = Context.UIService.TryGetSinglePanel(UIPanelType.PlayerScores);
((PlayerScores)getPanel)
.SetText(UNTILTHEYFIXCONTAINERS.Resolve<PlayerPrefsRacePoopshitter>().GetRaces());
Context.UIService.ClosePanel(UIPanelType.PlayerScoreCounter);
@@ -176,5 +175,14 @@ namespace Code.Infrastructure.App.States
}
public void CinemachineLoaded(CinemachineCamera cinemachineCamera) => _gameplayLoading.DoProgress();
public void UISinglePanelLoaded(UIPanelType uiPanelType)
{
}
public void UISinglePanelRemoved(UIPanelType uiPanelType)
{
throw new System.NotImplementedException();
}
}
}
@@ -12,7 +12,7 @@ namespace Code.Infrastructure.App.States
{
[State(typeof(AppStates),typeof(AppStateMachineContext))]
[StateRaisingEvent]
public partial class MainMenuState : IUIPanelLoaded, IReadyToPlayHandle, IOnMainMenuSceneLoadedHandler
public partial class MainMenuState : IReadyToPlayHandle, IOnMainMenuSceneLoadedHandler, IMenuChoosePanelCreatedHandle
{
public MainMenuState(AppStateMachineContext context, EventBus.EventBus eventBus) : base(context,eventBus)
{
@@ -26,7 +26,7 @@ namespace Code.Infrastructure.App.States
_loading = new Loading(2, LoadComplete);
Context.UIService.TryLoadPanel(UIPanelType.DebugSceneChooser);
Context.UIService.TryLoadCreatePanel(UIPanelType.DebugSceneChooser);
// Context.AudioFactory.LoadAudioClips(AudioNames.UISounds);
Context.SceneLoader.LoadSceneAsync(SceneId.MainMenu, LoadSceneMode.Single).Forget();
Context.AudioService.PlayRepeatedly(AudioNames.UISounds,0);
@@ -39,14 +39,6 @@ namespace Code.Infrastructure.App.States
EventBus.Unsubscribe(this);
}
public void UILoaded(UIPanelType uiPanelType)
{
if (uiPanelType != UIPanelType.DebugSceneChooser) return;
Context.UIService.OpenPanel(uiPanelType);
_loading.DoProgress();
}
private void LoadComplete()
{
Context.UIService.OpenPanel(UIPanelType.DebugSceneChooser);
@@ -68,5 +60,13 @@ namespace Code.Infrastructure.App.States
{
}
public void MenuChoosePanelCreated(UIPanel panel)
{
panel.gameObject.SetActive(true);
panel.Open();
_loading.DoProgress();
}
}
}
@@ -2,6 +2,8 @@ namespace Code.Infrastructure.Configs
{
public enum LayerMaskType
{
PlatformerGround
PlatformerGround,
PlatformerEnemy,
PlatformerPlayer
}
}
@@ -0,0 +1,71 @@
#if UNITY_EDITOR
using Code.Infrastructure.UI;
using UnityCodeGen;
using UnityEditor;
namespace Code.Infrastructure.Generators
{
[Generator]
public class UIPanelEventsGenerator : ICodeGenerator
{
public void Execute(GeneratorContext context)
{
GenerateStates(context);
}
private void GenerateStates(GeneratorContext context)
{
var states = TypeCache.GetTypesDerivedFrom<UIPanel>();
foreach (var st in states)
{
var fireStatesCode = $@"
public override void FireCreatedEvent()
{{
_eventBus.RaiseEvent<I{st.Name}CreatedHandle>(h => h.{st.Name}Created(this));
}}
public override void FireRemovedEvent()
{{
_eventBus.RaiseEvent<I{st.Name}RemovedHandle>(h => h.{st.Name}Removed());
}}
";
var fireStatesInterfacesCode = $@"
public interface I{st.Name}CreatedHandle : IGlobalSubscriber
{{
void {st.Name}Created(UIPanel panel);
}}
public interface I{st.Name}RemovedHandle : IGlobalSubscriber
{{
void {st.Name}Removed();
}}
";
var statesCode = $@"
// retard-generated
using Code.Infrastructure.UI;
using Code.Infrastructure.EventBus;
using Code.Infrastructure.StateMachine;
namespace {st.Namespace}
{{
public partial class {st.Name}
{{
{fireStatesCode}
}}
{fireStatesInterfacesCode}
}}
";
context.AddCode($"{st.FullName}Events.Generated.cs", statesCode);
}
}
}
}
#endif
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e534143b792f4c2692451b19fb9b7e98
timeCreated: 1773046409
@@ -3,13 +3,21 @@ namespace Code.Infrastructure.Input
public enum ActionMappings
{
MainMenu,
Gameplay,
Race,
Platformer,
Debug
}
public enum GameplayActions
public enum RaceActions
{
Move,
Brake,
Brake,
}
public enum PlatformerActions
{
Move,
Jump,
Attack,
Sprint,
}
public enum DebugActions
{
@@ -1,11 +1,9 @@
using UnityEngine;
using UnityEngine.AddressableAssets;
namespace Code.Infrastructure.SceneLoader
{
[CreateAssetMenu(fileName = "ScenesAssetReferences", menuName = "Configs/ScenesAssetReferences")]
public class ScenesAssetReferences : ScriptableObject
{
public AssetReference gameplaySceneReference;
}
}
@@ -1,17 +0,0 @@
using System;
namespace Code.Infrastructure.UI.Panels
{
public class DamnEmptyPanel : UIPanel
{
public override void Open(Action callback = null)
{
callback?.Invoke();
}
public override void Close(Action callback = null)
{
callback?.Invoke();
}
}
}
@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: ce4e618236c441ca857ad458fa13e09d
timeCreated: 1769347387
@@ -5,7 +5,7 @@ using UnityEngine.UI;
namespace Code.Infrastructure.UI.Panels
{
public class LoadingPanel : UIPanel
public partial class LoadingPanel : UIPanel
{
[SerializeField] private RawImage image;
[SerializeField] private Color shownColor;
@@ -5,7 +5,7 @@ using UnityEngine.UI;
namespace Code.Infrastructure.UI.Panels
{
public class LogoPanel : UIPanel
public partial class LogoPanel : UIPanel
{
[SerializeField] private Image image;
[SerializeField] private Color shownColor;
@@ -6,7 +6,7 @@ using UnityEngine;
namespace Code.Infrastructure.UI.Panels
{
public class MenuChoosePanel : UIPanel
public partial class MenuChoosePanel : UIPanel
{
[Inject] IAudioService _audioService;
[SerializeField] private SceneChooser sceneChooser;
+6 -3
View File
@@ -12,14 +12,16 @@ namespace Code.Infrastructure.UI
{
public interface IUIFactory
{
UniTaskVoid LoadPanel(UIPanelType panelType);
UniTaskVoid LoadPanel(UIPanelType panelType, Transform parent = null);
void ReleasePanel(UIPanel panel);
Canvas Canvas { get; }
bool CheckIsMultiple(UIPanelType panelType);
}
public class UIFactory : IDisposable, IUIFactory
{
private Dictionary<UIPanelType, UIPanelSettingsConfig> _configs;
public bool CheckIsMultiple(UIPanelType panelType) => _configs[panelType].Multiple;
private AssetReference _canvasConfigReference;
private string _configsLabel;
private EventBus.EventBus _eventBus;
@@ -41,9 +43,9 @@ namespace Code.Infrastructure.UI
LoadConfigs().Forget();
}
public async UniTaskVoid LoadPanel(UIPanelType panelType)
public async UniTaskVoid LoadPanel(UIPanelType panelType, Transform parent = null)
{
var panel = (await Addressables.InstantiateAsync(_configs[panelType].Prefab, _canvas.transform).ToUniTask())
var panel = (await Addressables.InstantiateAsync(_configs[panelType].Prefab, parent ?? _canvas.transform).ToUniTask())
.GetComponent<UIPanel>();
UnityEngine.Debug.LogWarning($"Panel loaded {panelType}");
@@ -90,5 +92,6 @@ namespace Code.Infrastructure.UI
public interface IUIPanelLoadedHandle : IGlobalSubscriber
{
void UIPanelLoaded(UIPanel panel, UIPanelType panelType);
List<UIPanel> TryGetMultiplePanels(UIPanelType panelType);
}
}
@@ -1,3 +1,2 @@
fileFormatVersion: 2
guid: 8447b81247b24f1b869b0067aeeff0b8
timeCreated: 1768979324
guid: 8447b81247b24f1b869b0067aeeff0b8
+8
View File
@@ -1,13 +1,21 @@
using System;
using Reflex.Attributes;
using UnityEngine;
namespace Code.Infrastructure.UI
{
public abstract class UIPanel : MonoBehaviour
{
public UIPanelType PanelType { get; set; }
[SerializeField] protected bool injectMeSenpai;
public bool InjectMeSenpai => injectMeSenpai;
[Inject] protected EventBus.EventBus _eventBus;
public abstract void Open(Action callback = null);
public abstract void Close(Action callback = null);
public virtual void FireCreatedEvent(){}
public virtual void FireRemovedEvent(){}
}
}
@@ -8,6 +8,7 @@ namespace Code.Infrastructure.UI
{
[ToConfig] public AssetReference Prefab;
[ToConfig] public UIPanelType UIPanelType;
[ToConfig] public bool Multiple;
}
[Config("Configs/UI/CanvasSettings")]
+76 -19
View File
@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Code.Infrastructure.EventBus;
using Reflex.Core;
using Reflex.Extensions;
using Reflex.Injectors;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Code.Infrastructure.UI
@@ -12,15 +14,18 @@ namespace Code.Infrastructure.UI
{
void OpenPanel(UIPanelType uiPanelType);
void ClosePanel(UIPanelType uiPanelType);
void TryLoadPanel(UIPanelType uiPanelType);
void TryLoadCreatePanel(UIPanelType uiPanelType, Transform parent = null);
void TryRemovePanel(UIPanelType uiPanelType);
void SetCanvasCamera(UnityEngine.Camera camera);
UIPanel TryGetPanel(UIPanelType panelType);
UIPanel TryGetSinglePanel(UIPanelType panelType);
void TryRemovePanel(UIPanel panel);
}
// Крайне неудобно пользоваться
public class UIService : IUIPanelLoadedHandle, IUIService
{
private Dictionary<UIPanelType, UIPanel> _loadedPanels = new();
private Dictionary<UIPanelType, UIPanel> _loadedSinglePanels = new();
private Dictionary<UIPanelType, List<UIPanel>> _loadedMultiplePanels = new();
private EventBus.EventBus _eventBus;
private IUIFactory _factory;
@@ -40,49 +45,101 @@ namespace Code.Infrastructure.UI
public void OpenPanel(UIPanelType uiPanelType)
{
_loadedPanels[uiPanelType].gameObject.SetActive(true);
_loadedPanels[uiPanelType].Open();
_loadedSinglePanels[uiPanelType].gameObject.SetActive(true);
_loadedSinglePanels[uiPanelType].Open();
}
// TODO Close event
public void ClosePanel(UIPanelType uiPanelType)
{
_loadedPanels[uiPanelType].Close(() => { _loadedPanels[uiPanelType].gameObject.SetActive(false); });
_loadedSinglePanels[uiPanelType].Close(() =>
{
_loadedSinglePanels[uiPanelType].gameObject.SetActive(false);
});
}
public void TryLoadPanel(UIPanelType uiPanelType) => _factory.LoadPanel(uiPanelType);
public void TryLoadCreatePanel(UIPanelType uiPanelType, Transform parent = null) => _factory.LoadPanel(uiPanelType, parent);
public void UIPanelLoaded(UIPanel panel, UIPanelType panelType)
{
_loadedPanels.Add(panelType, panel);
panel.PanelType = panelType;
if (!_factory.CheckIsMultiple(panelType))
_loadedSinglePanels.Add(panelType, panel);
else
{
if (!_loadedMultiplePanels.ContainsKey(panelType))
_loadedMultiplePanels.Add(panelType, new List<UIPanel>());
_loadedMultiplePanels[panelType].Add(panel);
}
if (panel.InjectMeSenpai)
GameObjectInjector.InjectRecursive(panel.gameObject, Container.RootContainer);
else
GameObjectInjector.InjectSingle(panel.gameObject, Container.RootContainer);
// GameObjectInjector.InjectRecursive(panel.gameObject, SceneManager.GetActiveScene().GetSceneContainer()); // Скорее всего будут нужны компоненты текущей сцены
_eventBus.RaiseEvent<IUIPanelLoaded>(ui => ui.UILoaded(panelType));
panel.FireCreatedEvent();
}
public void TryRemovePanel(UIPanelType uiPanelType)
{
_loadedPanels[uiPanelType].Close(() =>
if (_factory.CheckIsMultiple(uiPanelType))
{
_loadedPanels[uiPanelType].gameObject.SetActive(false);
UnityEngine.Debug.LogError("Это для единичных панелей олух");
return;
}
_loadedSinglePanels[uiPanelType].Close(() =>
{
_loadedSinglePanels[uiPanelType].gameObject.SetActive(false);
RemovePanel(uiPanelType);
});
}
public void TryRemovePanel(UIPanel panel)
{
panel.Close(() =>
{
panel.gameObject.SetActive(false);
RemovePanel(panel);
// _eventBus.RaiseEvent<IUIMultiplePanelHandle>(x=> x.UIMultiplePanelRemoved(panel));
});
}
private void RemovePanel(UIPanelType panelType)
{
_factory.ReleasePanel(_loadedPanels[panelType]);
_loadedPanels.Remove(panelType);
if (!_factory.CheckIsMultiple(panelType))
{
var temp = _loadedSinglePanels[panelType];
_loadedSinglePanels.Remove(panelType);
temp.FireRemovedEvent();
_factory.ReleasePanel(temp);
}
else
{
var temp = _loadedMultiplePanels[panelType];
_loadedMultiplePanels.Remove(panelType);
foreach (var panel in temp)
{
panel.FireRemovedEvent();
_factory.ReleasePanel(panel);
}
}
}
public UIPanel TryGetPanel(UIPanelType panelType) => _loadedPanels.GetValueOrDefault(panelType);
}
private void RemovePanel(UIPanel panel)
{
_loadedMultiplePanels[panel.PanelType].Remove(panel);
panel.FireRemovedEvent();
_factory.ReleasePanel(panel);
if(_loadedMultiplePanels[panel.PanelType].Count == 0) _loadedMultiplePanels.Remove(panel.PanelType);
}
public interface IUIPanelLoaded : IGlobalSubscriber
{
void UILoaded(UIPanelType uiPanelType);
public UIPanel TryGetSinglePanel(UIPanelType panelType) => _loadedSinglePanels.GetValueOrDefault(panelType);
public List<UIPanel> TryGetMultiplePanels(UIPanelType panelType) => _loadedMultiplePanels.GetValueOrDefault(panelType);
}
}