Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1c2c5fd18 | ||
|
|
485d54f272 | ||
|
|
0d0787b887 | ||
|
|
5d856ae162 | ||
|
|
dd1399e015 | ||
|
|
2b656412d5 | ||
|
|
36e6bc3bc2 | ||
|
|
1e31e1e8b1 | ||
|
|
2897eb88bf | ||
|
|
134adda787 | ||
|
|
2f56a5758d | ||
|
|
fb9510a6b2 | ||
|
|
aa4a9e69dd | ||
|
|
34d7fa3791 | ||
|
|
26804e08f7 | ||
|
|
e96dcf3e0d | ||
|
|
94f0522f89 | ||
|
|
eefcf6eabc | ||
|
|
c85638fda0 | ||
|
|
1de117622e | ||
|
|
e2f8984e6f | ||
|
|
32c6e0630a | ||
|
|
870a4743c6 | ||
|
|
2fc8e249f5 | ||
|
|
280eb3754c | ||
|
|
6eff3ef9a9 | ||
|
|
6b4792393a | ||
|
|
a547c39db7 | ||
|
|
0cab2eda74 | ||
|
|
5d075034b5 | ||
|
|
7f7ba0d9c5 | ||
|
|
ab0b41a318 | ||
|
|
a5ce8522ab | ||
|
|
97aea0fde1 | ||
|
|
e9e8e091b2 | ||
|
|
9e1c1177e0 | ||
|
|
07535982ba | ||
|
|
df0c2b3157 | ||
|
|
d51527b7f3 | ||
|
|
13aca5a86f | ||
|
|
9cc77d5c67 | ||
|
|
c1a0e94fe3 | ||
|
|
acd9cc1a32 | ||
|
|
d14f9c2a9f | ||
|
|
4b6909fe84 | ||
|
|
766609489d | ||
|
|
b7e9a26462 | ||
|
|
3782a0b568 | ||
|
|
000985ee9b | ||
|
|
abde1d5ba9 | ||
|
|
d10d2cdca6 | ||
|
|
01d3b0adec | ||
|
|
b271042137 | ||
|
|
cea36c0cda | ||
|
|
ff8ed96138 | ||
|
|
01505de4c3 | ||
|
|
52edef92e3 | ||
|
|
c6b097a879 | ||
|
|
a243ad53d6 | ||
|
|
85a07065d9 |
No files matched your search
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": "1.0",
|
||||
"components": [
|
||||
"Microsoft.VisualStudio.Workload.ManagedGame"
|
||||
]
|
||||
}
|
||||
@@ -15,7 +15,7 @@ MonoBehaviour:
|
||||
m_DefaultGroup: d447fc60305c17a17bf20948ab295a45
|
||||
m_currentHash:
|
||||
serializedVersion: 2
|
||||
Hash: 00000000000000000000000000000000
|
||||
Hash: 1ec1ee985689145b755c859b69691cb0
|
||||
m_OptimizeCatalogSize: 0
|
||||
m_BuildRemoteCatalog: 0
|
||||
m_CatalogRequestsTimeout: 0
|
||||
|
||||
@@ -32,6 +32,11 @@ MonoBehaviour:
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 1cc66c0b13a946e1c9ec37026268e144
|
||||
m_Address: Audio/Enemies/pl_metal2
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 1d4767c722c05b5d6b96bb226d378c65
|
||||
m_Address: Assets/Resources_moved/Prefabs/Player/ArmsMesh.prefab
|
||||
m_ReadOnly: 0
|
||||
@@ -52,6 +57,16 @@ MonoBehaviour:
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 26d4e4c556527924490b8018cd510eda
|
||||
m_Address: Assets/Resources_moved/Audio/Enemies/bc_bite2.wav
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 28a6c7a4124141341ab7c2b7dfd3e95b
|
||||
m_Address: Assets/Resources_moved/Prefabs/Levels/Level1 2.prefab
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 29bff8011973e4e519906b9da8fca0fc
|
||||
m_Address: Audio/Dispatcher/late3
|
||||
m_ReadOnly: 0
|
||||
@@ -62,6 +77,11 @@ MonoBehaviour:
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 2c6a984e4a1b42647b48e6b7bc69b158
|
||||
m_Address: Prefabs/Levels/Level6
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 2ed2d93a9f39d4edba511cb7396c7bb6
|
||||
m_Address: Assets/Resources_moved/Prefabs/Enemies/Cockroach.prefab
|
||||
m_ReadOnly: 0
|
||||
@@ -82,16 +102,31 @@ MonoBehaviour:
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 3f8f2171cc252d953b82083cc16bd1ae
|
||||
m_Address: Assets/Resources_moved/Prefabs/Levels/Level6_1.prefab
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 48aebfe8826dc0df79d047b5afbf8f5b
|
||||
m_Address: Canvas
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 4b279429428a13040b6d1713122cd0de
|
||||
m_Address: Assets/Resources_moved/Audio/SFX/pl_pain5.wav
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 4bd64d1fcecc9c6b09d81e78b7dcfebe
|
||||
m_Address: Audio/Dispatcher/take_damage1
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 7067a5248027e74478f4f0f53ddf06a4
|
||||
m_Address: Prefabs/Rooms/Save1
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 735f38402ea347fa381408293503a24e
|
||||
m_Address: Audio/Dispatcher/receiving_an_order1
|
||||
m_ReadOnly: 0
|
||||
@@ -143,11 +178,26 @@ MonoBehaviour:
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 9d78f017876abed4c9cd8957f1e140cb
|
||||
m_Address: Prefabs/Rooms/Level1_2
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: a306df57f348ce7cf900d0b9431739ee
|
||||
m_Address: launch_selectmenu
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: aa138b2e21adfbf4bbbfa5bf9d54b8f2
|
||||
m_Address: Assets/Resources_moved/Audio/UI/buttonclickrelease.wav
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: ae6ab2c88ae248ce1b6efca892f17659
|
||||
m_Address: Assets/Resources_moved/Audio/Music/TestDeath.ogg
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: b2e8dc2aeb0311cd8a826b51cf8e94dc
|
||||
m_Address: GameOver
|
||||
m_ReadOnly: 0
|
||||
@@ -158,16 +208,46 @@ MonoBehaviour:
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: b37ea8c61cc322afdad529d678612d22
|
||||
m_Address: Assets/Resources_moved/Audio/Enemies/zo_attack2.wav
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: bf87bc9ac43df86be8c818de81d44a54
|
||||
m_Address: Assets/Resources_moved/Audio/SFX/pl_step1.wav
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: c566fc932edefbbee9e53271eac3c560
|
||||
m_Address: MainMenu
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: c5a0ad8a615841547ac2ee613af526d8
|
||||
m_Address: Assets/Resources_moved/Audio/SFX/pl_pain2.wav
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: c938de3174f184741925c407a43a47f2
|
||||
m_Address: Prefabs/Rooms/Level1
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: cab4b1ff78dd6b1fba61aa165aa17b4d
|
||||
m_Address: Audio/Dispatcher/receiving_an_order2
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: e3a3840a7963bf841872cddb02e90151
|
||||
m_Address: Prefabs/Levels/MainMenu 1
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: e84e3a3c26ccbd50d92f13627403f148
|
||||
m_Address: Audio/Enemies/rch_walk
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: ebe18293a5ef86704b23dad3a1786476
|
||||
m_Address: Half-Life01
|
||||
m_ReadOnly: 0
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d36aab6707c518f5abfd60065165eb35
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d982316b2b4c99747b9e953ae7b9b42f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,6 +1,9 @@
|
||||
using Code.App.StateMachine;
|
||||
using Code.Audio;
|
||||
using Code.Gameplay.Player;
|
||||
using Code.Input;
|
||||
using Code.Scenes;
|
||||
using Code.Scenes.SceneEnvironments;
|
||||
using Code.StateMachine;
|
||||
using Code.UI;
|
||||
using Cysharp.Threading.Tasks;
|
||||
@@ -30,7 +33,11 @@ namespace Code.App.AppStates
|
||||
Context.InputService.EnableMap(ActionMappings.UI);
|
||||
Context.InputService.DebugBindAction((int)ActionMappings.UI,(int)UIActions.Continue, TryToExit);
|
||||
|
||||
GameOver();
|
||||
Context.AudioService.PlayRandomMusicUntilHumanityWillBeDestroyedForTheySins(MusicType.Death);
|
||||
|
||||
Context.AudioService.ApplyStun(5000,0.5f);
|
||||
|
||||
GameOver().Forget();
|
||||
|
||||
base.EnterState();
|
||||
}
|
||||
@@ -45,7 +52,7 @@ namespace Code.App.AppStates
|
||||
await Context.UIService.AsyncSwitchPanelTo(UIPanel.GameOver);
|
||||
|
||||
_gameOverPanel = (GameOverPanel)Context.UIService.CurrentPanel;
|
||||
|
||||
_gameOverPanel.Show();
|
||||
}
|
||||
|
||||
private void ToMainMenu()
|
||||
@@ -71,6 +78,8 @@ namespace Code.App.AppStates
|
||||
Context.InputService.DisableMap(ActionMappings.UI);
|
||||
Context.InputService.DebugUnbindAction((int)ActionMappings.UI,(int)UIActions.Continue, TryToExit);
|
||||
|
||||
Context.AudioService.GladlyAskToStopMusic(MusicType.Death, callback: Context.AudioFactory.ReleaseDeathMusic);
|
||||
Context.AudioService.TransitToSnapshot(AudioSnapshotState.None);
|
||||
base.ExitState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,12 @@ using Code.StateMachine;
|
||||
using Code.UI;
|
||||
using Code.UI.Panels;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using DG.Tweening;
|
||||
using Reflex.Core;
|
||||
using Reflex.Extensions;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Code.App.AppStates
|
||||
@@ -40,28 +42,20 @@ namespace Code.App.AppStates
|
||||
Context.LoadingManager
|
||||
.RegisterLoading(LoadingWork.LoadScene)
|
||||
.RegisterLoading(LoadingWork.LoadUI)
|
||||
// .RegisterLoading(LoadingWork.LoadModelResource)
|
||||
.RegisterLoading(LoadingWork.LoadModelResource)
|
||||
.RegisterLoading(LoadingWork.LoadAudio);
|
||||
|
||||
//_playerHealth = Context.PlayerFactory.CreatePlayerHealth();
|
||||
|
||||
//_playerHealth.OnDamage += PlayerDamageTaken;
|
||||
//_playerHealth.OnDeath += EndGame;
|
||||
|
||||
Context.AudioService.TransitToSnapshot(AudioSnapshotState.None);
|
||||
|
||||
Context.InputService.EnableMap(ActionMappings.Gameplay);
|
||||
|
||||
Context.InputService.DebugBindAction((int)ActionMappings.Debug, (int)DebugActions.Debug1, InstaKillDEBUG);
|
||||
Context.InputService.DebugBindAction((int)ActionMappings.Debug, (int)DebugActions.Debug4, RoomPassedDEBUG);
|
||||
Context.InputService.DebugBindAction((int)ActionMappings.Debug, (int)DebugActions.Debug5, Tube);
|
||||
Context.InputService.DebugBindAction((int)ActionMappings.Debug, (int)DebugActions.Debug4, TakeGamageDEBUG);
|
||||
|
||||
Context.SceneLoaderService.LoadSceneAsyncAwaitable((int)SceneIds.Gameplay);
|
||||
Context.SceneLoaderService.LoadSceneAsyncAwaitable((int)SceneIds.DevGen);
|
||||
Context.LoadingManager.OnLoadingEnded += AfterSceneLoaded;
|
||||
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
WaitForLoad();
|
||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
WaitForLoad().Forget();
|
||||
}
|
||||
private async UniTask WaitForPlayerCharacterLoad() => _playerCharacter = await Context.PlayerFactory.CreatePlayer();
|
||||
|
||||
@@ -70,8 +64,11 @@ namespace Code.App.AppStates
|
||||
await UniTask.WhenAll(
|
||||
Context.UIService.AsyncSwitchPanelTo(UIPanel.Gameplay),
|
||||
Context.AudioFactory.WarmGameplayMusic(),
|
||||
Context.AudioFactory.WarmDeathMusic(),
|
||||
Context.AudioFactory.WarmSFX(),
|
||||
Context.AudioFactory.WarmDispatcher()
|
||||
Context.AudioFactory.WarmDispatcher(),
|
||||
Context.AudioFactory.WarmEnemies(),
|
||||
Context.AudioFactory.WarmCourier()
|
||||
);
|
||||
|
||||
Context.LoadingManager
|
||||
@@ -91,6 +88,9 @@ namespace Code.App.AppStates
|
||||
Context.LoadingManager.OnLoadingEnded -= AfterSceneLoaded;
|
||||
Context.LoadingManager.OnLoadingEnded += AfterPlayerLoaded;
|
||||
|
||||
Context.PlayerProvider = SceneManager.GetActiveScene().GetSceneContainer().Resolve<IPlayerProvider>();
|
||||
Context.PlayerFactory = SceneManager.GetActiveScene().GetSceneContainer().Resolve<IPlayerFactory>();
|
||||
|
||||
await UniTask.WhenAll(
|
||||
WaitForPlayerArmsToInitialize(),
|
||||
WaitForPlayerCharacterLoad()
|
||||
@@ -112,6 +112,8 @@ namespace Code.App.AppStates
|
||||
|
||||
GameplaySceneEnvironment sceneEnvironment = SceneEnvironmentVariables(sceneContainer);
|
||||
|
||||
_volume = sceneEnvironment.volume;
|
||||
|
||||
PlayerInitialize(sceneEnvironment);
|
||||
|
||||
CameraInitialize();
|
||||
@@ -153,21 +155,30 @@ namespace Code.App.AppStates
|
||||
private void PlayerDamageTaken(int damage, PlayerHealth health)
|
||||
{
|
||||
Context.AudioService.PlayDispatcher((DispatcherSounds)Random.Range((int)DispatcherSounds.TakeDamage1,(int)DispatcherSounds.TakeDamage4));
|
||||
Context.AudioService.PlayCourier((CourierSounds)Random.Range((int)CourierSounds.Damage1,(int)CourierSounds.Damage2));
|
||||
DamageEffectProcess().Forget();
|
||||
}
|
||||
|
||||
// TODO В конфиг
|
||||
private async UniTaskVoid DamageEffectProcess()
|
||||
{
|
||||
_damagePanel.Show();
|
||||
Context.AudioService.ApplyStun(200, 0.5f);
|
||||
|
||||
DOTween.To(() => _volume.weight, x => _volume.weight = x, 1f, 0.5f);
|
||||
await UniTask.WaitForSeconds(3f);
|
||||
DOTween.To(() => _volume.weight, x => _volume.weight = x, 0f, 1f);
|
||||
Context.AudioService.ApplyStun(5000, 1f);
|
||||
_damagePanel.Hide();
|
||||
}
|
||||
// DEBUG
|
||||
private void InstaKillDEBUG(InputAction.CallbackContext context)
|
||||
{
|
||||
_playerHealth.InstaKill();
|
||||
}
|
||||
private void RoomPassedDEBUG(InputAction.CallbackContext context)
|
||||
private void TakeGamageDEBUG(InputAction.CallbackContext context)
|
||||
{
|
||||
_orderService.RoomPassed();
|
||||
}
|
||||
private OrderDispenser _debugTube;
|
||||
|
||||
private void Tube(InputAction.CallbackContext context)
|
||||
{
|
||||
_debugTube.ThrowOrder();
|
||||
_playerHealth.GetDamage(1);
|
||||
}
|
||||
// DEBUG
|
||||
private bool _tickEnabled;
|
||||
@@ -201,13 +212,16 @@ namespace Code.App.AppStates
|
||||
Context.AudioService.OnDispatcherEnded -= _gameplayPanel.CloseDispatcher;
|
||||
|
||||
Context.InputService.DisableMap(ActionMappings.Gameplay);
|
||||
Context.AudioService.GladlyAskToStopMusic(MusicType.Action, callback: Context.AudioFactory.ReleaseActionMusic);
|
||||
Context.AudioService.GladlyAskToStopMusic(MusicType.Peaceful, callback: Context.AudioFactory.ReleasePeacefulMusic);
|
||||
Context.AudioService.GladlyAskToStopMusic(MusicType.Action, time: 0f, callback: Context.AudioFactory.ReleaseActionMusic);
|
||||
Context.AudioService.GladlyAskToStopMusic(MusicType.Peaceful, time: 0f, callback: Context.AudioFactory.ReleasePeacefulMusic);
|
||||
Context.AudioFactory.ReleaseCourier();
|
||||
Context.AudioFactory.ReleaseDispatcher();
|
||||
Context.AudioFactory.ReleaseEnemies();
|
||||
Context.AudioFactory.ReleaseSFX();
|
||||
|
||||
|
||||
Context.InputService.DebugUnbindAction((int)ActionMappings.Debug, (int)DebugActions.Debug1, InstaKillDEBUG);
|
||||
Context.InputService.DebugUnbindAction((int)ActionMappings.Debug, (int)DebugActions.Debug4, RoomPassedDEBUG);
|
||||
Context.InputService.DebugUnbindAction((int)ActionMappings.Debug, (int)DebugActions.Debug5, Tube);
|
||||
Context.InputService.DebugUnbindAction((int)ActionMappings.Debug, (int)DebugActions.Debug4, TakeGamageDEBUG);
|
||||
|
||||
base.ExitState();
|
||||
}
|
||||
@@ -224,13 +238,15 @@ namespace Code.App.AppStates
|
||||
|
||||
private GameplayPanel _gameplayPanel;
|
||||
private ArmsMeshProvider _armsMesh;
|
||||
|
||||
private DamagePanel _damagePanel;
|
||||
private void UIInitialize()
|
||||
{
|
||||
_gameplayPanel = (GameplayPanel)Context.UIService.CurrentPanel;
|
||||
_gameplayPanel.Initialize(_playerScore, _playerHealth, _orderService);
|
||||
Context.AudioService.OnDispatcherStarted += _gameplayPanel.SummonDispatcher;
|
||||
Context.AudioService.OnDispatcherEnded += _gameplayPanel.CloseDispatcher;
|
||||
|
||||
_damagePanel = _gameplayPanel.DamagePanel;
|
||||
}
|
||||
private void MusicInitialize()
|
||||
{
|
||||
@@ -252,11 +268,12 @@ namespace Code.App.AppStates
|
||||
_orderService.OnOrderDelivered += OrderDelivered;
|
||||
_orderService.OnOrderFailure += OrderFailure;
|
||||
}
|
||||
|
||||
private Volume _volume;
|
||||
private GameplaySceneEnvironment SceneEnvironmentVariables(Container sceneContainer)
|
||||
{
|
||||
var sceneEnvironment = (GameplaySceneEnvironment)sceneContainer.Resolve<CurrentSceneEnvironment>();
|
||||
|
||||
_debugTube = sceneEnvironment.debugTube;
|
||||
return sceneEnvironment;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +123,6 @@ namespace Code.App.AppStates
|
||||
Context.AudioService.GladlyAskToStopMusic(MusicType.Menu, callback: Context.AudioFactory.ReleaseMenuMusic);
|
||||
|
||||
Context.AudioFactory.ReleaseAudioTestClips();
|
||||
Context.AudioFactory.ReleaseMenuMusic();
|
||||
base.ExitState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using Code.Gameplay.Camera;
|
||||
using Code.Gameplay.Enemies;
|
||||
using Code.Gameplay.Orders.Order;
|
||||
using Code.Gameplay.Player;
|
||||
using Code.Generator;
|
||||
using Code.Input;
|
||||
using Code.Scenes;
|
||||
using Code.StaticData;
|
||||
@@ -32,11 +33,7 @@ namespace Code.App
|
||||
containerBuilder.AddSingleton(typeof(LoadingManager), typeof(ILoadingManager));
|
||||
|
||||
containerBuilder.AddSingleton(typeof(InputService), typeof(IInputService));
|
||||
// Перенести нахуй в контейнер геймплея
|
||||
containerBuilder.AddSingleton(typeof(PlayerFactory), typeof(IPlayerFactory));
|
||||
containerBuilder.AddSingleton(typeof(EnemyFactory), typeof(IEnemyFactory));
|
||||
containerBuilder.AddSingleton(typeof(PlayerProvider), typeof(IPlayerProvider));
|
||||
//
|
||||
|
||||
InitializeCamera(containerBuilder, staticDataService);
|
||||
|
||||
containerBuilder.AddSingleton(typeof(UIFactory), typeof(IUIFactory));
|
||||
@@ -70,6 +67,7 @@ namespace Code.App
|
||||
containerBuilder.AddSingleton(infrastructureUnit.AddComponent<CameraStateMachine>());
|
||||
}
|
||||
|
||||
// TODO Часть в сцены
|
||||
private void InstallStaticData(ContainerBuilder containerBuilder, out IStaticDataService staticDataService)
|
||||
{
|
||||
staticDataService = new StaticDataService();
|
||||
@@ -96,12 +94,17 @@ namespace Code.App
|
||||
containerBuilder.AddSingleton(staticDataService.SoundtrackListConfig, typeof(SoundtrackListConfig));
|
||||
containerBuilder.AddSingleton(staticDataService.AudioTestClipsConfig, typeof(AudioTestClipsConfig));
|
||||
containerBuilder.AddSingleton(staticDataService.SFXListConfig, typeof(SFXListConfig));
|
||||
containerBuilder.AddSingleton(staticDataService.CourierSoundListConfig, typeof(CourierSoundListConfig));
|
||||
containerBuilder.AddSingleton(staticDataService.DispatcherSoundListConfig, typeof(DispatcherSoundListConfig));
|
||||
containerBuilder.AddSingleton(staticDataService.EnemiesSoundListConfig, typeof(EnemiesSoundListConfig));
|
||||
containerBuilder.AddSingleton(staticDataService.AudioSourceSettingsConfigs, typeof(Dictionary<AudioSourceType, AudioSourceSettingsConfig>));
|
||||
|
||||
containerBuilder.AddSingleton(staticDataService.DefaultAudioSettingsConfig, typeof(DefaultAudioSettingsConfig));
|
||||
|
||||
containerBuilder.AddSingleton(staticDataService.OrderServiceConfig, typeof(OrderServiceConfig));
|
||||
containerBuilder.AddSingleton(staticDataService.OrderBoxConfig, typeof(OrderBoxConfig));
|
||||
|
||||
containerBuilder.AddSingleton(staticDataService.GeneratorConfig, typeof(GeneratorConfig));
|
||||
}
|
||||
|
||||
private AppStateMachine _appStateMachine;
|
||||
@@ -116,9 +119,7 @@ namespace Code.App
|
||||
AttributeInjector.Inject(cameraStateMachine.StateMachineContext, container);
|
||||
cameraStateMachine.Initialize();
|
||||
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
BootstrapFinish(container);
|
||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
BootstrapFinish(container).Forget();
|
||||
}
|
||||
private async UniTaskVoid BootstrapFinish(Container container)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
using Code.App.Loading;
|
||||
using Code.Gameplay.Enemies;
|
||||
using Code.Gameplay.Orders.Order;
|
||||
using Code.Gameplay.Player;
|
||||
using Code.Generator;
|
||||
using Code.Scenes;
|
||||
using Code.Scenes.SceneEnvironments;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Reflex.Core;
|
||||
using UnityEngine;
|
||||
using IPlayerScore = Code.Gameplay.Player.IPlayerScore;
|
||||
@@ -18,6 +21,11 @@ namespace Code.App.SceneInstallers
|
||||
containerBuilder.AddScoped(typeof(GameplaySceneEnvironment), typeof(CurrentSceneEnvironment));
|
||||
containerBuilder.AddScoped(typeof(PlayerScore), typeof(IPlayerScore));
|
||||
containerBuilder.AddScoped(typeof(OrderService), typeof(IOrderService));
|
||||
containerBuilder.AddScoped(typeof(RoomGeneratorFactory), typeof(IRoomGeneratorFactory));
|
||||
containerBuilder.AddScoped(typeof(PlayerProvider), typeof(IPlayerProvider));
|
||||
containerBuilder.AddScoped(typeof(PlayerFactory), typeof(IPlayerFactory));
|
||||
containerBuilder.AddScoped(typeof(EnemyFactory), typeof(IEnemyFactory));
|
||||
containerBuilder.AddScoped(typeof(RoomGenerator));
|
||||
|
||||
containerBuilder.OnContainerBuilt += Initialize;
|
||||
}
|
||||
@@ -32,6 +40,17 @@ namespace Code.App.SceneInstallers
|
||||
|
||||
loadingManager
|
||||
.UnregisterLoading(LoadingWork.LoadScene);
|
||||
|
||||
LoadRooms(container,loadingManager).Forget();
|
||||
}
|
||||
|
||||
private async UniTaskVoid LoadRooms(Container container, ILoadingManager loadingManager)
|
||||
{
|
||||
await container.Resolve<IRoomGeneratorFactory>().PreloadRooms(container.Resolve<IOrderService>());
|
||||
|
||||
container.Resolve<RoomGenerator>().Initialize();
|
||||
|
||||
loadingManager.UnregisterLoading(LoadingWork.LoadModelResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using Code.Audio;
|
||||
using Code.Gameplay.Camera;
|
||||
using Code.Gameplay.Enemies;
|
||||
using Code.Gameplay.Player;
|
||||
using Code.Generator;
|
||||
using Code.Input;
|
||||
using Code.Scenes;
|
||||
using Code.UI;
|
||||
@@ -18,10 +19,10 @@ namespace Code.App.StateMachine
|
||||
[Inject] public AppStateMachine StateMachine { get; private set; }
|
||||
[Inject] public CameraStateMachine CameraStateMachine { get; private set; }
|
||||
[Inject] public IUIService UIService { get; private set; }
|
||||
[Inject] public IPlayerFactory PlayerFactory { get; private set; }
|
||||
[Inject] public IPlayerProvider PlayerProvider { get; private set; }
|
||||
[Inject] public IAudioFactory AudioFactory { get; private set; }
|
||||
[Inject] public IAudioService AudioService { get; private set; }
|
||||
[Inject] public IEnemyFactory EnemyFactory { get; private set; }
|
||||
/*[Inject]*/public IPlayerFactory PlayerFactory { get; set; }
|
||||
/*[Inject]*/public IPlayerProvider PlayerProvider { get; set; }
|
||||
// [Inject] public IEnemyFactory EnemyFactory { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,10 @@ namespace Code.Audio
|
||||
}
|
||||
public enum EnemiesSounds
|
||||
{
|
||||
Bastard,
|
||||
Bravo
|
||||
GrandpaAttack,
|
||||
RoachAttack,
|
||||
RoachStep,
|
||||
GrandpaStep
|
||||
}
|
||||
public enum DispatcherSounds
|
||||
{
|
||||
@@ -28,4 +30,10 @@ namespace Code.Audio
|
||||
Late4,
|
||||
Late5
|
||||
}
|
||||
public enum CourierSounds
|
||||
{
|
||||
Step,
|
||||
Damage1,
|
||||
Damage2
|
||||
}
|
||||
}
|
||||
@@ -19,24 +19,28 @@ namespace Code.Audio
|
||||
private AssetReference[] _audioTestClipsReferences;
|
||||
private AssetReference[] _peacefulSoundtrack;
|
||||
private AssetReference[] _actionSoundtrack;
|
||||
private AssetReference[] _deathSoundtrack;
|
||||
private AssetReference[] _menuSoundtrack;
|
||||
private AssetReference[] _SFX;
|
||||
private AssetReference[] _enemies;
|
||||
private AssetReference[] _dispatcher;
|
||||
private AssetReference[] _character;
|
||||
private AssetReference[] _courier;
|
||||
|
||||
private AsyncOperationHandle<IList<AudioClip>> _audioTestClipsHandle;
|
||||
private AsyncOperationHandle<IList<AudioClip>> _menuMusicHandle;
|
||||
private AsyncOperationHandle<IList<AudioClip>> _deathMusicHandle;
|
||||
private AsyncOperationHandle<IList<AudioClip>> _actionMusicHandle;
|
||||
private AsyncOperationHandle<IList<AudioClip>> _peacefulMusicHandle;
|
||||
private AsyncOperationHandle<IList<AudioClip>> _SFXHandle;
|
||||
private AsyncOperationHandle<IList<AudioClip>> _enemiesHandle;
|
||||
private AsyncOperationHandle<IList<AudioClip>> _dispatcherHandle;
|
||||
private AsyncOperationHandle<IList<AudioClip>> _courierHandle;
|
||||
|
||||
public Dictionary<AudioType, AudioClip> AudioTestClips { get; private set; } = new();
|
||||
public Dictionary<MusicType, List<AudioClip>> MusicDictionary { get; private set; } = new();
|
||||
public List<AudioClip> SFXAudios { get; private set; } = new();
|
||||
public List<AudioClip> EnemiesAudios { get; private set; } = new();
|
||||
public List<AudioClip> CourierAudios { get; private set; } = new();
|
||||
public List<AudioClip> DispatcherAudios { get; private set; } = new();
|
||||
|
||||
public AudioFactory(AudioMixerConfig audioMixerConfig,
|
||||
@@ -44,7 +48,8 @@ namespace Code.Audio
|
||||
SFXListConfig sfxListConfig,
|
||||
EnemiesSoundListConfig enemiesSoundListConfig,
|
||||
DispatcherSoundListConfig dispatcherSoundListConfig,
|
||||
AudioTestClipsConfig audioTestClipsConfig
|
||||
AudioTestClipsConfig audioTestClipsConfig,
|
||||
CourierSoundListConfig courierSoundListConfig
|
||||
)
|
||||
{
|
||||
AudioMixer = audioMixerConfig.audioMixerAsset;
|
||||
@@ -52,15 +57,18 @@ namespace Code.Audio
|
||||
|
||||
_peacefulSoundtrack = soundtrackListConfig.peacefulSoundtrack;
|
||||
_actionSoundtrack = soundtrackListConfig.actionSoundtrack;
|
||||
_deathSoundtrack = soundtrackListConfig.deathSoundtrack;
|
||||
_menuSoundtrack = soundtrackListConfig.menuSoundtrack;
|
||||
_SFX = sfxListConfig.SFX;
|
||||
_enemies = enemiesSoundListConfig.enemies;
|
||||
_dispatcher = dispatcherSoundListConfig.dispatcher;
|
||||
_courier = courierSoundListConfig.courierSounds;
|
||||
_audioTestClipsReferences = audioTestClipsConfig.audioTestClips;
|
||||
|
||||
MusicDictionary.Add(MusicType.Menu, new ());
|
||||
MusicDictionary.Add(MusicType.Peaceful, new ());
|
||||
MusicDictionary.Add(MusicType.Death, new ());
|
||||
MusicDictionary.Add(MusicType.Action, new ());
|
||||
MusicDictionary.Add(MusicType.Peaceful, new ());
|
||||
}
|
||||
|
||||
public async UniTask LoadAudioSourcePrefab(Action<GameObject> callback) =>
|
||||
@@ -112,6 +120,16 @@ namespace Code.Audio
|
||||
// foreach (var assetReference in _menuSoundtrack) assetReference.ReleaseAsset();
|
||||
_menuMusicHandle.Release();
|
||||
}
|
||||
public async UniTask WarmDeathMusic()
|
||||
{
|
||||
_deathMusicHandle = Addressables.LoadAssetsAsync<AudioClip>(_deathSoundtrack, OnDeathTrackLoaded, Addressables.MergeMode.Union);
|
||||
await _deathMusicHandle.ToUniTask();
|
||||
}
|
||||
public void ReleaseDeathMusic()
|
||||
{
|
||||
MusicDictionary[MusicType.Death].Clear();
|
||||
_deathMusicHandle.Release();
|
||||
}
|
||||
public async UniTask WarmSFX( )
|
||||
{
|
||||
_SFXHandle = Addressables.LoadAssetsAsync<AudioClip>(_SFX, OnSFXLoaded, Addressables.MergeMode.Union);
|
||||
@@ -137,6 +155,18 @@ namespace Code.Audio
|
||||
EnemiesAudios.Clear();
|
||||
_enemiesHandle.Release();
|
||||
}
|
||||
public async UniTask WarmCourier()
|
||||
{
|
||||
_courierHandle = Addressables.LoadAssetsAsync<AudioClip>(_courier, OnCourierLoaded, Addressables.MergeMode.Union);
|
||||
|
||||
await _courierHandle.ToUniTask();
|
||||
}
|
||||
|
||||
public void ReleaseCourier()
|
||||
{
|
||||
CourierAudios.Clear();
|
||||
_courierHandle.Release();
|
||||
}
|
||||
|
||||
public async UniTask WarmDispatcher( )
|
||||
{
|
||||
@@ -156,6 +186,10 @@ namespace Code.Audio
|
||||
{
|
||||
MusicDictionary[MusicType.Menu].Add(audioClip);
|
||||
}
|
||||
private void OnDeathTrackLoaded(AudioClip audioClip)
|
||||
{
|
||||
MusicDictionary[MusicType.Death].Add(audioClip);
|
||||
}
|
||||
|
||||
// private int _audioTestClipCounter;
|
||||
private void OnAudioTestClipLoaded(AudioClip audioClip)
|
||||
@@ -182,5 +216,9 @@ namespace Code.Audio
|
||||
{
|
||||
DispatcherAudios.Add(audioClip);
|
||||
}
|
||||
private void OnCourierLoaded(AudioClip audioClip)
|
||||
{
|
||||
CourierAudios.Add(audioClip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,134 +22,104 @@ namespace Code.Audio
|
||||
private AudioSource _actionMusicSource;
|
||||
private AudioSource _peacefulMusicSource;
|
||||
|
||||
private AudioMixerGroup _masterGroup,
|
||||
// _musicGroup,
|
||||
_actionMusicGroup,
|
||||
_menuMusicGroup,
|
||||
_peacefulMusicGroup,
|
||||
_SFXGroup,
|
||||
_creaturesGroup,
|
||||
_dispatcherGroup,
|
||||
_courierGroup,
|
||||
_enemiesGroup;
|
||||
|
||||
private Dictionary<AudioType, AudioMixerGroup> _audioMixerGroups = new();
|
||||
private readonly AudioSourcePool _audioSourcePool;
|
||||
|
||||
private Dictionary<AudioSnapshotState, AudioMixerSnapshot> _snapshots = new();
|
||||
// Юнити не может - говнокод поможет.
|
||||
private Dictionary<AudioSnapshotState, Dictionary<AudioType, float>> _snapshotsVolumes = new();
|
||||
private Dictionary<AudioSourceType, AudioSourceSettingsConfig> _settings;
|
||||
|
||||
public AudioService(IAudioFactory audioFactory, Dictionary<AudioSourceType, AudioSourceSettingsConfig> settings)
|
||||
public AudioService(IAudioFactory audioFactory,
|
||||
Dictionary<AudioSourceType, AudioSourceSettingsConfig> settings,
|
||||
DefaultAudioSettingsConfig defaultAudioSettingsConfig)
|
||||
{
|
||||
_audioFactory = audioFactory;
|
||||
_audioSourcePool = new(settings);
|
||||
_settings = settings;
|
||||
|
||||
_snapshotsVolumes.Add(AudioSnapshotState.None,defaultAudioSettingsConfig.noneVolume);
|
||||
_snapshotsVolumes.Add(AudioSnapshotState.Menu,defaultAudioSettingsConfig.menuVolume);
|
||||
_snapshotsVolumes.Add(AudioSnapshotState.Action,defaultAudioSettingsConfig.actionVolume);
|
||||
_snapshotsVolumes.Add(AudioSnapshotState.Peaceful,defaultAudioSettingsConfig.peacefulVolume);
|
||||
}
|
||||
|
||||
// TODO Грязно, убрать снапшоты НАХУЙ
|
||||
public float GetSetting(AudioType type)
|
||||
{
|
||||
float value;
|
||||
switch (type)
|
||||
{
|
||||
case AudioType.SFX:
|
||||
_snapshots[AudioSnapshotState.Peaceful].audioMixer.GetFloat(_SFXGroup.name, out value);
|
||||
break;
|
||||
case AudioType.Master:
|
||||
_snapshots[AudioSnapshotState.Menu].audioMixer.GetFloat(_masterGroup.name, out value);
|
||||
break;
|
||||
case AudioType.Creatures:
|
||||
_snapshots[AudioSnapshotState.Peaceful].audioMixer.GetFloat(_creaturesGroup.name, out value);
|
||||
break;
|
||||
case AudioType.GameplayMusic:
|
||||
_snapshots[AudioSnapshotState.Peaceful].audioMixer.GetFloat(_peacefulMusicGroup.name, out value);
|
||||
break;
|
||||
case AudioType.MenuMusic:
|
||||
_snapshots[AudioSnapshotState.Menu].audioMixer.GetFloat(_menuMusicGroup.name, out value);
|
||||
break;
|
||||
case AudioType.DispatcherSounds:
|
||||
_snapshots[AudioSnapshotState.Action].audioMixer.GetFloat(_dispatcherGroup.name, out value);
|
||||
break;
|
||||
default:
|
||||
value = 1;
|
||||
break;
|
||||
}
|
||||
_mixer.GetFloat(_audioMixerGroups[type].name, out float value);
|
||||
|
||||
value = Mathf.Pow(10f, value / 20);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// TODO Грязно, убрать снапшоты НАХУЙ
|
||||
public void ChangeSetting(AudioType type, float value)
|
||||
{
|
||||
float volume = Mathf.Log10(value) * 20;
|
||||
switch (type)
|
||||
{
|
||||
case AudioType.SFX:
|
||||
_snapshots[AudioSnapshotState.Peaceful].audioMixer.SetFloat(_SFXGroup.name, volume);
|
||||
_snapshots[AudioSnapshotState.Action].audioMixer.SetFloat(_SFXGroup.name, volume);
|
||||
break;
|
||||
case AudioType.DeathMusic:
|
||||
case AudioType.Master:
|
||||
_snapshots[AudioSnapshotState.Menu].audioMixer.SetFloat(_masterGroup.name, volume);
|
||||
_snapshots[AudioSnapshotState.Peaceful].audioMixer.SetFloat(_masterGroup.name, volume);
|
||||
_snapshots[AudioSnapshotState.Action].audioMixer.SetFloat(_masterGroup.name, volume);
|
||||
_snapshotsVolumes[AudioSnapshotState.Menu][type] = value;
|
||||
_snapshotsVolumes[AudioSnapshotState.Action][type] = value;
|
||||
_snapshotsVolumes[AudioSnapshotState.Peaceful][type] = value;
|
||||
_mixer.SetFloat(_audioMixerGroups[type].name, volume);
|
||||
break;
|
||||
case AudioType.Creatures:
|
||||
_snapshots[AudioSnapshotState.Peaceful].audioMixer.SetFloat(_creaturesGroup.name, volume);
|
||||
_snapshots[AudioSnapshotState.Action].audioMixer.SetFloat(_creaturesGroup.name, volume);
|
||||
case AudioType.ActionMusic:
|
||||
_snapshotsVolumes[AudioSnapshotState.Action][type] = value;
|
||||
_mixer.SetFloat(_audioMixerGroups[type].name, volume);
|
||||
break;
|
||||
case AudioType.GameplayMusic:
|
||||
_snapshots[AudioSnapshotState.Peaceful].audioMixer.SetFloat(_peacefulMusicGroup.name, volume);
|
||||
_snapshots[AudioSnapshotState.Action].audioMixer.SetFloat(_actionMusicGroup.name, volume);
|
||||
case AudioType.PeacefulMusic:
|
||||
_snapshotsVolumes[AudioSnapshotState.Peaceful][type] = value;
|
||||
_mixer.SetFloat(_audioMixerGroups[type].name, volume);
|
||||
break;
|
||||
case AudioType.MenuMusic:
|
||||
_snapshots[AudioSnapshotState.Menu].audioMixer.SetFloat(_menuMusicGroup.name, volume);
|
||||
_snapshotsVolumes[AudioSnapshotState.Menu][type] = value;
|
||||
_mixer.SetFloat(_audioMixerGroups[type].name, volume);
|
||||
break;
|
||||
case AudioType.DispatcherSounds:
|
||||
_snapshots[AudioSnapshotState.Peaceful].audioMixer.SetFloat(_dispatcherGroup.name, volume);
|
||||
_snapshots[AudioSnapshotState.Action].audioMixer.SetFloat(_dispatcherGroup.name, volume);
|
||||
case AudioType.SFX:
|
||||
case AudioType.Dispatcher:
|
||||
case AudioType.Courier:
|
||||
case AudioType.Enemies:
|
||||
_snapshotsVolumes[AudioSnapshotState.Action][type] = value;
|
||||
_snapshotsVolumes[AudioSnapshotState.Peaceful][type] = value;
|
||||
_mixer.SetFloat(_audioMixerGroups[type].name, volume);
|
||||
break;
|
||||
}
|
||||
// _mixer.FindSnapshot("Action").audioMixer.SetFloat("music", volume);
|
||||
}
|
||||
|
||||
public async UniTask Initialize()
|
||||
{
|
||||
// _mixer = await _audioFactory.CreateMixer();
|
||||
_mixer = _audioFactory.AudioMixer;
|
||||
|
||||
_masterGroup = _mixer.FindMatchingGroups(AudioGroups.MasterGroup)[0];
|
||||
_menuMusicGroup = _mixer.FindMatchingGroups(AudioGroups.MenuMusicGroup)[0];
|
||||
_actionMusicGroup = _mixer.FindMatchingGroups(AudioGroups.ActionMusicGroup)[0];
|
||||
_peacefulMusicGroup = _mixer.FindMatchingGroups(AudioGroups.PeacefulMusicGroup)[0];
|
||||
// _musicGroup = _mixer.FindMatchingGroups(AudioGroups.MusicGroup)[0];
|
||||
_musicAudioGroups.Add(MusicType.Menu, _mixer.FindMatchingGroups(AudioGroups.MenuMusicGroup)[0]);
|
||||
_musicAudioGroups.Add(MusicType.Death, _mixer.FindMatchingGroups(AudioGroups.DeathMusicGroup)[0]);
|
||||
_musicAudioGroups.Add(MusicType.Action, _mixer.FindMatchingGroups(AudioGroups.ActionMusicGroup)[0]);
|
||||
_musicAudioGroups.Add(MusicType.Peaceful, _mixer.FindMatchingGroups(AudioGroups.PeacefulMusicGroup)[0]);
|
||||
|
||||
_cancellationTokenSources.Add(MusicType.Menu, new());
|
||||
_cancellationTokenSources.Add(MusicType.Death, new());
|
||||
_cancellationTokenSources.Add(MusicType.Action, new());
|
||||
_cancellationTokenSources.Add(MusicType.Peaceful, new());
|
||||
|
||||
_musicAudioSources.Add(MusicType.Menu, null);
|
||||
_musicAudioSources.Add(MusicType.Death, null);
|
||||
_musicAudioSources.Add(MusicType.Action, null);
|
||||
_musicAudioSources.Add(MusicType.Peaceful, null);
|
||||
|
||||
_SFXGroup = _mixer.FindMatchingGroups(AudioGroups.SFXGroup)[0];
|
||||
_creaturesGroup = _mixer.FindMatchingGroups(AudioGroups.CreaturesGroup)[0];
|
||||
_dispatcherGroup = _mixer.FindMatchingGroups(AudioGroups.DispatcherMusicGroup)[0];
|
||||
_courierGroup = _mixer.FindMatchingGroups(AudioGroups.CourierMusicGroup)[0];
|
||||
_enemiesGroup = _mixer.FindMatchingGroups(AudioGroups.EnemiesMusicGroup)[0];
|
||||
_audioMixerGroups.Add(AudioType.Master, _mixer.FindMatchingGroups(AudioGroups.MasterGroup)[0]);
|
||||
_audioMixerGroups.Add(AudioType.SFX, _mixer.FindMatchingGroups(AudioGroups.SFXGroup)[0]);
|
||||
_audioMixerGroups.Add(AudioType.Dispatcher, _mixer.FindMatchingGroups(AudioGroups.DispatcherMusicGroup)[0]);
|
||||
_audioMixerGroups.Add(AudioType.Courier, _mixer.FindMatchingGroups(AudioGroups.CourierGroup)[0]);
|
||||
_audioMixerGroups.Add(AudioType.Enemies, _mixer.FindMatchingGroups(AudioGroups.EnemiesGroup)[0]);
|
||||
_audioMixerGroups.Add(AudioType.MenuMusic, _musicAudioGroups[MusicType.Menu]);
|
||||
_audioMixerGroups.Add(AudioType.DeathMusic, _musicAudioGroups[MusicType.Death]);
|
||||
_audioMixerGroups.Add(AudioType.ActionMusic, _musicAudioGroups[MusicType.Action]);
|
||||
_audioMixerGroups.Add(AudioType.PeacefulMusic, _musicAudioGroups[MusicType.Peaceful]);
|
||||
|
||||
_snapshots[AudioSnapshotState.None] = _mixer.FindSnapshot(AudioGroups.NoneSnapshot);
|
||||
_snapshots[AudioSnapshotState.Peaceful] = _mixer.FindSnapshot(AudioGroups.PeacefulSnapshot);
|
||||
_snapshots[AudioSnapshotState.Action] = _mixer.FindSnapshot(AudioGroups.ActionSnapshot);
|
||||
_snapshots[AudioSnapshotState.Menu] = _mixer.FindSnapshot(AudioGroups.MenuSnapshot);
|
||||
|
||||
await _audioFactory.LoadAudioSourcePrefab(_audioSourcePool.Initialize);
|
||||
}
|
||||
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
private Dictionary<MusicType, CancellationTokenSource> _cancellationTokenSources = new();
|
||||
private Dictionary<MusicType, AudioSource> _musicAudioSources = new();
|
||||
private Dictionary<MusicType, AudioMixerGroup> _musicAudioGroups = new();
|
||||
@@ -169,19 +139,13 @@ namespace Code.Audio
|
||||
|
||||
_musicAudioSources[musicType].Play();
|
||||
|
||||
// await UniTask.WaitUntilValueChanged(_musicAudioSources[musicType],
|
||||
// _ => !_musicAudioSources[musicType].isPlaying,
|
||||
// cancellationToken: _cancellationTokenSources[musicType].Token);
|
||||
await UniTask.NextFrame();
|
||||
// Debug.Log($"Playing {musicType}");
|
||||
var (isCanceled, _) = await UniTask.WaitUntilValueChanged(_musicAudioSources[musicType],
|
||||
_ => !_musicAudioSources[musicType].isPlaying,
|
||||
cancellationToken: _cancellationTokenSources[musicType].Token).SuppressCancellationThrow();
|
||||
// Debug.Log($"Finished {musicType}");
|
||||
|
||||
Debug.LogError("Music skipping");
|
||||
if (isCanceled)
|
||||
{
|
||||
// Debug.Log($"Cancelled {musicType}");
|
||||
_cancellationTokenSources[musicType].Dispose();
|
||||
_cancellationTokenSources[musicType] = new();
|
||||
|
||||
@@ -191,13 +155,13 @@ namespace Code.Audio
|
||||
return;
|
||||
}
|
||||
|
||||
PlayRandomMusicUntilHumanityWillBeDestroyedForTheySins(musicType);
|
||||
PlayRandomMusicUntilHumanityWillBeDestroyedForTheySins(musicType).Forget();
|
||||
}
|
||||
|
||||
public async UniTaskVoid GladlyAskToStopMusic(MusicType musicType,
|
||||
AudioSnapshotState audioSnapshotState = AudioSnapshotState.None, float time = 1f, Action callback = null)
|
||||
{
|
||||
TransitToSnapshot(audioSnapshotState, time);
|
||||
//TransitToSnapshot(audioSnapshotState, time);
|
||||
|
||||
await UniTask.WaitForSeconds(time);
|
||||
|
||||
@@ -205,39 +169,56 @@ namespace Code.Audio
|
||||
|
||||
callback?.Invoke();
|
||||
}
|
||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
|
||||
public void StopMusic()
|
||||
{
|
||||
_peacefulMusicSource.Stop();
|
||||
_actionMusicSource.Stop();
|
||||
_cancellationTokenSources[MusicType.Peaceful].Cancel();
|
||||
_cancellationTokenSources[MusicType.Action].Cancel();
|
||||
}
|
||||
|
||||
public void GladlyAskToStopMusic(Action callback = null)
|
||||
{
|
||||
TransitToSnapshot(AudioSnapshotState.None);
|
||||
// TransitToSnapshot(AudioSnapshotState.None);
|
||||
_peacefulMusicSource.Stop();
|
||||
_actionMusicSource.Stop();
|
||||
|
||||
callback?.Invoke();
|
||||
}
|
||||
|
||||
public void TransitToSnapshot(AudioSnapshotState state, float time = 1f)
|
||||
public void TransitToSnapshot(AudioSnapshotState state, float time = 1)
|
||||
{
|
||||
_snapshots[state].TransitionTo(time);
|
||||
foreach (var key in _audioMixerGroups.Keys)
|
||||
_mixer.DOSetFloat(_audioMixerGroups[key].name, Mathf.Log10(_snapshotsVolumes[state][key]) * 20, time);
|
||||
}
|
||||
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
|
||||
public void PlaySFX(SFXSounds sfxId, Vector3 position)
|
||||
{
|
||||
_audioSourcePool.PlayOneShot(_audioFactory.SFXAudios[(int)sfxId], position, _SFXGroup);
|
||||
_audioSourcePool
|
||||
.PlayOneShot(_audioFactory.SFXAudios[(int)sfxId], position, _audioMixerGroups[AudioType.SFX]).Forget();
|
||||
}
|
||||
public void ApplyStun(float value, float time)
|
||||
{
|
||||
_mixer.DOSetFloat("Stun", value, time);
|
||||
}
|
||||
|
||||
public void PlayEnemy(EnemiesSounds enemySoundId, Vector3 position)
|
||||
{
|
||||
_audioSourcePool.PlayOneShot(_audioFactory.EnemiesAudios[(int)enemySoundId], position, _enemiesGroup);
|
||||
_audioSourcePool.PlayOneShot(_audioFactory.EnemiesAudios[(int)enemySoundId], position,
|
||||
_audioMixerGroups[AudioType.Enemies]).Forget();
|
||||
}
|
||||
|
||||
public AudioSource GetSourceOfGroup(AudioType group)
|
||||
{
|
||||
AudioSource source = _audioSourcePool.GetSource();
|
||||
source.outputAudioMixerGroup = _audioMixerGroups[group];
|
||||
return source;
|
||||
}
|
||||
|
||||
public void ReleaseSourceOfGroup(AudioSource source) => _audioSourcePool.ReleaseSource(source);
|
||||
|
||||
// Чинить долго и дорого пусть Артёмов будет много, ведь он наш друг
|
||||
public event IAudioService.OnAudioPlayingDelegate OnDispatcherStarted;
|
||||
public event IAudioService.OnAudioPlayingDelegate OnDispatcherEnded;
|
||||
@@ -245,108 +226,35 @@ namespace Code.Audio
|
||||
public void PlayDispatcher(DispatcherSounds dispatcherSoundId)
|
||||
{
|
||||
OnDispatcherStarted?.Invoke();
|
||||
_audioSourcePool.PlayOneShot(_audioFactory.DispatcherAudios[(int)dispatcherSoundId], _dispatcherGroup,
|
||||
AudioSourceType.NoBlend, () => OnDispatcherEnded?.Invoke());
|
||||
_audioSourcePool.PlayOneShot(_audioFactory.DispatcherAudios[(int)dispatcherSoundId],
|
||||
_audioMixerGroups[AudioType.Dispatcher],
|
||||
AudioSourceType.NoBlend, () => OnDispatcherEnded?.Invoke()).Forget();
|
||||
}
|
||||
|
||||
public void PlayCourier(CourierSounds courierSounds)
|
||||
{
|
||||
_audioSourcePool.PlayOneShot(_audioFactory.CourierAudios[(int)courierSounds],
|
||||
_audioMixerGroups[AudioType.Courier],
|
||||
AudioSourceType.NoBlend).Forget();
|
||||
}
|
||||
private CancellationTokenSource _testClipCancellationTokenSource = new();
|
||||
private void ResetCurrentTestAudioSource() => _currentTestClipAudioType = AudioType.Master;
|
||||
|
||||
private AudioType _currentTestClipAudioType;
|
||||
|
||||
// TODO Засунуть в словарь
|
||||
public void PlayTestClip(AudioType audioType)
|
||||
{
|
||||
if(_currentTestClipAudioType == audioType) return;
|
||||
if (_currentTestClipAudioType == audioType) return;
|
||||
|
||||
_testClipCancellationTokenSource.Cancel();
|
||||
_testClipCancellationTokenSource = new();
|
||||
|
||||
_currentTestClipAudioType = audioType;
|
||||
|
||||
switch (audioType)
|
||||
{
|
||||
case AudioType.SFX:
|
||||
_audioSourcePool.PlayOneShot(_audioFactory.AudioTestClips[audioType],
|
||||
_SFXGroup, _testClipCancellationTokenSource,
|
||||
AudioSourceType.NoBlend, ResetCurrentTestAudioSource);
|
||||
break;
|
||||
case AudioType.Master:
|
||||
_audioSourcePool.PlayOneShot(_audioFactory.AudioTestClips[audioType],
|
||||
_masterGroup, _testClipCancellationTokenSource,
|
||||
AudioSourceType.NoBlend, ResetCurrentTestAudioSource);
|
||||
break;
|
||||
case AudioType.Creatures:
|
||||
_audioSourcePool.PlayOneShot( _audioFactory.AudioTestClips[audioType],
|
||||
_creaturesGroup, _testClipCancellationTokenSource,
|
||||
AudioSourceType.NoBlend, ResetCurrentTestAudioSource);
|
||||
break;
|
||||
case AudioType.GameplayMusic:
|
||||
_audioSourcePool.PlayOneShot(_audioFactory.AudioTestClips[audioType],
|
||||
_actionMusicGroup, _testClipCancellationTokenSource,
|
||||
AudioSourceType.NoBlend, ResetCurrentTestAudioSource);
|
||||
break;
|
||||
case AudioType.MenuMusic:
|
||||
_audioSourcePool.PlayOneShot(_audioFactory.AudioTestClips[audioType],
|
||||
_menuMusicGroup, _testClipCancellationTokenSource,
|
||||
AudioSourceType.NoBlend, ResetCurrentTestAudioSource);
|
||||
break;
|
||||
case AudioType.DispatcherSounds:
|
||||
_audioSourcePool.PlayOneShot(_audioFactory.AudioTestClips[audioType],
|
||||
_dispatcherGroup, _testClipCancellationTokenSource,
|
||||
AudioSourceType.NoBlend, ResetCurrentTestAudioSource);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private AudioSource _testClipAudioSource;
|
||||
private AudioType _currentTestClipAudioType;
|
||||
|
||||
// Эффективно и просто, может не так хитровыебано
|
||||
private void ReleaseTestAudioClipSource()
|
||||
{
|
||||
_testClipAudioSource = null;
|
||||
}
|
||||
|
||||
// TODO Засунуть в словарь
|
||||
public void PlayTestClipDeprecated(AudioType audioType)
|
||||
{
|
||||
if (!_testClipAudioSource) _testClipAudioSource = _audioSourcePool.GetSource();
|
||||
else if (_currentTestClipAudioType != audioType) _testClipAudioSource.Stop();
|
||||
else return;
|
||||
|
||||
_currentTestClipAudioType = audioType;
|
||||
|
||||
switch (audioType)
|
||||
{
|
||||
case AudioType.SFX:
|
||||
_audioSourcePool.PlayOneShot(_testClipAudioSource, _audioFactory.AudioTestClips[audioType],
|
||||
_SFXGroup,
|
||||
AudioSourceType.NoBlend, ReleaseTestAudioClipSource);
|
||||
break;
|
||||
case AudioType.Master:
|
||||
_audioSourcePool.PlayOneShot(_testClipAudioSource, _audioFactory.AudioTestClips[audioType],
|
||||
_masterGroup,
|
||||
AudioSourceType.NoBlend, ReleaseTestAudioClipSource);
|
||||
break;
|
||||
case AudioType.Creatures:
|
||||
_audioSourcePool.PlayOneShot(_testClipAudioSource, _audioFactory.AudioTestClips[audioType],
|
||||
_creaturesGroup,
|
||||
AudioSourceType.NoBlend, ReleaseTestAudioClipSource);
|
||||
break;
|
||||
case AudioType.GameplayMusic:
|
||||
_audioSourcePool.PlayOneShot(_testClipAudioSource, _audioFactory.AudioTestClips[audioType],
|
||||
_actionMusicGroup,
|
||||
AudioSourceType.NoBlend, ReleaseTestAudioClipSource);
|
||||
break;
|
||||
case AudioType.MenuMusic:
|
||||
_audioSourcePool.PlayOneShot(_testClipAudioSource, _audioFactory.AudioTestClips[audioType],
|
||||
_menuMusicGroup,
|
||||
AudioSourceType.NoBlend, ReleaseTestAudioClipSource);
|
||||
break;
|
||||
case AudioType.DispatcherSounds:
|
||||
_audioSourcePool.PlayOneShot(_testClipAudioSource, _audioFactory.AudioTestClips[audioType],
|
||||
_dispatcherGroup,
|
||||
AudioSourceType.NoBlend, ReleaseTestAudioClipSource);
|
||||
break;
|
||||
}
|
||||
_audioSourcePool.PlayOneShot(_audioFactory.AudioTestClips[audioType],
|
||||
_audioMixerGroups[audioType], _testClipCancellationTokenSource,
|
||||
AudioSourceType.NoBlend, ResetCurrentTestAudioSource).Forget();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ namespace Code.Audio
|
||||
List<AudioClip> SFXAudios { get; }
|
||||
List<AudioClip> EnemiesAudios { get; }
|
||||
List<AudioClip> DispatcherAudios { get; }
|
||||
List<AudioClip> CourierAudios { get; }
|
||||
UniTask LoadAudioSourcePrefab(Action<GameObject> callback);
|
||||
UniTask WarmGameplayMusic( );
|
||||
void ReleaseActionMusic();
|
||||
@@ -28,5 +29,9 @@ namespace Code.Audio
|
||||
void ReleaseEnemies();
|
||||
UniTask WarmDispatcher( );
|
||||
void ReleaseDispatcher();
|
||||
UniTask WarmCourier();
|
||||
void ReleaseCourier();
|
||||
UniTask WarmDeathMusic( );
|
||||
void ReleaseDeathMusic();
|
||||
}
|
||||
}
|
||||
@@ -23,5 +23,9 @@ namespace Code.Audio
|
||||
void ChangeSetting(AudioType type, float value);
|
||||
float GetSetting(AudioType type);
|
||||
void PlayTestClip(AudioType audioType);
|
||||
AudioSource GetSourceOfGroup(AudioType group);
|
||||
void ReleaseSourceOfGroup(AudioSource source);
|
||||
void PlayCourier(CourierSounds range);
|
||||
void ApplyStun(float value, float time);
|
||||
}
|
||||
}
|
||||
@@ -4,15 +4,19 @@ namespace Code.Audio
|
||||
{
|
||||
Menu,
|
||||
Peaceful,
|
||||
Action
|
||||
Action,
|
||||
Death
|
||||
}
|
||||
public enum AudioType
|
||||
{
|
||||
Master,
|
||||
MenuMusic,
|
||||
GameplayMusic,
|
||||
Creatures,
|
||||
DispatcherSounds,
|
||||
SFX
|
||||
Dispatcher,
|
||||
SFX,
|
||||
Courier,
|
||||
Enemies,
|
||||
ActionMusic,
|
||||
PeacefulMusic,
|
||||
DeathMusic
|
||||
}
|
||||
}
|
||||
@@ -23,17 +23,11 @@ namespace Code.Configs
|
||||
slideDuration = 0.8f, // Длительность слайда в секундах
|
||||
slideCooldown = 1.5f; // Время перезарядки слайда в секундах
|
||||
|
||||
// Залазание на стены
|
||||
public float
|
||||
wallClimbSpeedFactor = 0.8f, // Коэффициент преобразования горизонтальной скорости в вертикальную при залазании на стену
|
||||
minWallClimbSpeed = 9f, // Минимальная горизонтальная скорость для начала залазания на стену
|
||||
wallDetectionAngleThreshold = 80f; // Максимальный угол (в градусах) от вертикали, при котором поверхность считается "стеной"
|
||||
|
||||
// Наклон при залазании на стены
|
||||
public float
|
||||
maxWallLeanAngle = 45f, // Максимальный угол наклона от стены (в градусах)
|
||||
wallLeanSharpness = 50f, // Скорость наклона/выпрямления (чем выше — тем резче)
|
||||
wallLeanHeightScale = 0.1f; // Множитель: на сколько метров подъёма = 1 единица "наклона"
|
||||
leanAngle = 25f,
|
||||
leanThreshold = 0.3f,
|
||||
leanSmoothSpeed = 10f;
|
||||
|
||||
// Гравитация
|
||||
public Vector3 gravity = new(0f, -30f, 0f); // Вектор, отвечающий за применение гравитации
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Code.Configs
|
||||
{
|
||||
[CreateAssetMenu(menuName = "Config/Audio/CharacterSoundList", fileName = "CharacterSoundListConfig")]
|
||||
public class CharacterSoundListConfig : ScriptableObject
|
||||
{
|
||||
public AssetReference[] character;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Code.Configs
|
||||
{
|
||||
[CreateAssetMenu(menuName = "Config/Audio/CourierSoundListConfig", fileName = "CourierSoundListConfig")]
|
||||
public class CourierSoundListConfig : ScriptableObject
|
||||
{
|
||||
public AssetReference[] courierSounds;
|
||||
}
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using AYellowpaper.SerializedCollections;
|
||||
using UnityEngine;
|
||||
using AudioType = Code.Audio.AudioType;
|
||||
|
||||
namespace Code.Configs
|
||||
{
|
||||
[CreateAssetMenu(fileName = "DefaultAudioSettingsConfig", menuName = "Audio/DefaultAudioSettings")]
|
||||
public class DefaultAudioSettingsConfig : ScriptableObject
|
||||
{
|
||||
[Header("Menu")]
|
||||
[SerializedDictionary("AudioType", "Volume")]
|
||||
public SerializedDictionary<Audio.AudioType, float> menuVolume = new();
|
||||
|
||||
[Header("Action")]
|
||||
[SerializedDictionary("AudioType", "Volume")]
|
||||
public SerializedDictionary<Audio.AudioType, float> actionVolume = new();
|
||||
|
||||
[Header("Peaceful")]
|
||||
[SerializedDictionary("AudioType", "Volume")]
|
||||
public SerializedDictionary<Audio.AudioType, float> peacefulVolume = new();
|
||||
|
||||
[Header("None")]
|
||||
[SerializedDictionary("AudioType", "Volume")]
|
||||
public SerializedDictionary<Audio.AudioType, float> noneVolume = new();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36d35c52933d4d4ba836f75b05c4810f
|
||||
timeCreated: 1764754933
|
||||
@@ -0,0 +1,10 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Configs
|
||||
{
|
||||
[CreateAssetMenu(menuName = "Config/Audio/MusicPlayer", fileName = "MusicPlayerConfig")]
|
||||
public class MusicPlayerConfig : ScriptableObject
|
||||
{
|
||||
public float threshold = 0.5f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8708e3c129d241b08563f1a170bd3a44
|
||||
timeCreated: 1764585060
|
||||
@@ -8,6 +8,7 @@ namespace Code.Configs
|
||||
{
|
||||
public AssetReference[] peacefulSoundtrack;
|
||||
public AssetReference[] actionSoundtrack;
|
||||
public AssetReference[] deathSoundtrack;
|
||||
public AssetReference[] menuSoundtrack;
|
||||
}
|
||||
}
|
||||
@@ -19,13 +19,14 @@ namespace Code.Constants
|
||||
public const string PeacefulMusicGroup = "Peaceful";
|
||||
public const string ActionMusicGroup = "Action";
|
||||
public const string DispatcherMusicGroup = "Dispatcher";
|
||||
public const string CourierMusicGroup = "Courier";
|
||||
public const string EnemiesMusicGroup = "Enemies";
|
||||
public const string CourierGroup = "Courier";
|
||||
public const string EnemiesGroup = "Enemies";
|
||||
|
||||
public const string PeacefulSnapshot = "Peaceful";
|
||||
public const string ActionSnapshot = "Action";
|
||||
public const string NoneSnapshot = "None";
|
||||
public const string MenuSnapshot = "Menu";
|
||||
public const string MenuMusicGroup = "Menu";
|
||||
public const string DeathMusicGroup = "Death";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb5ad0cc3a72448a93ee2adb560c35ad
|
||||
timeCreated: 1764345160
|
||||
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.DebugAndTest
|
||||
{
|
||||
public class TriggerTest : MonoBehaviour
|
||||
{
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
Debug.Log(gameObject.name + " found " + other.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6bb3c649d82049079d00b843a76aced8
|
||||
timeCreated: 1764345168
|
||||
@@ -24,6 +24,8 @@ namespace Code.Gameplay.Camera.CameraStates
|
||||
CurrentDistance = 0f;
|
||||
|
||||
Camera.fieldOfView = Context.CameraSettingsConfigs[CameraMode.FirstPerson].fov;
|
||||
|
||||
Cursor.lockState = CursorLockMode.Locked;
|
||||
}
|
||||
|
||||
protected override void HandlePosition(float deltaTime, float zoomInput, Quaternion targetRotation)
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace Code.Gameplay.Camera.CameraStates
|
||||
base.EnterState();
|
||||
|
||||
Camera.fieldOfView = Context.CameraSettingsConfigs[CameraMode.MainMenu].fov;
|
||||
Cursor.lockState = CursorLockMode.None;
|
||||
}
|
||||
|
||||
protected override void HandlePosition(float deltaTime, float zoomInput, Quaternion targetRotation)
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Code.Gameplay.Camera.CameraStates
|
||||
base.EnterState();
|
||||
|
||||
Camera.fieldOfView = Context.CameraSettingsConfigs[CameraMode.Static].fov;
|
||||
Cursor.lockState = CursorLockMode.None;
|
||||
}
|
||||
|
||||
protected override void HandlePosition(float deltaTime, float zoomInput, Quaternion targetRotation)
|
||||
|
||||
+58
-127
@@ -1,147 +1,78 @@
|
||||
using UnityEngine;
|
||||
using KinematicCharacterController;
|
||||
|
||||
namespace Code.Gameplay.Character.Controller.Abilities
|
||||
{
|
||||
/*
|
||||
* Механика наклона персонажа при контакте со стеной
|
||||
* Управляет визуальным наклоном модели в зависимости от высоты подъёма по стене
|
||||
*/
|
||||
public class WallLeanMechanic
|
||||
{
|
||||
private readonly float _maxLeanAngle;
|
||||
private readonly float _leanSharpness;
|
||||
private readonly float _heightScale;
|
||||
private readonly float _leanAngle;
|
||||
private readonly float _threshold;
|
||||
private readonly float _smoothSpeed;
|
||||
|
||||
private Transform _characterTransform;
|
||||
private Vector3 _lastWallNormal;
|
||||
private float _lastWallContactHeight;
|
||||
private float _leanFactor;
|
||||
private float _leanSign;
|
||||
private Vector3 _leanDirection;
|
||||
private Transform _model;
|
||||
|
||||
private Vector3 _lastWallContactPoint;
|
||||
private bool _isLeaningOnWall;
|
||||
private const float WallProximityThreshold = 0.6f;
|
||||
|
||||
public WallLeanMechanic(float maxLeanAngle, float leanSharpness, float heightScale)
|
||||
public WallLeanMechanic(
|
||||
float leanAngle,
|
||||
float threshold,
|
||||
float smoothSpeed)
|
||||
{
|
||||
_maxLeanAngle = maxLeanAngle;
|
||||
_leanSharpness = leanSharpness;
|
||||
_heightScale = heightScale;
|
||||
_leanAngle = leanAngle;
|
||||
_threshold = threshold;
|
||||
_smoothSpeed = smoothSpeed;
|
||||
}
|
||||
|
||||
// Назначаем трансформ визуальной модели один раз
|
||||
public void SetCharacterTransform(Transform transform)
|
||||
public void SetModel(Transform model) => _model = model;
|
||||
|
||||
public void Update(bool isWallRunning, Vector3 wallNormal, Vector3 characterForward)
|
||||
{
|
||||
_characterTransform = transform;
|
||||
}
|
||||
|
||||
// Вызывается из OnMovementHit
|
||||
public void OnWallContact(KinematicCharacterMotor motor, Vector3 wallNormal, float contactHeight)
|
||||
{
|
||||
// Только если это действительно стена (не пол/потолок)
|
||||
var dotWithUp = Vector3.Dot(wallNormal, motor.CharacterUp);
|
||||
if (Mathf.Abs(dotWithUp) > 0.7f) // ~45°, можно настроить
|
||||
return;
|
||||
|
||||
_lastWallNormal = wallNormal;
|
||||
_lastWallContactHeight = contactHeight;
|
||||
_lastWallContactPoint = motor.TransientPosition;
|
||||
|
||||
// Пересчитываем направление наклона
|
||||
_leanDirection = -_lastWallNormal;
|
||||
_leanDirection = Vector3.ProjectOnPlane(_leanDirection, motor.CharacterUp).normalized;
|
||||
|
||||
_leanSign = 1;
|
||||
|
||||
// what the fuck
|
||||
if (_leanDirection.x != 0)
|
||||
if (!_model)
|
||||
{
|
||||
switch (_leanDirection.x)
|
||||
{
|
||||
case -1 or 1 when motor.CharacterRight.x > 0.1f:
|
||||
_leanSign = -1;
|
||||
break;
|
||||
case -1 or 1 when Mathf.Abs(motor.CharacterRight.x) < 0.1f:
|
||||
_leanDirection = new Vector3(0, 0, -1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (_leanDirection.z)
|
||||
{
|
||||
case 1 when Mathf.Abs(motor.CharacterRight.z) < 0.1f:
|
||||
_leanSign = -1;
|
||||
break;
|
||||
case -1 when motor.CharacterRight.z < -0.1f:
|
||||
case 1 when motor.CharacterRight.z > 0.1f:
|
||||
_leanDirection = new Vector3(-1, 0, 0);
|
||||
break;
|
||||
case -1 when motor.CharacterRight.z > 0.1f:
|
||||
case 1 when motor.CharacterRight.z < -0.1f:
|
||||
_leanDirection = new Vector3(1, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_isLeaningOnWall = true;
|
||||
}
|
||||
|
||||
// Обновление каждый кадр
|
||||
public void UpdateLean(KinematicCharacterMotor motor, float deltaTime)
|
||||
{
|
||||
if (!_characterTransform) return;
|
||||
|
||||
var currentPosition = motor.TransientPosition;
|
||||
|
||||
var isStillNearWall = false;
|
||||
if (_isLeaningOnWall && _lastWallNormal != Vector3.zero)
|
||||
{
|
||||
var toWall = currentPosition - _lastWallContactPoint;
|
||||
var distanceToWallPlane = Mathf.Abs(Vector3.Dot(toWall, _lastWallNormal));
|
||||
isStillNearWall = distanceToWallPlane <= WallProximityThreshold;
|
||||
}
|
||||
|
||||
if (_isLeaningOnWall)
|
||||
{
|
||||
var isBelowContactHeight = currentPosition.y < _lastWallContactHeight;
|
||||
|
||||
if (!isStillNearWall || isBelowContactHeight)
|
||||
{
|
||||
_isLeaningOnWall = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var heightDelta = currentPosition.y - _lastWallContactHeight;
|
||||
var targetLeanFactor = Mathf.Clamp01(heightDelta * _heightScale);
|
||||
_leanFactor = Mathf.Lerp(_leanFactor, targetLeanFactor, 1f - Mathf.Exp(-_leanSharpness * deltaTime));
|
||||
}
|
||||
}
|
||||
|
||||
if (!_isLeaningOnWall)
|
||||
{
|
||||
_leanFactor = Mathf.Lerp(_leanFactor, 0f, 1f - Mathf.Exp(-_leanSharpness * deltaTime));
|
||||
}
|
||||
|
||||
ApplyLeanRotation(motor);
|
||||
}
|
||||
|
||||
private void ApplyLeanRotation(KinematicCharacterMotor motor)
|
||||
{
|
||||
if (_leanFactor <= 0.01f)
|
||||
{
|
||||
_characterTransform.localRotation = Quaternion.identity;
|
||||
_model.localRotation = Quaternion.identity;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_leanDirection.sqrMagnitude < 0.01f) return;
|
||||
var targetRotation = Quaternion.identity;
|
||||
|
||||
var leanAngle = _leanSign * _leanFactor * _maxLeanAngle;
|
||||
var leanAxis = Vector3.Cross(motor.CharacterUp, _leanDirection);
|
||||
var leanRotation = Quaternion.AngleAxis(leanAngle, leanAxis);
|
||||
_characterTransform.localRotation = leanRotation;
|
||||
if (isWallRunning)
|
||||
{
|
||||
var n = new Vector3(wallNormal.x, 0f, wallNormal.z).normalized;
|
||||
if (n.sqrMagnitude < 0.001f) n = Vector3.forward;
|
||||
|
||||
var bodyRight = Vector3.Cross(Vector3.up, characterForward).normalized;
|
||||
var side = Vector3.Dot(n, bodyRight);
|
||||
var front = Vector3.Dot(n, characterForward);
|
||||
|
||||
var axis = Vector3.right;
|
||||
var angle = 0f;
|
||||
|
||||
if (side > _threshold)
|
||||
{
|
||||
axis = Vector3.forward;
|
||||
angle = -_leanAngle;
|
||||
}
|
||||
else if (side < -_threshold)
|
||||
{
|
||||
axis = Vector3.forward;
|
||||
angle = _leanAngle;
|
||||
}
|
||||
else if (front > _threshold)
|
||||
{
|
||||
axis = Vector3.right;
|
||||
angle = -_leanAngle;
|
||||
}
|
||||
else if (front < -_threshold)
|
||||
{
|
||||
axis = Vector3.right;
|
||||
angle = _leanAngle;
|
||||
}
|
||||
|
||||
targetRotation = Quaternion.AngleAxis(angle, axis);
|
||||
}
|
||||
|
||||
_model.localRotation = Quaternion.Slerp(
|
||||
_model.localRotation,
|
||||
targetRotation,
|
||||
1f - Mathf.Exp(-_smoothSpeed * Time.deltaTime)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+256
@@ -0,0 +1,256 @@
|
||||
using Code.Gameplay.Character.Controller.Input;
|
||||
using Code.Gameplay.Character.Core;
|
||||
using KinematicCharacterController;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Gameplay.Character.Controller.Abilities
|
||||
{
|
||||
public class WallRunningMechanic
|
||||
{
|
||||
public float MaxWallRunTime = 1.75f;
|
||||
public float WallRunSpeed = 8.0f;
|
||||
public float WallRunAcceleration = 25.0f;
|
||||
public float WallRunGravityScale = 0.25f;
|
||||
public float WallDetachImpulse = 7.0f;
|
||||
public float WallContactAngleThreshold = 45.0f;
|
||||
|
||||
private bool _isWallRunning;
|
||||
private float _wallRunTimer;
|
||||
private Vector3 _wallNormal;
|
||||
private Vector3 _wallTangentRight;
|
||||
private Vector3 _wallTangentUp;
|
||||
private Vector3 _wallContactPoint;
|
||||
private Vector3 _lastMoveInputInWallSpace;
|
||||
|
||||
private float _surfaceAngleCos;
|
||||
private bool _canWallRun;
|
||||
public float WallContactHeight { get; private set; }
|
||||
|
||||
public Vector3 WallRunStartForward { get; private set; }
|
||||
|
||||
private KinematicCharacterMotor _motor;
|
||||
private CharacterInputHandler _inputHandler;
|
||||
|
||||
public bool IsWallRunning => _isWallRunning;
|
||||
|
||||
public void Initialize(KinematicCharacterMotor motor, CharacterInputHandler inputHandler)
|
||||
{
|
||||
_motor = motor;
|
||||
_inputHandler = inputHandler;
|
||||
_surfaceAngleCos = Mathf.Cos(Mathf.Deg2Rad * WallContactAngleThreshold);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_isWallRunning = false;
|
||||
_wallRunTimer = 0f;
|
||||
_wallNormal = Vector3.zero;
|
||||
}
|
||||
|
||||
public void Tick(float deltaTime)
|
||||
{
|
||||
if (_isWallRunning)
|
||||
{
|
||||
_wallRunTimer += deltaTime;
|
||||
if (_wallRunTimer > MaxWallRunTime)
|
||||
{
|
||||
DetachFromWall(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryStartWallRun(Vector3 hitNormal, Vector3 hitPoint)
|
||||
{
|
||||
if (_isWallRunning) return false;
|
||||
|
||||
float dotWithUp = Vector3.Dot(hitNormal, _motor.CharacterUp);
|
||||
bool isWall = Mathf.Abs(dotWithUp) < _surfaceAngleCos;
|
||||
|
||||
if (!isWall) return false;
|
||||
|
||||
if (_motor.GroundingStatus.IsStableOnGround) return false;
|
||||
|
||||
float velocityIntoWall = Vector3.Dot(_motor.Velocity, -hitNormal);
|
||||
if (velocityIntoWall < 1f) return false;
|
||||
|
||||
StartWallRun(hitNormal, hitPoint);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void StartWallRun(Vector3 wallNormal, Vector3 contactPoint)
|
||||
{
|
||||
_isWallRunning = true;
|
||||
_wallRunTimer = 0f;
|
||||
_wallNormal = wallNormal.normalized;
|
||||
_wallContactPoint = contactPoint;
|
||||
WallContactHeight = contactPoint.y;
|
||||
|
||||
//_wallTangentUp = Vector3.ProjectOnPlane(_motor.CharacterUp, _wallNormal).normalized;
|
||||
if (_wallTangentUp.sqrMagnitude < 0.01f) _wallTangentUp = Vector3.up;
|
||||
|
||||
_wallTangentRight = Vector3.Cross(_wallNormal, _wallTangentUp).normalized;
|
||||
|
||||
_wallTangentUp = Vector3.Cross(_wallTangentRight, _wallNormal).normalized;
|
||||
if (Vector3.Dot(_wallTangentUp, Vector3.up) < 0)
|
||||
_wallTangentUp = -_wallTangentUp;
|
||||
|
||||
WallRunStartForward = _motor.CharacterForward;
|
||||
_motor.ForceUnground();
|
||||
}
|
||||
|
||||
public void HandleWallRun(ref Vector3 currentVelocity, CharacterInputs inputs, float deltaTime)
|
||||
{
|
||||
if (!_isWallRunning) return;
|
||||
if (!IsWallStillPresent()) { DetachFromWall(false); return; }
|
||||
|
||||
Vector3 moveInputWorld = _inputHandler.MoveInputVector;
|
||||
Vector3 moveInWallPlane = Vector3.ProjectOnPlane(moveInputWorld, _wallNormal);
|
||||
|
||||
Vector3 wsMove = Vector3.Project(moveInWallPlane, _wallTangentRight);
|
||||
|
||||
float ad = inputs.MoveAxisRight;
|
||||
|
||||
float sideDot = Vector3.Dot(_wallNormal, _motor.CharacterRight);
|
||||
if (sideDot < 0)
|
||||
ad = -ad;
|
||||
|
||||
Vector3 adMove = _wallTangentUp * (-ad);
|
||||
|
||||
Vector3 finalMove = wsMove + adMove;
|
||||
finalMove = finalMove.normalized * moveInputWorld.magnitude;
|
||||
|
||||
Vector3 targetVelocity = finalMove * WallRunSpeed;
|
||||
|
||||
currentVelocity = Vector3.Lerp(
|
||||
currentVelocity,
|
||||
targetVelocity,
|
||||
1f - Mathf.Exp(-WallRunAcceleration * deltaTime)
|
||||
);
|
||||
|
||||
currentVelocity += Physics.gravity * (WallRunGravityScale * deltaTime);
|
||||
|
||||
float distanceToWall = Vector3.Dot(_motor.TransientPosition - _wallContactPoint, _wallNormal);
|
||||
if (Mathf.Abs(distanceToWall) > 0.8f)
|
||||
{
|
||||
DetachFromWall(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (inputs.JumpPressed)
|
||||
{
|
||||
DetachFromWall(true);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsWallStillPresent()
|
||||
{
|
||||
if (_motor == null) return false;
|
||||
|
||||
Vector3 characterCenter = _motor.TransientPosition;
|
||||
Vector3 characterForward = _motor.CharacterForward;
|
||||
Vector3 characterRight = _motor.CharacterRight;
|
||||
Vector3 characterUp = _motor.CharacterUp;
|
||||
|
||||
float checkDistance = 0.45f;
|
||||
Vector3 rayOrigin = characterCenter + characterUp * 0.2f;
|
||||
Vector3 rayDir = -_wallNormal;
|
||||
|
||||
Vector3[] offsets = {
|
||||
Vector3.zero,
|
||||
characterUp * 0.3f,
|
||||
-characterUp * 0.3f,
|
||||
characterRight * 0.2f,
|
||||
-characterRight * 0.2f
|
||||
};
|
||||
|
||||
foreach (var offset in offsets)
|
||||
{
|
||||
if (Physics.Raycast(rayOrigin + offset, rayDir, out RaycastHit hit, checkDistance,
|
||||
_motor.CollidableLayers, QueryTriggerInteraction.Ignore))
|
||||
{
|
||||
float dotWithUp = Mathf.Abs(Vector3.Dot(hit.normal, characterUp));
|
||||
if (dotWithUp < _surfaceAngleCos)
|
||||
{
|
||||
_wallNormal = hit.normal.normalized;
|
||||
_wallContactPoint = hit.point;
|
||||
|
||||
/*_wallTangentUp = Vector3.ProjectOnPlane(_motor.CharacterUp, _wallNormal).normalized;
|
||||
if (_wallTangentUp.sqrMagnitude < 0.01f) _wallTangentUp = Vector3.up;
|
||||
_wallTangentRight = Vector3.Cross(_wallNormal, _wallTangentUp).normalized;
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void DetachFromWall(bool withImpulse)
|
||||
{
|
||||
if (!_isWallRunning) return;
|
||||
|
||||
_isWallRunning = false;
|
||||
|
||||
if (withImpulse && _motor != null)
|
||||
{
|
||||
Vector3 detachImpulse = -_wallNormal * WallDetachImpulse;
|
||||
_motor.BaseVelocity += detachImpulse;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 GetWallNormal() => _wallNormal;
|
||||
public bool TryGetWallTangents(out Vector3 up, out Vector3 right)
|
||||
{
|
||||
if (!_isWallRunning)
|
||||
{
|
||||
up = right = Vector3.zero;
|
||||
return false;
|
||||
}
|
||||
up = _wallTangentUp;
|
||||
right = _wallTangentRight;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CanWallRun()
|
||||
{
|
||||
return !_isWallRunning && !_motor.GroundingStatus.IsStableOnGround;
|
||||
}
|
||||
|
||||
public void PerformWallJump(CharacterInputs inputs, Quaternion cameraRotation)
|
||||
{
|
||||
if (!_isWallRunning || _motor == null) return;
|
||||
|
||||
_isWallRunning = false;
|
||||
|
||||
Vector3 wallAway = _wallNormal;
|
||||
Vector3 wallUp = _wallTangentUp;
|
||||
|
||||
Vector3 playerForward = cameraRotation * Vector3.forward;
|
||||
|
||||
Vector3 forwardInWallPlane = Vector3.ProjectOnPlane(playerForward, _wallNormal).normalized;
|
||||
if (forwardInWallPlane.sqrMagnitude < 0.01f) forwardInWallPlane = _wallTangentRight;
|
||||
|
||||
Vector3 jumpDirection =
|
||||
forwardInWallPlane * 0.2f +
|
||||
wallAway * 0.4f +
|
||||
wallUp * 0.4f;
|
||||
|
||||
jumpDirection = jumpDirection.normalized;
|
||||
|
||||
float wallJumpForce = WallDetachImpulse * 2f;
|
||||
|
||||
Vector3 jumpImpulse = jumpDirection * wallJumpForce;
|
||||
|
||||
_motor.BaseVelocity += jumpImpulse;
|
||||
|
||||
_motor.SetPosition(_motor.TransientPosition + wallAway * 0.07f);
|
||||
|
||||
if (_motor.CharacterController is CustomCharacterController controller)
|
||||
{
|
||||
controller.BlockAbilities(0.12f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4bef67aa9cf14753a63ea07eecc5ff67
|
||||
timeCreated: 1764263348
|
||||
+58
-90
@@ -28,49 +28,23 @@ namespace Code.Gameplay.Character.Controller
|
||||
// Подсистемы
|
||||
private CharacterInputHandler _inputHandler;
|
||||
private SlideMechanic _slideMechanic;
|
||||
private WallClimbMechanic _wallClimbMechanic;
|
||||
// private WallClimbMechanic _wallClimbMechanic;
|
||||
private WallRunningMechanic _wallRunningMechanic;
|
||||
private WallLeanMechanic _wallLeanMechanic;
|
||||
private GroundMovementSystem _groundMovement;
|
||||
private AirMovementSystem _airMovement;
|
||||
|
||||
public bool IsSliding => _slideMechanic.IsSliding;
|
||||
public bool IsWallRunning => _wallRunningMechanic.IsWallRunning;
|
||||
|
||||
private float abilityBlockTimer;
|
||||
private bool isAbilitiesBlocked;
|
||||
|
||||
private CharacterInputs _lastInputs;
|
||||
|
||||
public void SetPosition(Vector3 position) => motor.SetPosition(position);
|
||||
public void SetRotation(Quaternion rotation) => motor.SetRotation(rotation);
|
||||
|
||||
// Инициализация контроллера
|
||||
// private void Awake()
|
||||
// {
|
||||
// // Инициализация подсистем с параметрами из конфига
|
||||
// _inputHandler = new CharacterInputHandler(
|
||||
// _characterConfig.sprintAngleThreshold
|
||||
// );
|
||||
// _slideMechanic = new SlideMechanic(
|
||||
// _characterConfig.slideSpeed,
|
||||
// _characterConfig.slideDuration,
|
||||
// _characterConfig.slideCooldown
|
||||
// );
|
||||
// _wallClimbMechanic = new WallClimbMechanic(
|
||||
// _characterConfig.wallClimbSpeedFactor,
|
||||
// _characterConfig.minWallClimbSpeed,
|
||||
// _characterConfig.wallDetectionAngleThreshold
|
||||
// );
|
||||
// _wallLeanMechanic = new WallLeanMechanic(
|
||||
// _characterConfig.maxWallLeanAngle,
|
||||
// _characterConfig.wallLeanSharpness,
|
||||
// _characterConfig.wallLeanHeightScale
|
||||
// );
|
||||
// _groundMovement = new GroundMovementSystem(
|
||||
// _characterConfig.maxStableMoveSpeed,
|
||||
// _characterConfig.sprintMoveSpeed,
|
||||
// _characterConfig.stableMovementSharpness,
|
||||
// _characterConfig.jumpSpeed
|
||||
// );
|
||||
// _airMovement = new AirMovementSystem(_characterConfig.gravity);
|
||||
// }
|
||||
[Inject]
|
||||
private void Construct(CharacterConfig characterConfig)
|
||||
{
|
||||
@@ -84,16 +58,25 @@ namespace Code.Gameplay.Character.Controller
|
||||
_characterConfig.slideDuration,
|
||||
_characterConfig.slideCooldown
|
||||
);
|
||||
_wallClimbMechanic = new WallClimbMechanic(
|
||||
_characterConfig.wallClimbSpeedFactor,
|
||||
_characterConfig.minWallClimbSpeed,
|
||||
_characterConfig.wallDetectionAngleThreshold
|
||||
);
|
||||
// _wallClimbMechanic = new WallClimbMechanic(
|
||||
// _characterConfig.wallClimbSpeedFactor,
|
||||
// _characterConfig.minWallClimbSpeed,
|
||||
// _characterConfig.wallDetectionAngleThreshold
|
||||
// );
|
||||
_wallRunningMechanic = new WallRunningMechanic();
|
||||
// Настройка параметров WallRunningMechanic (можно вынести в конфиг позже)
|
||||
_wallRunningMechanic.MaxWallRunTime = 1.75f;
|
||||
_wallRunningMechanic.WallRunSpeed = 15.0f;
|
||||
_wallRunningMechanic.WallRunAcceleration = 25.0f;
|
||||
_wallRunningMechanic.WallRunGravityScale = 0.25f;
|
||||
_wallRunningMechanic.WallDetachImpulse = 7.0f;
|
||||
_wallRunningMechanic.WallContactAngleThreshold = 45.0f;
|
||||
|
||||
_wallLeanMechanic = new WallLeanMechanic(
|
||||
_characterConfig.maxWallLeanAngle,
|
||||
_characterConfig.wallLeanSharpness,
|
||||
_characterConfig.wallLeanHeightScale
|
||||
);
|
||||
_characterConfig.leanAngle,
|
||||
_characterConfig.leanThreshold,
|
||||
_characterConfig.leanSmoothSpeed
|
||||
);
|
||||
_groundMovement = new GroundMovementSystem(
|
||||
_characterConfig.maxStableMoveSpeed,
|
||||
_characterConfig.sprintMoveSpeed,
|
||||
@@ -106,31 +89,24 @@ namespace Code.Gameplay.Character.Controller
|
||||
motor.CharacterController = this; // Регистрация этого контроллера в движке
|
||||
_inputHandler.FirstPersonCameraRotation =
|
||||
motor.Transform.rotation; // Начальное вращение совпадает с персонажемс
|
||||
_wallLeanMechanic.SetCharacterTransform(characterTransform);
|
||||
_wallLeanMechanic.SetModel(characterTransform);
|
||||
_wallRunningMechanic.Initialize(motor, _inputHandler);
|
||||
}
|
||||
|
||||
// Текущий режим камеры для адаптации поведения
|
||||
private CameraMode _currentCameraMode = CameraMode.FirstPerson;
|
||||
|
||||
// Инициализация контроллера
|
||||
// private void Start()
|
||||
// {
|
||||
// motor.CharacterController = this; // Регистрация этого контроллера в движке
|
||||
// _inputHandler.FirstPersonCameraRotation =
|
||||
// motor.Transform.rotation; // Начальное вращение совпадает с персонажемс
|
||||
// _wallLeanMechanic.SetCharacterTransform(characterTransform);
|
||||
// }
|
||||
|
||||
// Обработка и преобразование входных данных от персонажа
|
||||
public void SetInputs(ref CharacterInputs inputs)
|
||||
{
|
||||
// Обновляем таймер перезарядки слайда
|
||||
_lastInputs = inputs;
|
||||
// Обновляем таймеры механик
|
||||
_slideMechanic.TickCooldown(Time.deltaTime);
|
||||
_wallClimbMechanic.TickCooldown(Time.deltaTime);
|
||||
// _wallClimbMechanic.TickCooldown(Time.deltaTime);
|
||||
_wallRunningMechanic.Tick(Time.deltaTime);
|
||||
|
||||
// Если активен слайд - игнорируем весь остальной ввод
|
||||
if (_slideMechanic.IsSliding)
|
||||
{
|
||||
// Во время слайда не обрабатываем движение, прыжки и спринт
|
||||
_inputHandler.MoveInputVector = Vector3.zero;
|
||||
_inputHandler.LookInputVector = Vector3.one;
|
||||
_inputHandler.IsSprinting = false;
|
||||
@@ -138,7 +114,6 @@ namespace Code.Gameplay.Character.Controller
|
||||
return;
|
||||
}
|
||||
|
||||
// Сохраняем текущий режим камеры
|
||||
_currentCameraMode = inputs.CameraMode;
|
||||
|
||||
if (isAbilitiesBlocked)
|
||||
@@ -161,42 +136,33 @@ namespace Code.Gameplay.Character.Controller
|
||||
// Обработка остального ввода
|
||||
_inputHandler.ProcessInputs(ref inputs, motor);
|
||||
|
||||
// Передаём запрос прыжка напрямую в систему движения по земле
|
||||
// Передаём запрос прыжка
|
||||
_groundMovement.RequestJump(inputs.JumpPressed);
|
||||
}
|
||||
|
||||
// Обновление вращения персонажа на основе входных данных
|
||||
public void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
|
||||
{
|
||||
if (_slideMechanic.IsSliding || _wallClimbMechanic.IsClimbingActive) return;
|
||||
if (_slideMechanic.IsSliding) return;
|
||||
|
||||
switch (_currentCameraMode)
|
||||
{
|
||||
// В FirstPerson режиме применяем вращение камеры напрямую к персонажу (только горизонталь)
|
||||
case CameraMode.FirstPerson when _inputHandler.ShouldApplyCameraRotation:
|
||||
// Немедленно применяем горизонтальное вращение камеры к персонажу
|
||||
currentRotation = _inputHandler.FirstPersonCameraRotation;
|
||||
break;
|
||||
// В ThirdPerson режиме плавно поворачиваем персонаж в направлении движения
|
||||
case CameraMode.ThirdPerson:
|
||||
{
|
||||
// Вращение применяется только если есть направление движения и разрешена резкость вращения
|
||||
if (_inputHandler.LookInputVector.sqrMagnitude > 0 && _characterConfig.orientationSharpness > 0)
|
||||
{
|
||||
// Плавная интерполяция текущего направления к целевому с экспоненциальным сглаживанием
|
||||
var smoothedLookInputDirection = Vector3.Slerp(
|
||||
motor.CharacterForward,
|
||||
_inputHandler.LookInputVector,
|
||||
1f - Mathf.Exp(-_characterConfig.orientationSharpness * deltaTime)
|
||||
).normalized;
|
||||
|
||||
// Установка нового вращения смотря в сглаженном направлении
|
||||
currentRotation = Quaternion.LookRotation(smoothedLookInputDirection, motor.CharacterUp);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
// Заготовка на будущее (если понадобится)
|
||||
case CameraMode.Static:
|
||||
case CameraMode.Cinematic:
|
||||
default:
|
||||
@@ -204,38 +170,49 @@ namespace Code.Gameplay.Character.Controller
|
||||
}
|
||||
}
|
||||
|
||||
// Обновление скорости движения персонажа
|
||||
public void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
|
||||
{
|
||||
// Если во время слайда запрошен прыжок — прерываем слайд
|
||||
if (_slideMechanic.IsSliding && _groundMovement.JumpRequested)
|
||||
{
|
||||
_slideMechanic.EndSlide();
|
||||
}
|
||||
|
||||
// Проверяем запрос слайда и запускаем его если можно
|
||||
if (!_slideMechanic.IsSliding)
|
||||
{
|
||||
_slideMechanic.TryStartSlide(motor, _currentCameraMode, _inputHandler.FirstPersonCameraRotation,
|
||||
_inputHandler.LookInputVector);
|
||||
}
|
||||
// Если активен слайд - обрабатываем отдельно
|
||||
else
|
||||
{
|
||||
_slideMechanic.HandleSlide(ref currentVelocity, deltaTime, motor);
|
||||
return;
|
||||
}
|
||||
|
||||
// === WALL RUNNING: обработка состояния ===
|
||||
if (_wallRunningMechanic.IsWallRunning)
|
||||
{
|
||||
// 🔄 Передаём актуальные данные для walljump
|
||||
if (_groundMovement.JumpRequested) // или _lastInputs.JumpPressed — зависит от логики
|
||||
{
|
||||
_wallRunningMechanic.PerformWallJump(_lastInputs, _inputHandler.FirstPersonCameraRotation);
|
||||
_groundMovement.CancelJumpRequest(); // сброс, чтобы не сработало дважды
|
||||
}
|
||||
else
|
||||
{
|
||||
_wallRunningMechanic.HandleWallRun(ref currentVelocity, _lastInputs, deltaTime);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Если персонаж находится на земле
|
||||
if (motor.GroundingStatus.IsStableOnGround)
|
||||
{
|
||||
_groundMovement.UpdateVelocity(ref currentVelocity, _inputHandler, motor, deltaTime);
|
||||
}
|
||||
// Если персонаж не находится на земле
|
||||
// Если персонаж не на земле — стандартное воздушное движение
|
||||
else
|
||||
{
|
||||
_airMovement.UpdateVelocity(ref currentVelocity, deltaTime);
|
||||
// Отменяем прыжок (фикс проблемы с двойным прыжком после приземления)
|
||||
_groundMovement.CancelJumpRequest();
|
||||
}
|
||||
}
|
||||
@@ -246,60 +223,51 @@ namespace Code.Gameplay.Character.Controller
|
||||
abilityBlockTimer = duration;
|
||||
}
|
||||
|
||||
// Метод вызывается перед обновлением персонажа (можно использовать для подготовки)
|
||||
public void BeforeCharacterUpdate(float deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
// Метод вызывается после обработки столкновения с землей
|
||||
public void PostGroundingUpdate(float deltaTime)
|
||||
{
|
||||
// Если во время слайда персонаж оторвался от земли - заканчиваем слайд
|
||||
if (_slideMechanic.IsSliding && !motor.GroundingStatus.IsStableOnGround)
|
||||
{
|
||||
_slideMechanic.EndSlide();
|
||||
}
|
||||
|
||||
if (motor.GroundingStatus.IsStableOnGround)
|
||||
{
|
||||
_wallClimbMechanic.ResetWallClimbSession();
|
||||
}
|
||||
}
|
||||
|
||||
// Метод вызывается после обновления персонажа
|
||||
public void AfterCharacterUpdate(float deltaTime)
|
||||
{
|
||||
_wallLeanMechanic.UpdateLean(motor, deltaTime);
|
||||
_wallLeanMechanic.Update(
|
||||
_wallRunningMechanic.IsWallRunning,
|
||||
_wallRunningMechanic.GetWallNormal(),
|
||||
motor.CharacterForward
|
||||
);
|
||||
}
|
||||
|
||||
// Проверка валидности коллайдера для обработки столкновений
|
||||
public bool IsColliderValidForCollisions(Collider coll)
|
||||
{
|
||||
return true; // Все коллайдеры считаются валидными для столкновений
|
||||
return true;
|
||||
}
|
||||
|
||||
// Обработка столкновения с землей (вызывается при приземлении)
|
||||
public void OnGroundHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint,
|
||||
ref HitStabilityReport hitStabilityReport)
|
||||
{
|
||||
}
|
||||
|
||||
// Обработка столкновения при движении (вызывается при ударе о препятствие)
|
||||
public void OnMovementHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint,
|
||||
ref HitStabilityReport hitStabilityReport)
|
||||
{
|
||||
if (_wallClimbMechanic.TryClimbWall(motor, hitNormal))
|
||||
_wallLeanMechanic.OnWallContact(motor, hitNormal, motor.TransientPosition.y);
|
||||
if (_wallRunningMechanic.TryStartWallRun(hitNormal, hitPoint))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// Обработка отчета о стабильности столкновения
|
||||
public void ProcessHitStabilityReport(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint,
|
||||
Vector3 atCharacterPosition,
|
||||
Quaternion atCharacterRotation, ref HitStabilityReport hitStabilityReport)
|
||||
{
|
||||
}
|
||||
|
||||
// Обработка дискретных столкновений (для триггеров и специальных коллайдеров)
|
||||
public void OnDiscreteCollisionDetected(Collider hitCollider)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Gameplay.Door
|
||||
{
|
||||
public class Door : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform doorPolotno;
|
||||
private Vector3 _doorInitialPosition;
|
||||
private Quaternion _doorInitialRotation;
|
||||
[SerializeField] private Transform hingeJointAnchor;
|
||||
[SerializeField] private HingeJoint hingeJoint;
|
||||
[SerializeField] private Rigidbody rigidbody;
|
||||
|
||||
public void TranslationMode(bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
rigidbody.isKinematic = true;
|
||||
return;
|
||||
}
|
||||
_doorInitialPosition = doorPolotno.position;
|
||||
_doorInitialRotation = doorPolotno.rotation;
|
||||
|
||||
rigidbody.isKinematic = false;
|
||||
hingeJoint.autoConfigureConnectedAnchor = false;
|
||||
hingeJoint.connectedAnchor = hingeJointAnchor.position;
|
||||
}
|
||||
|
||||
public void CloseTheDoor()
|
||||
{
|
||||
TranslationMode(true);
|
||||
doorPolotno.DORotate(_doorInitialRotation.eulerAngles, 0.5f);
|
||||
doorPolotno.DOMove(_doorInitialPosition, 0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc9fc6ce2cc24b68b2b330e4fd029b80
|
||||
timeCreated: 1764304430
|
||||
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Gameplay.Door
|
||||
{
|
||||
public class DoorDebug : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform doorSelf;
|
||||
[SerializeField] private Transform doorPolotno;
|
||||
private Vector3 _doorInitialPosition;
|
||||
private Quaternion _doorInitialRotation;
|
||||
[SerializeField] private Transform hingeJointAnchor;
|
||||
[SerializeField] private HingeJoint hingeJoint;
|
||||
[SerializeField] private Rigidbody rigidbody;
|
||||
[SerializeField] private bool debug;
|
||||
[SerializeField] private bool closed;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_doorInitialPosition = doorPolotno.position;
|
||||
_doorInitialRotation = doorPolotno.rotation;
|
||||
}
|
||||
private void Update()
|
||||
{
|
||||
if(debug && !closed)
|
||||
{
|
||||
CloseTheDoor();
|
||||
}
|
||||
}
|
||||
|
||||
public void TranslationMode(bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
rigidbody.isKinematic = true;
|
||||
return;
|
||||
}
|
||||
_doorInitialPosition = doorPolotno.position;
|
||||
_doorInitialRotation = doorPolotno.rotation;
|
||||
|
||||
rigidbody.isKinematic = false;
|
||||
hingeJoint.autoConfigureConnectedAnchor = false;
|
||||
hingeJoint.connectedAnchor = hingeJointAnchor.position;
|
||||
}
|
||||
public void CloseTheDoor()
|
||||
{
|
||||
// TranslationMode(true);
|
||||
doorPolotno.DORotate(_doorInitialRotation.eulerAngles, 0.5f);
|
||||
doorPolotno.DOMove(_doorInitialPosition, 0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed06ed70c7924ca9bc59f33ee7e6cdfa
|
||||
timeCreated: 1764533216
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Code.Gameplay.Door
|
||||
{
|
||||
public class DoorPooler
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: acfad6f51f224b51abb761fc22e4356f
|
||||
timeCreated: 1764521809
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f17ace0fa75741f2a730ff21181c6e8c
|
||||
timeCreated: 1764575680
|
||||
@@ -0,0 +1,23 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
|
||||
namespace Code.Gameplay.Enemies.Animators
|
||||
{
|
||||
public class EnemyAnimator : MonoBehaviour
|
||||
{
|
||||
private static readonly int Velocity = Animator.StringToHash("Velocity");
|
||||
|
||||
[SerializeField] private Animator animator;
|
||||
[SerializeField] private NavMeshAgent agent;
|
||||
|
||||
private void SetVelocity(float velocity)
|
||||
{
|
||||
animator.SetFloat(Velocity, velocity);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if(agent) SetVelocity(agent.velocity.magnitude);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 936125a7ed844674b0e0586a484253ce
|
||||
timeCreated: 1764575708
|
||||
@@ -1,8 +1,10 @@
|
||||
using Code.Audio;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
using Code.Gameplay.Player;
|
||||
using Code.Gameplay.Character.Controller;
|
||||
using Code.Gameplay.Character.Core;
|
||||
using Code.Gameplay.Enemies.Animators;
|
||||
using Reflex.Attributes;
|
||||
using Reflex.Core;
|
||||
using Reflex.Injectors;
|
||||
@@ -13,6 +15,7 @@ namespace Code.Gameplay.Enemies
|
||||
{
|
||||
[SerializeField] protected NavMeshAgent agent;
|
||||
[SerializeField] protected Collider enemyCollider;
|
||||
[Inject] protected IAudioService audioService;
|
||||
|
||||
protected int Damage;
|
||||
protected float AttackCooldown;
|
||||
@@ -35,7 +38,7 @@ namespace Code.Gameplay.Enemies
|
||||
private bool _isStunned;
|
||||
private float _currentStunTimer;
|
||||
|
||||
private bool _canAttack = true;
|
||||
protected bool _canAttack = true;
|
||||
private float _attackCooldownTimer;
|
||||
|
||||
private enum IdleState { Moving, Paused }
|
||||
@@ -50,10 +53,11 @@ namespace Code.Gameplay.Enemies
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
if (_playerProvider == null)
|
||||
{
|
||||
AttributeInjector.Inject(this, Container.ProjectContainer);
|
||||
}
|
||||
// // TODO Мешает
|
||||
// if (_playerProvider == null)
|
||||
// {
|
||||
// AttributeInjector.Inject(this, Container.ProjectContainer);
|
||||
// }
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
@@ -164,19 +168,19 @@ namespace Code.Gameplay.Enemies
|
||||
|
||||
protected virtual void HandleAttackCooldown()
|
||||
{
|
||||
if (!_canAttack)
|
||||
if (_canAttack) return;
|
||||
|
||||
_attackCooldownTimer -= Time.deltaTime;
|
||||
|
||||
if (_attackCooldownTimer <= 0)
|
||||
{
|
||||
_attackCooldownTimer -= Time.deltaTime;
|
||||
if (_attackCooldownTimer <= 0)
|
||||
{
|
||||
_canAttack = true;
|
||||
}
|
||||
_canAttack = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void DealDamage()
|
||||
{
|
||||
if (!_canAttack || PlayerHealth == null) return;
|
||||
if (PlayerHealth == null) return;
|
||||
|
||||
PlayerHealth.GetDamage(Damage);
|
||||
ApplyEffectsToPlayer();
|
||||
@@ -184,11 +188,10 @@ namespace Code.Gameplay.Enemies
|
||||
_canAttack = false;
|
||||
_attackCooldownTimer = AttackCooldown;
|
||||
}
|
||||
|
||||
protected virtual void ApplyEffectsToPlayer()
|
||||
{
|
||||
if (PlayerController)
|
||||
PlayerController.BlockAbilities(3f);
|
||||
PlayerController.BlockAbilities(3f); // TODO в конфиг
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Code.Audio;
|
||||
using Code.Configs;
|
||||
using Reflex.Attributes;
|
||||
using UnityEngine;
|
||||
@@ -35,7 +36,7 @@ namespace Code.Gameplay.Enemies
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
if (agent == null) return;
|
||||
if (!agent) return;
|
||||
|
||||
var walkableArea = NavMesh.GetAreaFromName("Cockroach");
|
||||
agent.areaMask = 1 << walkableArea;
|
||||
@@ -43,12 +44,14 @@ namespace Code.Gameplay.Enemies
|
||||
|
||||
protected override void HandleAttack()
|
||||
{
|
||||
if (!Player) return;
|
||||
if (!Player || !_canAttack) return;
|
||||
|
||||
var distance = Vector3.Distance(transform.position, Player.transform.position);
|
||||
|
||||
if (!(distance <= AttackRange)) return;
|
||||
|
||||
audioService.PlayEnemy(EnemiesSounds.RoachAttack, agent.transform.position);
|
||||
|
||||
DealDamage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Code.Audio;
|
||||
using Code.Configs;
|
||||
using Code.Gameplay.Enemies.Animators;
|
||||
using Reflex.Attributes;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
@@ -40,15 +42,16 @@ namespace Code.Gameplay.Enemies
|
||||
var walkableArea = NavMesh.GetAreaFromName("Walkable");
|
||||
agent.areaMask = 1 << walkableArea;
|
||||
}
|
||||
|
||||
protected override void HandleAttack()
|
||||
{
|
||||
if (!Player) return;
|
||||
if (!Player || !_canAttack) return;
|
||||
|
||||
var distance = Vector3.Distance(transform.position, Player.transform.position);
|
||||
|
||||
if (!(distance <= AttackRange)) return;
|
||||
|
||||
audioService.PlayEnemy(EnemiesSounds.GrandpaAttack,agent.transform.position);
|
||||
|
||||
if (Player.CustomCharacterController.IsSliding)
|
||||
ApplyStun();
|
||||
else
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using Code.Audio;
|
||||
using Reflex.Attributes;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Gameplay.Enemies
|
||||
{
|
||||
public class EnemyAudio : MonoBehaviour
|
||||
{
|
||||
private IAudioService _audioService;
|
||||
private IAudioFactory _audioFactory;
|
||||
[SerializeField] private AudioSource _audioSource;
|
||||
[SerializeField] private EnemiesSounds stepId;
|
||||
|
||||
[Inject]
|
||||
private void Construct(IAudioService audioService, IAudioFactory audioFactory)
|
||||
{
|
||||
_audioService = audioService;
|
||||
_audioSource = audioService.GetSourceOfGroup(Audio.AudioType.Enemies);
|
||||
_audioSource.transform.position = transform.position;
|
||||
_audioSource.spatialBlend = 0;
|
||||
_audioFactory = audioFactory;
|
||||
}
|
||||
|
||||
public void PlayStep()
|
||||
{
|
||||
_audioSource.transform.position = transform.position;
|
||||
_audioSource.PlayOneShot(_audioFactory.EnemiesAudios[(int)stepId]);
|
||||
}
|
||||
private void OnDestroy()
|
||||
{
|
||||
_audioService.ReleaseSourceOfGroup(_audioSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91cb250df1b24fc4825ee791a12dda11
|
||||
timeCreated: 1764695102
|
||||
@@ -3,9 +3,11 @@ using Code.Configs;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Reflex.Attributes;
|
||||
using Reflex.Core;
|
||||
using Reflex.Extensions;
|
||||
using Reflex.Injectors;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Code.Gameplay.Enemies
|
||||
{
|
||||
@@ -27,14 +29,14 @@ namespace Code.Gameplay.Enemies
|
||||
)
|
||||
.ToUniTask();
|
||||
|
||||
AttributeInjector.Inject(enemyObj, Container.ProjectContainer);
|
||||
GameObjectInjector.InjectRecursive(enemyObj, SceneManager.GetActiveScene().GetSceneContainer());
|
||||
|
||||
return enemyObj.GetComponent<BaseEnemy>();
|
||||
}
|
||||
|
||||
public void ReleaseEnemy(BaseEnemy enemy)
|
||||
{
|
||||
if (enemy == null) return;
|
||||
if (!enemy) return;
|
||||
|
||||
enemy.gameObject.SetActive(false);
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using Code.Gameplay.Player;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Reflex.Attributes;
|
||||
using Reflex.Core;
|
||||
using Reflex.Injectors;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Gameplay.Enemies
|
||||
@@ -20,13 +18,14 @@ namespace Code.Gameplay.Enemies
|
||||
private bool _isSpawning;
|
||||
private bool _isPlayerInRange;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_playerProvider == null || _enemyFactory == null)
|
||||
{
|
||||
AttributeInjector.Inject(this, Container.ProjectContainer);
|
||||
}
|
||||
}
|
||||
// GameObjectSelfInjector существует
|
||||
// private void Awake()
|
||||
// {
|
||||
// if (_playerProvider == null || _enemyFactory == null)
|
||||
// {
|
||||
// AttributeInjector.Inject(this, Container.ProjectContainer);
|
||||
// }
|
||||
// }
|
||||
|
||||
private void Update()
|
||||
{
|
||||
@@ -64,9 +63,14 @@ namespace Code.Gameplay.Enemies
|
||||
_isSpawning = false;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Despawn();
|
||||
}
|
||||
|
||||
private void Despawn()
|
||||
{
|
||||
if (_spawnedEnemy == null) return;
|
||||
if (!_spawnedEnemy) return;
|
||||
|
||||
_enemyFactory.ReleaseEnemy(_spawnedEnemy);
|
||||
_spawnedEnemy = null;
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Code.Gameplay.Orders.Order
|
||||
}
|
||||
public void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (!_pickupMode) return;
|
||||
if (!_pickupMode || !other.CompareTag("Player")) return;
|
||||
|
||||
_orderService.OrderRecieved();
|
||||
Destroy(gameObject);
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Code.Gameplay.Orders.Order
|
||||
private bool _playerEntered;
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (_playerEntered) return;
|
||||
if (_playerEntered ) return;
|
||||
|
||||
_playerEntered = true;
|
||||
_orderService.OrderDelivered();
|
||||
|
||||
@@ -14,18 +14,20 @@ namespace Code.Gameplay.Orders.Order
|
||||
hatch.DORotate(new Vector3(-130f, 0, 0), 0.2f);
|
||||
|
||||
order.rigidbody.isKinematic = false;
|
||||
order.rigidbody.AddForce(-transform.forward * 10f, ForceMode.Impulse);
|
||||
order.rigidbody.AddForce(-transform.forward * 1f, ForceMode.Impulse);
|
||||
|
||||
order.SwitchMode();
|
||||
}
|
||||
|
||||
// DEBUG TODO ДИМКА УДАЛИ И ПРОПИШИ В СВОЕЙ ЛОГИКЕ
|
||||
public void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if(_activated) return;
|
||||
_activated = true;
|
||||
|
||||
ThrowOrder();
|
||||
order.SwitchMode();
|
||||
}
|
||||
// public void OnTriggerEnter(Collider other)
|
||||
// {
|
||||
// if(_activated) return;
|
||||
// _activated = true;
|
||||
//
|
||||
// ThrowOrder();
|
||||
// order.SwitchMode();
|
||||
// }
|
||||
// DEBUG
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace Code.Gameplay.Orders.Order
|
||||
private bool _playerEntered;
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (_playerEntered) return;
|
||||
if (_playerEntered ) return;
|
||||
|
||||
_playerEntered = true;
|
||||
_orderService.OrderGive();
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Gameplay.Orders.Order
|
||||
{
|
||||
public class RoomDispenserTrigger : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private OrderDispenser orderDispenser;
|
||||
private bool _playerEntered;
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (_playerEntered ) return;
|
||||
orderDispenser.ThrowOrder();
|
||||
_playerEntered = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 630780fe69aa45eda7d4bcf966516c7d
|
||||
timeCreated: 1764313014
|
||||
@@ -0,0 +1,32 @@
|
||||
using Code.Audio;
|
||||
using Reflex.Attributes;
|
||||
using UnityEngine;
|
||||
using AudioType = Code.Audio.AudioType;
|
||||
|
||||
namespace Code.Gameplay.Player
|
||||
{
|
||||
public class PlayerAudio : MonoBehaviour
|
||||
{
|
||||
private IAudioService _audioService;
|
||||
private IAudioFactory _audioFactory;
|
||||
private AudioSource _audioSource;
|
||||
|
||||
[Inject]
|
||||
private void Construct(IAudioService audioService, IAudioFactory audioFactory)
|
||||
{
|
||||
_audioService = audioService;
|
||||
_audioSource = audioService.GetSourceOfGroup(AudioType.Courier);
|
||||
|
||||
_audioFactory = audioFactory;
|
||||
}
|
||||
|
||||
public void PlayStep()
|
||||
{
|
||||
_audioSource.PlayOneShot(_audioFactory.CourierAudios[(int)CourierSounds.Step]);
|
||||
}
|
||||
private void OnDestroy()
|
||||
{
|
||||
_audioService.ReleaseSourceOfGroup(_audioSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64f99dccce9d41df98accae0f355dbca
|
||||
timeCreated: 1764584350
|
||||
@@ -42,7 +42,13 @@ namespace Code.Gameplay.Player
|
||||
Addressables.ReleaseInstance(characterProvider.gameObject);
|
||||
}
|
||||
|
||||
public async UniTask<ArmsMeshProvider> CreateArms(Transform papochka) => (await Addressables.InstantiateAsync(_playerConfig.armsMeshPrefab, papochka).ToUniTask()).GetComponent<ArmsMeshProvider>();
|
||||
public async UniTask<ArmsMeshProvider> CreateArms(Transform papochka)
|
||||
{
|
||||
var armsMesh = (await Addressables.InstantiateAsync(_playerConfig.armsMeshPrefab, papochka).ToUniTask());
|
||||
GameObjectInjector.InjectRecursive(armsMesh, Container.ProjectContainer);
|
||||
|
||||
return armsMesh.GetComponent<ArmsMeshProvider>();
|
||||
}
|
||||
public void ReleaseArms(ArmsMeshProvider arms) => Addressables.ReleaseInstance(arms.gameObject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b32d6ce440f44fd3abadaa489a44890c
|
||||
timeCreated: 1762797763
|
||||
@@ -0,0 +1,11 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Code.Generator
|
||||
{
|
||||
[CreateAssetMenu(menuName = "Config/GeneratorConfig", fileName = "GeneratorConfig")]
|
||||
public class GeneratorConfig : ScriptableObject
|
||||
{
|
||||
public AssetReference[] roomAssetReferences;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a7c77305de54155b5b94b607531ee3c
|
||||
timeCreated: 1762453750
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
using Code.Gameplay.Orders.Order;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Generator
|
||||
{
|
||||
public interface IRoomGeneratorFactory
|
||||
{
|
||||
UniTask PreloadRooms(IOrderService orderService);
|
||||
GameObject GetCachedPrefab(int index, RoomType roomType);
|
||||
Room CreateRoomByIndex(int index, RoomType roomType);
|
||||
void ReleaseRooms();
|
||||
GameObject GetRandomCachedPrefabOfType(RoomType roomType, out int index);
|
||||
int GetRandomIndexOfType(RoomType roomType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3fca4115e714519b869eb72d856e89f
|
||||
timeCreated: 1762453657
|
||||
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Generator
|
||||
{
|
||||
public class InitialRoom : Room
|
||||
{
|
||||
public Transform playerSpawn;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4245aa5c87c7455ebad11edaad3b649e
|
||||
timeCreated: 1764324045
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using Code.Gameplay.Door;
|
||||
using Code.Gameplay.Orders.Order;
|
||||
using Code.UI;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Generator
|
||||
{
|
||||
// Для написания нормальной системы комнат нужен другой подход в корне, это уже не исправить, только залатать большие дыры
|
||||
public class Room : MonoBehaviour
|
||||
{
|
||||
[SerializeField] protected RoomType roomType;
|
||||
public RoomType RoomType => roomType;
|
||||
[SerializeField] protected float roomTimer;
|
||||
public float RoomTimer => roomTimer;
|
||||
[SerializeField] protected Transform enterMarker;
|
||||
public Transform EnterMarker => enterMarker;
|
||||
[SerializeField] protected Transform exitMarker;
|
||||
[SerializeField] protected Transform doorSlot;
|
||||
public Transform ExitMarker => exitMarker;
|
||||
[SerializeField] protected Door door;
|
||||
|
||||
public void Initialize(IOrderService orderService)
|
||||
{
|
||||
door.TranslationMode(false);
|
||||
|
||||
if(roomTrigger) roomTrigger.OrderService = orderService;
|
||||
}
|
||||
public void Seal() => door.CloseTheDoor();
|
||||
[SerializeField] public RoomTrigger roomTrigger;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ba1a19c534f4401aa287d4b68ce470c
|
||||
timeCreated: 1762014278
|
||||
@@ -0,0 +1,276 @@
|
||||
using System.Collections.Generic;
|
||||
using Code.Gameplay.Orders.Order;
|
||||
using Code.Scenes;
|
||||
using Code.Scenes.SceneEnvironments;
|
||||
using Reflex.Attributes;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Generator
|
||||
{
|
||||
public class RoomGenerator
|
||||
{
|
||||
[Inject] private IOrderService _orderService;
|
||||
|
||||
[Inject] private GeneratorConfig generatorConfig;
|
||||
|
||||
[Inject] private IRoomGeneratorFactory _factory;
|
||||
|
||||
private List<RoomIndex> _roomIndexesStack;
|
||||
|
||||
private struct RoomIndex
|
||||
{
|
||||
public RoomType RoomType;
|
||||
public int Index;
|
||||
|
||||
public RoomIndex(RoomType roomType, int index)
|
||||
{
|
||||
RoomType = roomType;
|
||||
Index = index;
|
||||
}
|
||||
}
|
||||
|
||||
private List<Room> _spawnedRooms;
|
||||
|
||||
private int _nextRoomStackIndex;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_spawnedRooms = new List<Room>();
|
||||
_roomIndexesStack = new();
|
||||
|
||||
_orderService.OnOrderGiven += CreateRoomsStack;
|
||||
CreateInitialRoom();
|
||||
}
|
||||
|
||||
private void OnPlayerEntered()
|
||||
{
|
||||
SpawnNextRoom();
|
||||
|
||||
if (_spawnedRooms.Count > 3)
|
||||
{
|
||||
Room roomToRemove = _spawnedRooms[0];
|
||||
_spawnedRooms.RemoveAt(0);
|
||||
|
||||
Object.Destroy(roomToRemove.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateRoomsStack(float timer)
|
||||
{
|
||||
_nextRoomStackIndex = 0;
|
||||
_roomIndexesStack.Clear();
|
||||
|
||||
var remainingTime = timer;
|
||||
|
||||
while (remainingTime > 0)
|
||||
{
|
||||
var prefab = _factory.GetRandomCachedPrefabOfType(RoomType.Basic, out int roomIndex);
|
||||
|
||||
Room room = prefab.GetComponent<Room>();
|
||||
|
||||
_roomIndexesStack.Add(new(RoomType.Basic, roomIndex));
|
||||
remainingTime -= room.RoomTimer;
|
||||
}
|
||||
|
||||
AddPickupRoom();
|
||||
|
||||
AddSaveRoom();
|
||||
|
||||
SpawnNextRoom();
|
||||
}
|
||||
|
||||
private void AddSaveRoom()
|
||||
{
|
||||
int saveRoomIndex = _factory.GetRandomIndexOfType(RoomType.Save);
|
||||
|
||||
_roomIndexesStack.Add(new(RoomType.Save, saveRoomIndex));
|
||||
}
|
||||
|
||||
private void AddPickupRoom()
|
||||
{
|
||||
int pickupIndex = _factory.GetRandomIndexOfType(RoomType.PickUp);
|
||||
|
||||
int insertPos = Random.Range(1, _roomIndexesStack.Count + 1);
|
||||
|
||||
_roomIndexesStack.Insert(insertPos, new(RoomType.PickUp, pickupIndex));
|
||||
}
|
||||
|
||||
[Inject] private CurrentSceneEnvironment _currentSceneEnvironment;
|
||||
|
||||
private void CreateInitialRoom()
|
||||
{
|
||||
GameplaySceneEnvironment gameplaySceneEnvironment = (GameplaySceneEnvironment)_currentSceneEnvironment;
|
||||
|
||||
int roomIndex = _factory.GetRandomIndexOfType(RoomType.Initial);
|
||||
|
||||
InitialRoom instantiated = _factory.CreateRoomByIndex(roomIndex, RoomType.Initial).GetComponent<InitialRoom>();
|
||||
_spawnedRooms.Add(instantiated);
|
||||
instantiated.transform.position = Vector3.zero;
|
||||
instantiated.transform.rotation = Quaternion.identity;
|
||||
|
||||
gameplaySceneEnvironment.playerSpawnPoint = instantiated.playerSpawn;
|
||||
instantiated.Initialize(_orderService);
|
||||
}
|
||||
private void SpawnNextRoom()
|
||||
{
|
||||
if (_nextRoomStackIndex >= _roomIndexesStack.Count)
|
||||
return;
|
||||
|
||||
RoomIndex index = _roomIndexesStack[_nextRoomStackIndex];
|
||||
Room room = _factory.CreateRoomByIndex(index.Index, index.RoomType);
|
||||
|
||||
if (_spawnedRooms.Count == 0)
|
||||
{
|
||||
room.transform.position = Vector3.zero;
|
||||
room.transform.rotation = Quaternion.identity;
|
||||
}
|
||||
else
|
||||
{
|
||||
Room previousRoom = _spawnedRooms[_spawnedRooms.Count - 1];
|
||||
PlaceRoom(room, previousRoom);
|
||||
}
|
||||
|
||||
// Отписываться можно, но Хатико никогда не дождётся вызова уничтоженного объекта.
|
||||
room.roomTrigger.OnEnter += OnPlayerEntered;
|
||||
|
||||
room.roomTrigger.OnExit += _spawnedRooms[^1].Seal;
|
||||
_spawnedRooms.Add(room);
|
||||
_nextRoomStackIndex++;
|
||||
}
|
||||
|
||||
|
||||
private void PlaceRoom(Room current, Room previous)
|
||||
{
|
||||
if (current.EnterMarker == null || previous.ExitMarker == null)
|
||||
return;
|
||||
|
||||
Vector3 segmentOriginPosition = previous.ExitMarker.transform.position;
|
||||
|
||||
Transform randomDoorOrigin = current.EnterMarker;
|
||||
Vector3 randomDoorOriginPosition = randomDoorOrigin.localPosition * current.transform.localScale.x;
|
||||
Quaternion randomDoorOriginRotation = randomDoorOrigin.localRotation;
|
||||
|
||||
float segmentOriginYRotation;
|
||||
|
||||
float entityRotation = previous.ExitMarker.transform.rotation.eulerAngles.y;
|
||||
if (entityRotation > 305f) entityRotation -= 360f;
|
||||
else if (entityRotation < -45f) entityRotation += 360f;
|
||||
|
||||
if (entityRotation > 135f)
|
||||
segmentOriginYRotation = entityRotation - randomDoorOriginRotation.eulerAngles.y + 180f;
|
||||
else
|
||||
segmentOriginYRotation = entityRotation - randomDoorOriginRotation.eulerAngles.y - 180f;
|
||||
|
||||
if (segmentOriginYRotation < -45f) segmentOriginYRotation += 360f;
|
||||
else if (segmentOriginYRotation > 305f) segmentOriginYRotation -= 360f;
|
||||
else if (segmentOriginYRotation < -305f) segmentOriginYRotation += 720f;
|
||||
|
||||
if (segmentOriginYRotation is > -45f and < 45f)
|
||||
{
|
||||
segmentOriginPosition.x -= randomDoorOriginPosition.x;
|
||||
segmentOriginPosition.z -= randomDoorOriginPosition.z;
|
||||
}
|
||||
else if (segmentOriginYRotation is >= 45f and < 135f)
|
||||
{
|
||||
segmentOriginPosition.x -= randomDoorOriginPosition.z;
|
||||
segmentOriginPosition.z += randomDoorOriginPosition.x;
|
||||
}
|
||||
else if (segmentOriginYRotation is >= 135f and < 225f)
|
||||
{
|
||||
segmentOriginPosition.x += randomDoorOriginPosition.x;
|
||||
segmentOriginPosition.z += randomDoorOriginPosition.z;
|
||||
}
|
||||
else if (segmentOriginYRotation is >= 225f and < 305f)
|
||||
{
|
||||
segmentOriginPosition.x += randomDoorOriginPosition.z;
|
||||
segmentOriginPosition.z -= randomDoorOriginPosition.x;
|
||||
}
|
||||
|
||||
segmentOriginPosition.y -= randomDoorOriginPosition.y;
|
||||
current.transform.position = segmentOriginPosition;
|
||||
current.transform.rotation = Quaternion.Euler(0, segmentOriginYRotation, 0);
|
||||
current.Initialize(_orderService);
|
||||
}
|
||||
}
|
||||
}
|
||||
// private void CreateRoomsStackDimka()
|
||||
// {
|
||||
// _roomIndexesStack.Clear();
|
||||
// var remainingTime = _orderService.DeliveryTimer;
|
||||
// float ladderTimer = 0f;
|
||||
// int totalRooms = generatorConfig.roomAssetReferences.Length;
|
||||
// List<int> availableIndexes = new List<int>();
|
||||
// for (int i = 0; i < totalRooms; i++)
|
||||
// availableIndexes.Add(i);
|
||||
//
|
||||
// int saveIndex = FindRoomIndexByType(RoomType.Save);
|
||||
// if (saveIndex != -1)
|
||||
// {
|
||||
// var prefab = _factory.GetCachedPrefab(saveIndex);
|
||||
// if (prefab != null)
|
||||
// {
|
||||
// Room saveRoom = prefab.GetComponent<Room>();
|
||||
// if (saveRoom != null)
|
||||
// {
|
||||
// _roomIndexesStack.Add(saveIndex);
|
||||
// availableIndexes.Remove(saveIndex);
|
||||
//
|
||||
// Debug.Log($"Первая комната: {saveRoom.name}");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// while (remainingTime > 0 && availableIndexes.Count > 0)
|
||||
// {
|
||||
// int randomIndex = Random.Range(0, availableIndexes.Count);
|
||||
// int chosenOne = availableIndexes[randomIndex];
|
||||
//
|
||||
// var prefab = _factory.GetCachedPrefab(chosenOne);
|
||||
// if (prefab == null)
|
||||
// continue;
|
||||
//
|
||||
// Room room = prefab.GetComponent<Room>();
|
||||
// if (room == null)
|
||||
// continue;
|
||||
//
|
||||
// switch (room.RoomType)
|
||||
// {
|
||||
// case RoomType.Save or RoomType.PickUp:
|
||||
// availableIndexes.RemoveAt(randomIndex);
|
||||
// continue;
|
||||
//
|
||||
// case RoomType.Basic:
|
||||
// float currentRoomTime = room.RoomTimer;
|
||||
// if (remainingTime >= currentRoomTime && ladderTimer < 30f)
|
||||
// {
|
||||
// _roomIndexesStack.Add(chosenOne);
|
||||
// remainingTime -= currentRoomTime;
|
||||
// ladderTimer += currentRoomTime;
|
||||
// Debug.Log($"комната {room.name} время {currentRoomTime} осталось: {remainingTime}");
|
||||
// }
|
||||
//
|
||||
// availableIndexes.RemoveAt(randomIndex);
|
||||
// break;
|
||||
//
|
||||
// case RoomType.Ladder:
|
||||
// if (ladderTimer >= 30f)
|
||||
// {
|
||||
// _roomIndexesStack.Add(chosenOne);
|
||||
// ladderTimer = 0f;
|
||||
//
|
||||
// availableIndexes.RemoveAt(randomIndex);
|
||||
// Debug.Log($"Лестница ура {room.name}");
|
||||
// }
|
||||
//
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// Debug.Log($"тип комнаты {room.RoomType}");
|
||||
// availableIndexes.RemoveAt(randomIndex);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// AddPickupRoom();
|
||||
// Debug.Log($"стек комнат: {_roomIndexesStack.Count}");
|
||||
// }
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 353230beca35458dafc91c6409c25ab3
|
||||
timeCreated: 1762014615
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Code.Configs;
|
||||
using Code.Gameplay.Orders.Order;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Reflex.Extensions;
|
||||
using Reflex.Injectors;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
using UnityEngine.SceneManagement;
|
||||
using Object = System.Object;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace Code.Generator
|
||||
{
|
||||
public class RoomGeneratorFactory : IRoomGeneratorFactory
|
||||
{
|
||||
private AsyncOperationHandle<IList<GameObject>> _roomsHandle;
|
||||
private readonly AssetReference[] _roomAssetReferences;
|
||||
private Dictionary<RoomType, List<GameObject>> _cashedRooms = new();
|
||||
|
||||
public RoomGeneratorFactory(GeneratorConfig generatorConfig)
|
||||
{
|
||||
_roomAssetReferences = generatorConfig.roomAssetReferences;
|
||||
// _cashedRooms = new GameObject[_roomAssetReferences.Length];
|
||||
_cashedRooms.Add(RoomType.Basic, new());
|
||||
_cashedRooms.Add(RoomType.Save, new ());
|
||||
_cashedRooms.Add(RoomType.PickUp, new ());
|
||||
_cashedRooms.Add(RoomType.Initial, new ());
|
||||
}
|
||||
|
||||
public async UniTask PreloadRooms(IOrderService orderService)
|
||||
{
|
||||
_roomsHandle =
|
||||
Addressables.LoadAssetsAsync<GameObject>(_roomAssetReferences, OnRoomLoaded, Addressables.MergeMode.Union);
|
||||
await _roomsHandle.ToUniTask();
|
||||
// _cashedRooms = rooms.ToArray(); var rooms =
|
||||
|
||||
// Debug.Log($"Комнат в памяти есть: {_cashedRooms.Length}");
|
||||
}
|
||||
|
||||
private void OnRoomLoaded(GameObject room)
|
||||
{
|
||||
var temp = room.GetComponent<Room>();
|
||||
_cashedRooms[temp.RoomType].Add(room);
|
||||
}
|
||||
public GameObject GetCachedPrefab(int index, RoomType roomType)
|
||||
{
|
||||
if (index < 0 || index >= _cashedRooms[roomType].Count)
|
||||
return null;
|
||||
return _cashedRooms[roomType][index];
|
||||
}
|
||||
public GameObject GetRandomCachedPrefabOfType(RoomType roomType, out int index)
|
||||
{
|
||||
index = Random.Range(0, _cashedRooms[roomType].Count);
|
||||
return _cashedRooms[roomType][index];
|
||||
}
|
||||
public int GetRandomIndexOfType(RoomType roomType) => Random.Range(0, _cashedRooms[roomType].Count);
|
||||
|
||||
public Room CreateRoomByIndex(int index, RoomType roomType)
|
||||
{
|
||||
var room = UnityEngine.Object.Instantiate(_cashedRooms[roomType][index]);
|
||||
return room.GetComponent<Room>();
|
||||
}
|
||||
public void ReleaseRooms()
|
||||
{
|
||||
_roomsHandle.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6e5b72284354ba79ec5b89cf06f1203
|
||||
timeCreated: 1762454256
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using Code.Gameplay.Orders.Order;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Generator
|
||||
{
|
||||
public class RoomTrigger : MonoBehaviour
|
||||
{
|
||||
public IOrderService OrderService;
|
||||
public event Action OnEnter;
|
||||
public event Action OnExit;
|
||||
|
||||
private bool _playerEntered, _playerExited;
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (_playerEntered) return;
|
||||
|
||||
_playerEntered = true;
|
||||
|
||||
OrderService.RoomPassed();
|
||||
|
||||
OnEnter?.Invoke();
|
||||
}
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (_playerExited) return;
|
||||
|
||||
Debug.Log(other.name);
|
||||
|
||||
_playerExited = true;
|
||||
|
||||
OnExit?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d6940d73d544f0a8e4a45d956bc2364
|
||||
timeCreated: 1764525516
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Code.Generator
|
||||
{
|
||||
public enum RoomType
|
||||
{
|
||||
Basic,
|
||||
Save,
|
||||
PickUp,
|
||||
Initial
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 304fa5ed27cc4bc3aabcfeb272206d89
|
||||
timeCreated: 1762945420
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e76fbbe72ad97cc4f9dfe770ddc79857
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
public class LightProbeRuntime : MonoBehaviour
|
||||
{
|
||||
public Color m_Ambient;
|
||||
Light[] m_Lights;
|
||||
|
||||
// Start is called before the first frame update
|
||||
IEnumerator Start()
|
||||
{
|
||||
yield return null;
|
||||
|
||||
m_Lights = FindObjectsOfType<Light>();
|
||||
SphericalHarmonicsL2[] bakedProbes = LightmapSettings.lightProbes.bakedProbes;
|
||||
Vector3[] probePositions = LightmapSettings.lightProbes.positions;
|
||||
int probeCount = LightmapSettings.lightProbes.count;
|
||||
|
||||
// Clear all probes
|
||||
for (int i = 0; i < probeCount; i++)
|
||||
bakedProbes[i].Clear();
|
||||
|
||||
// Add ambient light to all probes
|
||||
for (int i = 0; i < probeCount; i++)
|
||||
bakedProbes[i].AddAmbientLight(m_Ambient);
|
||||
|
||||
// Add directional and point lights' contribution to all probes
|
||||
foreach (Light l in m_Lights)
|
||||
{
|
||||
if (l.type == LightType.Directional)
|
||||
{
|
||||
for (int i = 0; i < probeCount; i++)
|
||||
bakedProbes[i].AddDirectionalLight(-l.transform.forward, l.color, l.intensity);
|
||||
}
|
||||
else if (l.type == LightType.Point)
|
||||
{
|
||||
for (int i = 0; i < probeCount; i++)
|
||||
SHAddPointLight(probePositions[i], l.transform.position, l.range, l.color, l.intensity, ref bakedProbes[i]);
|
||||
}
|
||||
}
|
||||
LightmapSettings.lightProbes.bakedProbes = bakedProbes;
|
||||
}
|
||||
|
||||
void SHAddPointLight(Vector3 probePosition, Vector3 position, float range, Color color, float intensity, ref SphericalHarmonicsL2 sh)
|
||||
{
|
||||
// From the point of view of an SH probe, point light looks no different than a directional light,
|
||||
// just attenuated and coming from the right direction.
|
||||
Vector3 probeToLight = position - probePosition;
|
||||
float attenuation = 1.0F / (1.0F + 25.0F * probeToLight.sqrMagnitude / (range * range));
|
||||
sh.AddDirectionalLight(probeToLight.normalized, color, intensity * attenuation);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9643888b3364f55439c6adf3309cc447
|
||||
@@ -0,0 +1,295 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
[ExecuteAlways]
|
||||
public class PrefabLightmapData : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Reassigns shaders when applying the baked lightmaps. Might conflict with some shaders like transparent HDRP.")]
|
||||
public bool releaseShaders = true;
|
||||
|
||||
[System.Serializable]
|
||||
struct RendererInfo
|
||||
{
|
||||
public Renderer renderer;
|
||||
public int lightmapIndex;
|
||||
public Vector4 lightmapOffsetScale;
|
||||
}
|
||||
[System.Serializable]
|
||||
struct LightInfo
|
||||
{
|
||||
public Light light;
|
||||
public int lightmapBaketype;
|
||||
public int mixedLightingMode;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
RendererInfo[] m_RendererInfo;
|
||||
[SerializeField]
|
||||
Texture2D[] m_Lightmaps;
|
||||
[SerializeField]
|
||||
Texture2D[] m_LightmapsDir;
|
||||
[SerializeField]
|
||||
Texture2D[] m_ShadowMasks;
|
||||
[SerializeField]
|
||||
LightInfo[] m_LightInfo;
|
||||
|
||||
|
||||
void Awake()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
if (m_RendererInfo == null || m_RendererInfo.Length == 0)
|
||||
return;
|
||||
|
||||
var lightmaps = LightmapSettings.lightmaps;
|
||||
int[] offsetsindexes = new int[m_Lightmaps.Length];
|
||||
int counttotal = lightmaps.Length;
|
||||
List<LightmapData> combinedLightmaps = new List<LightmapData>();
|
||||
|
||||
for (int i = 0; i < m_Lightmaps.Length; i++)
|
||||
{
|
||||
bool exists = false;
|
||||
for (int j = 0; j < lightmaps.Length; j++)
|
||||
{
|
||||
|
||||
if (m_Lightmaps[i] == lightmaps[j].lightmapColor)
|
||||
{
|
||||
exists = true;
|
||||
offsetsindexes[i] = j;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if (!exists)
|
||||
{
|
||||
offsetsindexes[i] = counttotal;
|
||||
var newlightmapdata = new LightmapData
|
||||
{
|
||||
lightmapColor = m_Lightmaps[i],
|
||||
lightmapDir = m_LightmapsDir.Length == m_Lightmaps.Length ? m_LightmapsDir[i] : default(Texture2D),
|
||||
shadowMask = m_ShadowMasks.Length == m_Lightmaps.Length ? m_ShadowMasks[i] : default(Texture2D),
|
||||
};
|
||||
|
||||
combinedLightmaps.Add(newlightmapdata);
|
||||
|
||||
counttotal += 1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var combinedLightmaps2 = new LightmapData[counttotal];
|
||||
|
||||
lightmaps.CopyTo(combinedLightmaps2, 0);
|
||||
combinedLightmaps.ToArray().CopyTo(combinedLightmaps2, lightmaps.Length);
|
||||
|
||||
bool directional=true;
|
||||
|
||||
foreach(Texture2D t in m_LightmapsDir)
|
||||
{
|
||||
if (t == null)
|
||||
{
|
||||
directional = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LightmapSettings.lightmapsMode = (m_LightmapsDir.Length == m_Lightmaps.Length && directional) ? LightmapsMode.CombinedDirectional : LightmapsMode.NonDirectional;
|
||||
ApplyRendererInfo(m_RendererInfo, offsetsindexes, m_LightInfo);
|
||||
LightmapSettings.lightmaps = combinedLightmaps2;
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
|
||||
}
|
||||
|
||||
// called second
|
||||
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
// called when the game is terminated
|
||||
void OnDisable()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ApplyRendererInfo(RendererInfo[] infos, int[] lightmapOffsetIndex, LightInfo[] lightsInfo)
|
||||
{
|
||||
for (int i = 0; i < infos.Length; i++)
|
||||
{
|
||||
var info = infos[i];
|
||||
|
||||
info.renderer.lightmapIndex = lightmapOffsetIndex[info.lightmapIndex];
|
||||
info.renderer.lightmapScaleOffset = info.lightmapOffsetScale;
|
||||
|
||||
if (releaseShaders)
|
||||
{
|
||||
// You have to release shaders.
|
||||
Material[] mat = info.renderer.sharedMaterials;
|
||||
for (int j = 0; j < mat.Length; j++)
|
||||
{
|
||||
if (mat[j] != null && Shader.Find(mat[j].shader.name) != null)
|
||||
{
|
||||
mat[j].shader = Shader.Find(mat[j].shader.name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0; i < lightsInfo.Length; i++)
|
||||
{
|
||||
LightBakingOutput bakingOutput = new LightBakingOutput();
|
||||
bakingOutput.isBaked = true;
|
||||
bakingOutput.lightmapBakeType = (LightmapBakeType)lightsInfo[i].lightmapBaketype;
|
||||
bakingOutput.mixedLightingMode = (MixedLightingMode)lightsInfo[i].mixedLightingMode;
|
||||
|
||||
lightsInfo[i].light.bakingOutput = bakingOutput;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.MenuItem("Assets/Bake Prefab Lightmaps")]
|
||||
static void GenerateLightmapInfo()
|
||||
{
|
||||
if (UnityEditor.Lightmapping.giWorkflowMode != UnityEditor.Lightmapping.GIWorkflowMode.OnDemand)
|
||||
{
|
||||
Debug.LogError("ExtractLightmapData requires that you have baked you lightmaps and Auto mode is disabled.");
|
||||
return;
|
||||
}
|
||||
UnityEditor.Lightmapping.Bake();
|
||||
|
||||
PrefabLightmapData[] prefabs = FindObjectsOfType<PrefabLightmapData>();
|
||||
|
||||
foreach (var instance in prefabs)
|
||||
{
|
||||
var gameObject = instance.gameObject;
|
||||
var rendererInfos = new List<RendererInfo>();
|
||||
var lightmaps = new List<Texture2D>();
|
||||
var lightmapsDir = new List<Texture2D>();
|
||||
var shadowMasks = new List<Texture2D>();
|
||||
var lightsInfos = new List<LightInfo>();
|
||||
|
||||
GenerateLightmapInfo(gameObject, rendererInfos, lightmaps, lightmapsDir, shadowMasks, lightsInfos);
|
||||
|
||||
instance.m_RendererInfo = rendererInfos.ToArray();
|
||||
instance.m_Lightmaps = lightmaps.ToArray();
|
||||
instance.m_LightmapsDir = lightmapsDir.ToArray();
|
||||
instance.m_LightInfo = lightsInfos.ToArray();
|
||||
instance.m_ShadowMasks = shadowMasks.ToArray();
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
var targetPrefab = PrefabUtility.GetCorrespondingObjectFromOriginalSource(instance.gameObject) as GameObject;
|
||||
if (targetPrefab != null)
|
||||
{
|
||||
GameObject root = PrefabUtility.GetOutermostPrefabInstanceRoot(instance.gameObject);// 根结点
|
||||
//如果当前预制体是是某个嵌套预制体的一部分(IsPartOfPrefabInstance)
|
||||
if (root != null)
|
||||
{
|
||||
GameObject rootPrefab = PrefabUtility.GetCorrespondingObjectFromSource(instance.gameObject);
|
||||
string rootPath = AssetDatabase.GetAssetPath(rootPrefab);
|
||||
//打开根部预制体
|
||||
PrefabUtility.UnpackPrefabInstanceAndReturnNewOutermostRoots(root, PrefabUnpackMode.OutermostRoot);
|
||||
try
|
||||
{
|
||||
//Apply各个子预制体的改变
|
||||
PrefabUtility.ApplyPrefabInstance(instance.gameObject, InteractionMode.AutomatedAction);
|
||||
}
|
||||
catch { }
|
||||
finally
|
||||
{
|
||||
//重新更新根预制体
|
||||
PrefabUtility.SaveAsPrefabAssetAndConnect(root, rootPath, InteractionMode.AutomatedAction);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PrefabUtility.ApplyPrefabInstance(instance.gameObject, InteractionMode.AutomatedAction);
|
||||
}
|
||||
}
|
||||
#else
|
||||
var targetPrefab = UnityEditor.PrefabUtility.GetPrefabParent(gameObject) as GameObject;
|
||||
if (targetPrefab != null)
|
||||
{
|
||||
//UnityEditor.Prefab
|
||||
UnityEditor.PrefabUtility.ReplacePrefab(gameObject, targetPrefab);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void GenerateLightmapInfo(GameObject root, List<RendererInfo> rendererInfos, List<Texture2D> lightmaps, List<Texture2D> lightmapsDir, List<Texture2D> shadowMasks, List<LightInfo> lightsInfo)
|
||||
{
|
||||
var renderers = root.GetComponentsInChildren<MeshRenderer>();
|
||||
foreach (MeshRenderer renderer in renderers)
|
||||
{
|
||||
if (renderer.lightmapIndex != -1)
|
||||
{
|
||||
RendererInfo info = new RendererInfo();
|
||||
info.renderer = renderer;
|
||||
|
||||
if (renderer.lightmapScaleOffset != Vector4.zero)
|
||||
{
|
||||
//1ibrium's pointed out this issue : https://docs.unity3d.com/ScriptReference/Renderer-lightmapIndex.html
|
||||
if(renderer.lightmapIndex < 0 || renderer.lightmapIndex == 0xFFFE) continue;
|
||||
info.lightmapOffsetScale = renderer.lightmapScaleOffset;
|
||||
|
||||
Texture2D lightmap = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapColor;
|
||||
Texture2D lightmapDir = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapDir;
|
||||
Texture2D shadowMask = LightmapSettings.lightmaps[renderer.lightmapIndex].shadowMask;
|
||||
|
||||
info.lightmapIndex = lightmaps.IndexOf(lightmap);
|
||||
if (info.lightmapIndex == -1)
|
||||
{
|
||||
info.lightmapIndex = lightmaps.Count;
|
||||
lightmaps.Add(lightmap);
|
||||
lightmapsDir.Add(lightmapDir);
|
||||
shadowMasks.Add(shadowMask);
|
||||
}
|
||||
|
||||
rendererInfos.Add(info);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var lights = root.GetComponentsInChildren<Light>(true);
|
||||
|
||||
foreach (Light l in lights)
|
||||
{
|
||||
LightInfo lightInfo = new LightInfo();
|
||||
lightInfo.light = l;
|
||||
lightInfo.lightmapBaketype = (int)l.lightmapBakeType;
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
lightInfo.mixedLightingMode = (int)UnityEditor.Lightmapping.lightingSettings.mixedBakeMode;
|
||||
#elif UNITY_2018_1_OR_NEWER
|
||||
lightInfo.mixedLightingMode = (int)UnityEditor.LightmapEditorSettings.mixedBakeMode;
|
||||
#else
|
||||
lightInfo.mixedLightingMode = (int)l.bakingOutput.lightmapBakeType;
|
||||
#endif
|
||||
lightsInfo.Add(lightInfo);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b91f32cd81021d24ab9ff545997e9666
|
||||
@@ -1,5 +1,6 @@
|
||||
using Code.Gameplay.Orders.Order;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Code.Scenes.SceneEnvironments
|
||||
@@ -8,12 +9,12 @@ namespace Code.Scenes.SceneEnvironments
|
||||
public class GameplaySceneEnvironment : CurrentSceneEnvironment
|
||||
{
|
||||
public Transform playerSpawnPoint;
|
||||
public OrderDispenser debugTube;
|
||||
public Volume volume;
|
||||
|
||||
public void TransitVariables(GameplaySceneEnvironment env)
|
||||
{
|
||||
playerSpawnPoint = env.playerSpawnPoint;
|
||||
debugTube = env.debugTube;
|
||||
volume = env.volume;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using System.Threading.Tasks;
|
||||
using Code.Audio;
|
||||
using Code.Configs;
|
||||
using Code.Gameplay.Camera;
|
||||
using Code.Generator;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
@@ -31,6 +32,9 @@ namespace Code.StaticData
|
||||
Dictionary<CameraMode, CameraSettingsConfig> CameraSettingsConfigs { get; }
|
||||
Dictionary<AudioSourceType, AudioSourceSettingsConfig> AudioSourceSettingsConfigs { get; }
|
||||
AudioTestClipsConfig AudioTestClipsConfig { get; }
|
||||
GeneratorConfig GeneratorConfig { get; }
|
||||
CourierSoundListConfig CourierSoundListConfig { get; }
|
||||
DefaultAudioSettingsConfig DefaultAudioSettingsConfig { get; }
|
||||
void Load();
|
||||
Task<T> InstantiateAsset<T>(AssetReference assetReference) where T : Behaviour;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using Code.Audio;
|
||||
using Code.Configs;
|
||||
using Code.Constants;
|
||||
using Code.Gameplay.Camera;
|
||||
using Code.Generator;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
@@ -28,6 +29,8 @@ namespace Code.StaticData
|
||||
public DispatcherSoundListConfig DispatcherSoundListConfig { get; private set; }
|
||||
public EnemiesSoundListConfig EnemiesSoundListConfig { get; private set; }
|
||||
public AudioTestClipsConfig AudioTestClipsConfig { get; private set; }
|
||||
public CourierSoundListConfig CourierSoundListConfig { get; private set; }
|
||||
public DefaultAudioSettingsConfig DefaultAudioSettingsConfig { get; private set; }
|
||||
|
||||
public DrunkenGrandpaConfig DrunkenGrandpaConfig {get; private set;}
|
||||
public CockroachConfig CockroachConfig { get; private set; }
|
||||
@@ -36,6 +39,8 @@ namespace Code.StaticData
|
||||
public OrderServiceConfig OrderServiceConfig { get; private set; }
|
||||
public OrderBoxConfig OrderBoxConfig { get; private set; }
|
||||
|
||||
public GeneratorConfig GeneratorConfig { get; private set; }
|
||||
|
||||
public Dictionary<CameraMode, CameraSettingsConfig> CameraSettingsConfigs { get; private set; } = new();
|
||||
|
||||
public Dictionary<AudioSourceType, AudioSourceSettingsConfig> AudioSourceSettingsConfigs { get; private set; } = new();
|
||||
@@ -49,6 +54,7 @@ namespace Code.StaticData
|
||||
PlayerConfig = Resources.Load<PlayerConfig>(string.Format(StringPaths.ConfigSingle, "App", "PlayerConfig"));
|
||||
OrderServiceConfig = Resources.Load<OrderServiceConfig>(string.Format(StringPaths.ConfigSingle, "Gameplay", "OrderServiceConfig"));
|
||||
OrderBoxConfig = Resources.Load<OrderBoxConfig>(string.Format(StringPaths.ConfigSingle, "Gameplay", "OrderBoxConfig"));
|
||||
GeneratorConfig = Resources.Load<GeneratorConfig>(string.Format(StringPaths.ConfigSingle, "App", "GeneratorConfig"));
|
||||
|
||||
CameraConfig = Resources.Load<CameraConfig>(string.Format(StringPaths.ConfigSingle, "Camera", "CameraConfig"));
|
||||
CameraSettingsConfigs = Resources
|
||||
@@ -62,9 +68,11 @@ namespace Code.StaticData
|
||||
private void LoadAudioConfigs()
|
||||
{
|
||||
AudioMixerConfig = Resources.Load<AudioMixerConfig>(string.Format(StringPaths.ConfigSingle, "Audio", "AudioMixerConfig"));
|
||||
DefaultAudioSettingsConfig = Resources.Load<DefaultAudioSettingsConfig>(string.Format(StringPaths.ConfigSingle, "Audio", "DefaultAudioSettingsConfig"));
|
||||
SoundtrackListConfig = Resources.Load<SoundtrackListConfig>(string.Format(StringPaths.ConfigSingle, "Audio", "SoundtrackListConfig"));
|
||||
AudioTestClipsConfig = Resources.Load<AudioTestClipsConfig>(string.Format(StringPaths.ConfigSingle, "Audio", "AudioTestClipsConfig"));
|
||||
SFXListConfig = Resources.Load<SFXListConfig>(string.Format(StringPaths.ConfigSingle, "Audio", "SFXListConfig"));
|
||||
CourierSoundListConfig = Resources.Load<CourierSoundListConfig>(string.Format(StringPaths.ConfigSingle, "Audio", "CourierSoundListConfig"));
|
||||
DispatcherSoundListConfig = Resources.Load<DispatcherSoundListConfig>(string.Format(StringPaths.ConfigSingle, "Audio", "DispatcherSoundListConfig"));
|
||||
EnemiesSoundListConfig = Resources.Load<EnemiesSoundListConfig>(string.Format(StringPaths.ConfigSingle, "Audio", "EnemiesSoundListConfig"));
|
||||
AudioSourceSettingsConfigs = Resources
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Code.UI.Panels
|
||||
{
|
||||
public class DamagePanel : UIElement
|
||||
{
|
||||
[SerializeField] private Image background;
|
||||
[SerializeField] private Color shownColor;
|
||||
[SerializeField] private Color hiddenColor;
|
||||
public override void Hide()
|
||||
{
|
||||
Shown = false;
|
||||
// background.enabled = false;
|
||||
background.DOColor(hiddenColor, 2f);
|
||||
}
|
||||
public override void Show()
|
||||
{
|
||||
Shown = true;
|
||||
// background.enabled = true;
|
||||
background.DOColor(shownColor, 0.3f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b586dbc292c44261892460f578a38e50
|
||||
timeCreated: 1764769541
|
||||
@@ -1,3 +1,4 @@
|
||||
using DG.Tweening;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
@@ -9,21 +10,27 @@ namespace Code.UI
|
||||
[SerializeField] private TMP_Text scoreText;
|
||||
[SerializeField] private TMP_Text gameOverText;
|
||||
[SerializeField] private Image _background;
|
||||
[SerializeField] private Color shownColor;
|
||||
[SerializeField] private Color hiddenColor;
|
||||
|
||||
public void UpdateScoreText(int score) => scoreText.text = score.ToString();
|
||||
|
||||
public override void Hide()
|
||||
{
|
||||
_background.enabled = false;
|
||||
scoreText.enabled = false;
|
||||
gameOverText.enabled = false;
|
||||
// scoreText.enabled = true;
|
||||
// gameOverText.enabled = false;
|
||||
scoreText.DOColor(hiddenColor, 3f);
|
||||
// gameOverText.DOColor(hiddenColor, 3f);
|
||||
base.Hide();
|
||||
}
|
||||
public override void Show()
|
||||
{
|
||||
_background.enabled = true;
|
||||
scoreText.enabled = true;
|
||||
gameOverText.enabled = true;
|
||||
// _background.enabled = true;
|
||||
// scoreText.enabled = true;
|
||||
// gameOverText.enabled = true;
|
||||
scoreText.DOColor(shownColor, 5f);
|
||||
// gameOverText.DOColor(shownColor, 5f);
|
||||
base.Show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace Code.UI.Panels
|
||||
[Header("MoneyBar")]
|
||||
[SerializeField] private TMP_Text moneyText;
|
||||
|
||||
[SerializeField] private DamagePanel damagePanel;
|
||||
public DamagePanel DamagePanel => damagePanel;
|
||||
|
||||
private void ScoreUpdate(int count, int money)
|
||||
{
|
||||
// TODO Анимация получения\потери
|
||||
|
||||
@@ -7,21 +7,24 @@ namespace Code.UI.Panels
|
||||
public class LoadingScreen : UIElement
|
||||
{
|
||||
[SerializeField] private Image background;
|
||||
[SerializeField] private TMP_Text loadingTitle;
|
||||
[SerializeField] private TMP_Text vyapWatermark;
|
||||
[SerializeField] private Image loadingImage;
|
||||
// [SerializeField] private TMP_Text loadingTitle;
|
||||
// [SerializeField] private TMP_Text vyapWatermark;
|
||||
public override void Hide()
|
||||
{
|
||||
Shown = false;
|
||||
background.enabled = false;
|
||||
loadingTitle.enabled = false;
|
||||
vyapWatermark.enabled = false;
|
||||
loadingImage.enabled = false;
|
||||
// loadingTitle.enabled = false;
|
||||
// vyapWatermark.enabled = false;
|
||||
}
|
||||
public override void Show()
|
||||
{
|
||||
Shown = true;
|
||||
background.enabled = true;
|
||||
loadingTitle.enabled = true;
|
||||
vyapWatermark.enabled = true;
|
||||
loadingImage.enabled = true;
|
||||
// loadingTitle.enabled = true;
|
||||
// vyapWatermark.enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ namespace Code.UI
|
||||
[SerializeField] private Slider master;
|
||||
[SerializeField] private Slider sfx;
|
||||
[SerializeField] private Slider dispatcher;
|
||||
[SerializeField] private Slider courier;
|
||||
[SerializeField] private Slider creatures;
|
||||
[SerializeField] private Slider menuMusic;
|
||||
[SerializeField] private Slider gameplayMusic;
|
||||
@@ -28,16 +29,19 @@ namespace Code.UI
|
||||
sfx.value = _audioService.GetSetting(AudioType.SFX);
|
||||
sfx.onValueChanged.AddListener(OnSFXUpdate);
|
||||
|
||||
dispatcher.value = _audioService.GetSetting(AudioType.DispatcherSounds);
|
||||
dispatcher.value = _audioService.GetSetting(AudioType.Dispatcher);
|
||||
dispatcher.onValueChanged.AddListener(OnDispatcherUpdate);
|
||||
|
||||
creatures.value = _audioService.GetSetting(AudioType.Creatures);
|
||||
courier.value = _audioService.GetSetting(AudioType.Courier);
|
||||
courier.onValueChanged.AddListener(OnCourierUpdate);
|
||||
|
||||
creatures.value = _audioService.GetSetting(AudioType.Enemies);
|
||||
creatures.onValueChanged.AddListener(OnEnemiesUpdate);
|
||||
|
||||
menuMusic.value = _audioService.GetSetting(AudioType.MenuMusic);
|
||||
menuMusic.onValueChanged.AddListener(OnMenuMusicUpdate);
|
||||
|
||||
gameplayMusic.value = _audioService.GetSetting(AudioType.GameplayMusic);
|
||||
gameplayMusic.value = _audioService.GetSetting(AudioType.ActionMusic);
|
||||
gameplayMusic.onValueChanged.AddListener(OnGameplayUpdate);
|
||||
}
|
||||
|
||||
@@ -51,25 +55,32 @@ namespace Code.UI
|
||||
_audioService.ChangeSetting(AudioType.SFX, value);
|
||||
_audioService.PlayTestClip(AudioType.SFX);
|
||||
}
|
||||
private void OnCourierUpdate(float value)
|
||||
{
|
||||
_audioService.ChangeSetting(AudioType.Courier, value);
|
||||
_audioService.PlayTestClip(AudioType.Courier);
|
||||
}
|
||||
private void OnDispatcherUpdate(float value)
|
||||
{
|
||||
_audioService.ChangeSetting(AudioType.DispatcherSounds, value);
|
||||
_audioService.PlayTestClip(AudioType.DispatcherSounds);
|
||||
_audioService.ChangeSetting(AudioType.Dispatcher, value);
|
||||
_audioService.PlayTestClip(AudioType.Dispatcher);
|
||||
}
|
||||
private void OnEnemiesUpdate(float value)
|
||||
{
|
||||
_audioService.ChangeSetting(AudioType.Creatures, value);
|
||||
_audioService.PlayTestClip(AudioType.Creatures);
|
||||
_audioService.ChangeSetting(AudioType.Enemies, value);
|
||||
_audioService.PlayTestClip(AudioType.Enemies);
|
||||
}
|
||||
private void OnMenuMusicUpdate(float value)
|
||||
{
|
||||
_audioService.ChangeSetting(AudioType.MenuMusic, value);
|
||||
_audioService.ChangeSetting(AudioType.DeathMusic, value);
|
||||
_audioService.PlayTestClip(AudioType.MenuMusic);
|
||||
}
|
||||
private void OnGameplayUpdate(float value)
|
||||
{
|
||||
_audioService.ChangeSetting(AudioType.GameplayMusic, value);
|
||||
_audioService.PlayTestClip(AudioType.GameplayMusic);
|
||||
_audioService.ChangeSetting(AudioType.ActionMusic, value);
|
||||
_audioService.ChangeSetting(AudioType.PeacefulMusic, value);
|
||||
_audioService.PlayTestClip(AudioType.ActionMusic);
|
||||
}
|
||||
|
||||
public override void Hide()
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45b4aa0e7c33e934493bb7d2a15a9add
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 767316a9a37abc34694c3086d846f668
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43bd94852ddc6b34dbe9fec318fb54d8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "AYellowpaper.SerializedCollections.Editor",
|
||||
"references": [
|
||||
"GUID:d525ad6bd40672747bde77962f1c401e"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 234340c04eed5674a988bc6ebde7d248
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 243052
|
||||
packageName: Serialized Dictionary
|
||||
packageVersion: 1.0.13
|
||||
assetPath: Assets/Plugins/SerializedCollections/Editor/AYellowpaper.SerializedCollections.Editor.asmdef
|
||||
uploadId: 632226
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: edb739dfb1824234681f6480c75cd523
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Binary file not shown.
Loaded 100 of 626 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user