integrated Audio system in player and enemies scripts; made ScriptableObjects for SFX Assets; modified AudioManager.cs by _sega to play random SFX from SFX Asset
This commit is contained in:
parent
4a750d9404
commit
09f10bd5be
@ -5078,4 +5078,11 @@ AnimationClip:
|
||||
flags: 16
|
||||
m_HasGenericRootTransform: 0
|
||||
m_HasMotionFloatCurves: 0
|
||||
m_Events: []
|
||||
m_Events:
|
||||
- time: 0.05
|
||||
functionName: Step
|
||||
data:
|
||||
objectReferenceParameter: {fileID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
|
||||
@ -10356,6 +10356,13 @@ AnimationClip:
|
||||
m_HasGenericRootTransform: 0
|
||||
m_HasMotionFloatCurves: 0
|
||||
m_Events:
|
||||
- time: 0
|
||||
functionName: OnDeathBegin
|
||||
data:
|
||||
objectReferenceParameter: {fileID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
- time: 1.25
|
||||
functionName: OnDeathEnd
|
||||
data:
|
||||
|
||||
@ -8287,9 +8287,9 @@ AnimationClip:
|
||||
m_HasMotionFloatCurves: 0
|
||||
m_Events:
|
||||
- time: 0
|
||||
functionName: PlaySfx
|
||||
functionName: Jump
|
||||
data:
|
||||
objectReferenceParameter: {fileID: 8300000, guid: fa0b6b9872cd9b84bb24e35b24e57fdf, type: 3}
|
||||
objectReferenceParameter: {fileID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
|
||||
@ -15829,23 +15829,23 @@ AnimationClip:
|
||||
m_HasMotionFloatCurves: 0
|
||||
m_Events:
|
||||
- time: 0.083333336
|
||||
functionName: PlaySfx
|
||||
functionName: Step
|
||||
data:
|
||||
objectReferenceParameter: {fileID: 8300000, guid: 144cba17f4a47274d834d5e1fc28acb9, type: 3}
|
||||
objectReferenceParameter: {fileID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
- time: 0.8833333
|
||||
functionName: PlaySfx
|
||||
functionName: Step
|
||||
data:
|
||||
objectReferenceParameter: {fileID: 8300000, guid: 144cba17f4a47274d834d5e1fc28acb9, type: 3}
|
||||
objectReferenceParameter: {fileID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
- time: 1.7
|
||||
functionName: PlaySfx
|
||||
functionName: Step
|
||||
data:
|
||||
objectReferenceParameter: {fileID: 8300000, guid: 144cba17f4a47274d834d5e1fc28acb9, type: 3}
|
||||
objectReferenceParameter: {fileID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1010,6 +1010,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
config: {fileID: 11400000, guid: d8fdc5ccf56a1ca4389e7927d0b86526, type: 2}
|
||||
sfxAsset: {fileID: 11400000, guid: 9cb4dd9d30f2420439e056018daf622a, type: 2}
|
||||
--- !u!114 &-3949889748814893039
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@ -1679,6 +1679,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
config: {fileID: 11400000, guid: d8fdc5ccf56a1ca4389e7927d0b86526, type: 2}
|
||||
sfxAsset: {fileID: 11400000, guid: 9cb4dd9d30f2420439e056018daf622a, type: 2}
|
||||
--- !u!114 &-7639911518411260797
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@ -2835,6 +2835,9 @@ MonoBehaviour:
|
||||
m_Bits: 64
|
||||
animator: {fileID: 0}
|
||||
maxHealth: 1
|
||||
stepSounds: {fileID: 11400000, guid: 37fe07ddcac109a46a86ba44df16d551, type: 2}
|
||||
hurtSounds: {fileID: 11400000, guid: 89e7f713913aecb40ada8c2f27c69303, type: 2}
|
||||
jumpSounds: {fileID: 11400000, guid: 9a63566742cc2d84c89928c8b988e4eb, type: 2}
|
||||
--- !u!114 &9068111837403598740
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -2868,6 +2871,7 @@ MonoBehaviour:
|
||||
launchAxis: {x: 1, y: 0}
|
||||
launchPoint: {fileID: 6550761234582043067}
|
||||
attachPoint: {fileID: 6550761234593413718}
|
||||
throwSounds: {fileID: 11400000, guid: 4b774d97282b77f45b08068d61682269, type: 2}
|
||||
--- !u!114 &-953906007136484429
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
8
Assets/SFX/Enemies.meta
Normal file
8
Assets/SFX/Enemies.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1843e8ef4c43772469423eda8873ec39
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/SFX/Enemies/Enemy_Hit_1.wav
Normal file
BIN
Assets/SFX/Enemies/Enemy_Hit_1.wav
Normal file
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f6a3b9402e60e9469e3b2cf9dd01ff3
|
||||
guid: 37f7526ec58db8843916100518133785
|
||||
AudioImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 8
|
||||
BIN
Assets/SFX/Enemies/Knife_Throw_1.wav
Normal file
BIN
Assets/SFX/Enemies/Knife_Throw_1.wav
Normal file
Binary file not shown.
23
Assets/SFX/Enemies/Knife_Throw_1.wav.meta
Normal file
23
Assets/SFX/Enemies/Knife_Throw_1.wav.meta
Normal file
@ -0,0 +1,23 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5084f4cf2fabc74fae40a5a9ebc2718
|
||||
AudioImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 8
|
||||
defaultSettings:
|
||||
serializedVersion: 2
|
||||
loadType: 0
|
||||
sampleRateSetting: 0
|
||||
sampleRateOverride: 44100
|
||||
compressionFormat: 1
|
||||
quality: 1
|
||||
conversionMode: 0
|
||||
preloadAudioData: 0
|
||||
platformSettingOverrides: {}
|
||||
forceToMono: 0
|
||||
normalize: 1
|
||||
loadInBackground: 0
|
||||
ambisonic: 0
|
||||
3D: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/SFX/Enemies/Knife_Throw_2.wav
Normal file
BIN
Assets/SFX/Enemies/Knife_Throw_2.wav
Normal file
Binary file not shown.
23
Assets/SFX/Enemies/Knife_Throw_2.wav.meta
Normal file
23
Assets/SFX/Enemies/Knife_Throw_2.wav.meta
Normal file
@ -0,0 +1,23 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb475b242c9b6ec448dfec33ec8da9f2
|
||||
AudioImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 8
|
||||
defaultSettings:
|
||||
serializedVersion: 2
|
||||
loadType: 0
|
||||
sampleRateSetting: 0
|
||||
sampleRateOverride: 44100
|
||||
compressionFormat: 1
|
||||
quality: 1
|
||||
conversionMode: 0
|
||||
preloadAudioData: 0
|
||||
platformSettingOverrides: {}
|
||||
forceToMono: 0
|
||||
normalize: 1
|
||||
loadInBackground: 0
|
||||
ambisonic: 0
|
||||
3D: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/SFX/Enemies/Laser_Fire_1.wav
Normal file
BIN
Assets/SFX/Enemies/Laser_Fire_1.wav
Normal file
Binary file not shown.
23
Assets/SFX/Enemies/Laser_Fire_1.wav.meta
Normal file
23
Assets/SFX/Enemies/Laser_Fire_1.wav.meta
Normal file
@ -0,0 +1,23 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0166fbc7106f42498be14d005a200f4
|
||||
AudioImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 8
|
||||
defaultSettings:
|
||||
serializedVersion: 2
|
||||
loadType: 0
|
||||
sampleRateSetting: 0
|
||||
sampleRateOverride: 44100
|
||||
compressionFormat: 1
|
||||
quality: 1
|
||||
conversionMode: 0
|
||||
preloadAudioData: 0
|
||||
platformSettingOverrides: {}
|
||||
forceToMono: 0
|
||||
normalize: 1
|
||||
loadInBackground: 0
|
||||
ambisonic: 0
|
||||
3D: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
BIN
Assets/SFX/Player/Hurt_1.wav
Normal file
BIN
Assets/SFX/Player/Hurt_1.wav
Normal file
Binary file not shown.
23
Assets/SFX/Player/Hurt_1.wav.meta
Normal file
23
Assets/SFX/Player/Hurt_1.wav.meta
Normal file
@ -0,0 +1,23 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f59cd1f6b437f7d4f8fa63bad1e466a5
|
||||
AudioImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 8
|
||||
defaultSettings:
|
||||
serializedVersion: 2
|
||||
loadType: 0
|
||||
sampleRateSetting: 0
|
||||
sampleRateOverride: 44100
|
||||
compressionFormat: 1
|
||||
quality: 1
|
||||
conversionMode: 0
|
||||
preloadAudioData: 0
|
||||
platformSettingOverrides: {}
|
||||
forceToMono: 0
|
||||
normalize: 1
|
||||
loadInBackground: 0
|
||||
ambisonic: 0
|
||||
3D: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/SFX/Player/Hurt_2.wav
Normal file
BIN
Assets/SFX/Player/Hurt_2.wav
Normal file
Binary file not shown.
23
Assets/SFX/Player/Hurt_2.wav.meta
Normal file
23
Assets/SFX/Player/Hurt_2.wav.meta
Normal file
@ -0,0 +1,23 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce8d9dfcc94fcae46a52bd90ac0b0a19
|
||||
AudioImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 8
|
||||
defaultSettings:
|
||||
serializedVersion: 2
|
||||
loadType: 0
|
||||
sampleRateSetting: 0
|
||||
sampleRateOverride: 44100
|
||||
compressionFormat: 1
|
||||
quality: 1
|
||||
conversionMode: 0
|
||||
preloadAudioData: 0
|
||||
platformSettingOverrides: {}
|
||||
forceToMono: 0
|
||||
normalize: 1
|
||||
loadInBackground: 0
|
||||
ambisonic: 0
|
||||
3D: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/SFX/Player/Throw_1.wav
Normal file
BIN
Assets/SFX/Player/Throw_1.wav
Normal file
Binary file not shown.
23
Assets/SFX/Player/Throw_1.wav.meta
Normal file
23
Assets/SFX/Player/Throw_1.wav.meta
Normal file
@ -0,0 +1,23 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9399f94f3fa20f44b8d76c30deda71c
|
||||
AudioImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 8
|
||||
defaultSettings:
|
||||
serializedVersion: 2
|
||||
loadType: 0
|
||||
sampleRateSetting: 0
|
||||
sampleRateOverride: 44100
|
||||
compressionFormat: 1
|
||||
quality: 1
|
||||
conversionMode: 0
|
||||
preloadAudioData: 0
|
||||
platformSettingOverrides: {}
|
||||
forceToMono: 0
|
||||
normalize: 1
|
||||
loadInBackground: 0
|
||||
ambisonic: 0
|
||||
3D: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/SFX/Props.meta
Normal file
8
Assets/SFX/Props.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 102b571a03e65d549bcbc5b6f780ce62
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/SFX/Props/Laser_1.wav
Normal file
BIN
Assets/SFX/Props/Laser_1.wav
Normal file
Binary file not shown.
23
Assets/SFX/Props/Laser_1.wav.meta
Normal file
23
Assets/SFX/Props/Laser_1.wav.meta
Normal file
@ -0,0 +1,23 @@
|
||||
fileFormatVersion: 2
|
||||
guid: caba1143532ae5642aa33fa950eb6269
|
||||
AudioImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 8
|
||||
defaultSettings:
|
||||
serializedVersion: 2
|
||||
loadType: 0
|
||||
sampleRateSetting: 0
|
||||
sampleRateOverride: 44100
|
||||
compressionFormat: 1
|
||||
quality: 1
|
||||
conversionMode: 0
|
||||
preloadAudioData: 0
|
||||
platformSettingOverrides: {}
|
||||
forceToMono: 0
|
||||
normalize: 1
|
||||
loadInBackground: 0
|
||||
ambisonic: 0
|
||||
3D: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1017,8 +1017,8 @@ MonoBehaviour:
|
||||
m_TargetGraphic: {fileID: 434895586}
|
||||
m_HandleRect: {fileID: 434895585}
|
||||
m_Direction: 2
|
||||
m_Value: 0
|
||||
m_Size: 0.99999815
|
||||
m_Value: 1
|
||||
m_Size: 1
|
||||
m_NumberOfSteps: 0
|
||||
m_OnValueChanged:
|
||||
m_PersistentCalls:
|
||||
@ -4474,7 +4474,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0.0009856848}
|
||||
m_AnchoredPosition: {x: 0, y: -0.000023633147}
|
||||
m_SizeDelta: {x: 0, y: 300}
|
||||
m_Pivot: {x: 0, y: 1}
|
||||
--- !u!114 &1792218764
|
||||
@ -4953,6 +4953,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
config: {fileID: 11400000, guid: 1db1421e9cc6f214f9b91a29eba61e76, type: 2}
|
||||
sfxAsset: {fileID: 0}
|
||||
--- !u!61 &1925001481
|
||||
BoxCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -5025,7 +5026,7 @@ Rigidbody2D:
|
||||
m_Interpolate: 0
|
||||
m_SleepingMode: 1
|
||||
m_CollisionDetection: 0
|
||||
m_Constraints: 4
|
||||
m_Constraints: 7
|
||||
--- !u!95 &1925001483
|
||||
Animator:
|
||||
serializedVersion: 7
|
||||
@ -10191,6 +10192,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
config: {fileID: 11400000, guid: 1db1421e9cc6f214f9b91a29eba61e76, type: 2}
|
||||
sfxAsset: {fileID: 0}
|
||||
--- !u!1 &1976298767889346999
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -10491,6 +10493,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
config: {fileID: 11400000, guid: 1db1421e9cc6f214f9b91a29eba61e76, type: 2}
|
||||
sfxAsset: {fileID: 0}
|
||||
--- !u!4 &2347305775932578288
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -16911,7 +16914,7 @@ Rigidbody2D:
|
||||
m_Interpolate: 0
|
||||
m_SleepingMode: 1
|
||||
m_CollisionDetection: 0
|
||||
m_Constraints: 4
|
||||
m_Constraints: 7
|
||||
--- !u!4 &3947579830075241860
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -24510,6 +24513,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
config: {fileID: 11400000, guid: 1db1421e9cc6f214f9b91a29eba61e76, type: 2}
|
||||
sfxAsset: {fileID: 0}
|
||||
--- !u!4 &4934570997528600992
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -28867,7 +28871,7 @@ Rigidbody2D:
|
||||
m_Interpolate: 0
|
||||
m_SleepingMode: 1
|
||||
m_CollisionDetection: 0
|
||||
m_Constraints: 4
|
||||
m_Constraints: 7
|
||||
--- !u!483693784 &7700946729994996886
|
||||
TilemapRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -28998,7 +29002,7 @@ Rigidbody2D:
|
||||
m_Interpolate: 0
|
||||
m_SleepingMode: 1
|
||||
m_CollisionDetection: 0
|
||||
m_Constraints: 4
|
||||
m_Constraints: 7
|
||||
--- !u!4 &8062548743945812344
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -31343,7 +31347,7 @@ Rigidbody2D:
|
||||
m_Interpolate: 0
|
||||
m_SleepingMode: 1
|
||||
m_CollisionDetection: 0
|
||||
m_Constraints: 4
|
||||
m_Constraints: 7
|
||||
--- !u!70 &8787207207727294666
|
||||
CapsuleCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@ -1,16 +1,35 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
using RR.Game2D.Behaviour;
|
||||
using RR.Game2D.Behaviour.ScriptableObjects;
|
||||
using RR.Game2D.Core.Managers;
|
||||
|
||||
public class EnemyAnimationEvents : MonoBehaviour
|
||||
{
|
||||
private SFXAsset _stepSounds;
|
||||
private SFXAsset _hurtSounds;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
EnemyController controller = GetComponent<EnemyController>();
|
||||
_stepSounds = controller.sfxAsset.stepSounds;
|
||||
_hurtSounds = controller.sfxAsset.hurtSounds;
|
||||
}
|
||||
|
||||
public void OnDeathBegin()
|
||||
{
|
||||
// Проигрывание SFX для получения урона
|
||||
if (_hurtSounds && _hurtSounds.soundEffects.Length > 0)
|
||||
GameManager.Instance.Audio.PlayRandomSfxAt(_hurtSounds.soundEffects, transform.position);
|
||||
|
||||
gameObject.layer = LayerMask.NameToLayer("No Collision");
|
||||
Rigidbody2D rb = GetComponent<Rigidbody2D>();
|
||||
Collider2D col = GetComponent<Collider2D>();
|
||||
EnemyController controller = GetComponent<EnemyController>();
|
||||
EnemyFireScript fireScript = GetComponent<EnemyFireScript>();
|
||||
if (controller) controller.enabled = false;
|
||||
if (fireScript) fireScript.enabled = false;
|
||||
if (col) col.enabled = false;
|
||||
if (!rb) return;
|
||||
rb.linearVelocity = Vector2.zero;
|
||||
@ -21,4 +40,11 @@ public class EnemyAnimationEvents : MonoBehaviour
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
public void Step()
|
||||
{
|
||||
// Проигрывание SFX для шага
|
||||
if (_stepSounds && _stepSounds.soundEffects.Length > 0)
|
||||
GameManager.Instance.Audio.PlayRandomSfxAt(_stepSounds.soundEffects, transform.position);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,21 +1,32 @@
|
||||
using RR.Common.Managers;
|
||||
using RR.Game2D.Behaviour;
|
||||
using RR.Game2D.Behaviour.ScriptableObjects;
|
||||
using RR.Game2D.Core.Managers;
|
||||
using UnityEngine;
|
||||
|
||||
public class PlayerAnimationEvents : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private AudioClip deathSound;
|
||||
|
||||
private PlayerController _controller;
|
||||
private SFXAsset _stepSounds;
|
||||
private SFXAsset _hurtSounds;
|
||||
private SFXAsset _jumpSounds;
|
||||
private Rigidbody2D _rb;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_controller = GetComponent<PlayerController>();
|
||||
PlayerController controller = GetComponent<PlayerController>();
|
||||
|
||||
_stepSounds = controller.stepSounds;
|
||||
_hurtSounds = controller.hurtSounds;
|
||||
_jumpSounds = controller.jumpSounds;
|
||||
_rb = GetComponent<Rigidbody2D>();
|
||||
}
|
||||
|
||||
public void OnDeathBegin()
|
||||
{
|
||||
if (_hurtSounds && _hurtSounds.soundEffects.Length > 0)
|
||||
GameManager.Instance.Audio.PlayRandomSfxAt(_hurtSounds.soundEffects, transform.position);
|
||||
}
|
||||
|
||||
public void OnDeathEnd()
|
||||
{
|
||||
Animator animator = GetComponent<Animator>();
|
||||
@ -25,10 +36,15 @@ public class PlayerAnimationEvents : MonoBehaviour
|
||||
GameManager.Instance.RespawnPlayer();
|
||||
}
|
||||
|
||||
public void PlaySfx(AudioClip sound)
|
||||
public void Step()
|
||||
{
|
||||
// Debug.Log($"StepSound: {stepSound}");
|
||||
if (sound != null) GameManager.Instance.Audio.PlaySfxAt(sound, transform.position, 0.5f);
|
||||
// AudioManager.Instance.PlaySfxAt(stepSound, transform.position);
|
||||
if (_stepSounds && _stepSounds.soundEffects.Length > 0)
|
||||
GameManager.Instance.Audio.PlayRandomSfxAt(_stepSounds.soundEffects, transform.position);
|
||||
}
|
||||
|
||||
public void Jump()
|
||||
{
|
||||
if (_jumpSounds && _jumpSounds.soundEffects.Length > 0)
|
||||
GameManager.Instance.Audio.PlayRandomSfxAt(_jumpSounds.soundEffects, transform.position);
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Audio;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace RR.Common.Managers
|
||||
{
|
||||
@ -233,6 +235,22 @@ namespace RR.Common.Managers
|
||||
ConfigureAndPlaySfx(src, clip, volume, pitch, Mathf.Clamp01(spatialBlend), position);
|
||||
}
|
||||
|
||||
public void PlayRandomSfx(SoundEffect[] sfxAsset)
|
||||
{
|
||||
if (sfxAsset.Length == 0) return;
|
||||
|
||||
SoundEffect chosenEffect = sfxAsset[Random.Range(0, sfxAsset.Length - 1)];
|
||||
PlaySfx(chosenEffect.sound, chosenEffect.volume, chosenEffect.pitch);
|
||||
}
|
||||
|
||||
public void PlayRandomSfxAt(SoundEffect[] sfxAsset, Vector3 position)
|
||||
{
|
||||
if (sfxAsset.Length == 0) return;
|
||||
|
||||
SoundEffect chosenEffect = sfxAsset[Random.Range(0, sfxAsset.Length - 1)];
|
||||
PlaySfxAt(chosenEffect.sound, position, chosenEffect.volume, chosenEffect.pitch);
|
||||
}
|
||||
|
||||
// ==== Internal helpers ====
|
||||
|
||||
private void StopCrossfadeAndFade()
|
||||
@ -340,6 +358,15 @@ namespace RR.Common.Managers
|
||||
|
||||
src.Play();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct SoundEffect
|
||||
{
|
||||
public AudioClip sound;
|
||||
[Min(0f)]public float volume;
|
||||
public float pitch;
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,24 +9,24 @@ public class CameraControlTrigger : MonoBehaviour
|
||||
{
|
||||
public CustomInspectorObjects customInspectorObjects;
|
||||
|
||||
private Collider2D col;
|
||||
private bool cameraPanned = false; // Флаг для отслеживания состояния
|
||||
private Collider2D _col;
|
||||
private bool _cameraPanned = false; // Флаг для отслеживания состояния
|
||||
|
||||
private void Start()
|
||||
{
|
||||
col = GetComponent<Collider2D>();
|
||||
_col = GetComponent<Collider2D>();
|
||||
}
|
||||
|
||||
private void OnTriggerEnter2D(Collider2D collision)
|
||||
{
|
||||
if (collision.CompareTag("Player"))
|
||||
{
|
||||
if (customInspectorObjects.panCameraOnContact && !cameraPanned)
|
||||
if (customInspectorObjects.panCameraOnContact && !_cameraPanned)
|
||||
{
|
||||
if (CameraManager.instance != null)
|
||||
{
|
||||
CameraManager.instance.PanCameraOnContact(customInspectorObjects.panDistance, customInspectorObjects.panTime, customInspectorObjects.panDirection, false);
|
||||
cameraPanned = true;
|
||||
_cameraPanned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -36,12 +36,12 @@ public class CameraControlTrigger : MonoBehaviour
|
||||
{
|
||||
if (collision.CompareTag("Player"))
|
||||
{
|
||||
if (customInspectorObjects.panCameraOnContact && cameraPanned)
|
||||
if (customInspectorObjects.panCameraOnContact && _cameraPanned)
|
||||
{
|
||||
if (CameraManager.instance != null)
|
||||
{
|
||||
CameraManager.instance.PanCameraOnContact(customInspectorObjects.panDistance, customInspectorObjects.panTime, customInspectorObjects.panDirection, true);
|
||||
cameraPanned = false;
|
||||
_cameraPanned = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,32 +13,32 @@ namespace RR.Game2D.Core.Managers
|
||||
[Header("Behaviour")]
|
||||
[SerializeField] protected bool snapOnFound = true;
|
||||
|
||||
protected Transform player;
|
||||
protected Transform _player;
|
||||
//private float lastX;
|
||||
protected Coroutine bindRoutine;
|
||||
protected Coroutine _bindRoutine;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
offset = new Vector2(Mathf.Abs(offset.x), offset.y);
|
||||
bindRoutine = StartCoroutine(BindLoop());
|
||||
_bindRoutine = StartCoroutine(BindLoop());
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (bindRoutine != null) { StopCoroutine(bindRoutine); bindRoutine = null; }
|
||||
if (_bindRoutine != null) { StopCoroutine(_bindRoutine); _bindRoutine = null; }
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (!player) return; // ждём появления
|
||||
if (!_player) return; // ждём появления
|
||||
|
||||
float currentX = player.position.x;
|
||||
float currentX = _player.position.x;
|
||||
//if (currentX > lastX + 0.01f) faceLeft = false;
|
||||
//else if (currentX < lastX - 0.01f) faceLeft = true;
|
||||
faceLeft = Mathf.Abs(player.localEulerAngles.y) >= 180 ? true : false;
|
||||
faceLeft = Mathf.Abs(_player.localEulerAngles.y) >= 180 ? true : false;
|
||||
//lastX = currentX;
|
||||
|
||||
Vector3 target = player.position;
|
||||
Vector3 target = _player.position;
|
||||
target.x += faceLeft ? -offset.x : +offset.x;
|
||||
target.y += offset.y;
|
||||
target.z = transform.position.z;
|
||||
@ -53,12 +53,12 @@ namespace RR.Game2D.Core.Managers
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (!player)
|
||||
if (!_player)
|
||||
{
|
||||
var t = ResolvePlayer();
|
||||
if (t)
|
||||
{
|
||||
player = t;
|
||||
_player = t;
|
||||
//lastX = player.position.x;
|
||||
if (snapOnFound) SnapToPlayer(faceLeft);
|
||||
}
|
||||
@ -89,8 +89,8 @@ namespace RR.Game2D.Core.Managers
|
||||
public virtual void FindPlayer(bool playerFaceLeft)
|
||||
{
|
||||
faceLeft = playerFaceLeft;
|
||||
player = ResolvePlayer();
|
||||
if (!player)
|
||||
_player = ResolvePlayer();
|
||||
if (!_player)
|
||||
{
|
||||
Debug.Log("CameraFollow2D: player not found yet, will wait.");
|
||||
return;
|
||||
@ -105,8 +105,8 @@ namespace RR.Game2D.Core.Managers
|
||||
/// <param name="playerFaceLeft">Повернут ли игрок налево</param>
|
||||
private void SnapToPlayer(bool playerFaceLeft)
|
||||
{
|
||||
if (!player) return;
|
||||
Vector3 p = player.position;
|
||||
if (!_player) return;
|
||||
Vector3 p = _player.position;
|
||||
p.x += (playerFaceLeft ? -offset.x : offset.x);
|
||||
p.y += offset.y;
|
||||
p.z = transform.position.z;
|
||||
|
||||
@ -4,42 +4,29 @@ using UnityEngine;
|
||||
|
||||
public class CinemachineFindPlayer : MonoBehaviour
|
||||
{
|
||||
//[Header("Параметры смещения")]
|
||||
//[SerializeField] float interpolationTime = 10f;
|
||||
|
||||
private GameObject tPlayer;
|
||||
private Transform tFollowTarget;
|
||||
private CinemachineCamera vcam;
|
||||
//private CinemachineFollow followScript;
|
||||
//private bool playerFacedLeft = false;
|
||||
private GameObject _tPlayer;
|
||||
private Transform _tFollowTarget;
|
||||
private CinemachineCamera _virtualCamera;
|
||||
|
||||
void Start()
|
||||
{
|
||||
vcam = GetComponent<CinemachineCamera>();
|
||||
//followScript = GetComponent<CinemachineFollow>();
|
||||
_virtualCamera = GetComponent<CinemachineCamera>();
|
||||
|
||||
if (tPlayer == null)
|
||||
{
|
||||
tPlayer = GameManager.Instance.PlayerObj;
|
||||
if (tPlayer == null) tPlayer = GameObject.FindWithTag("Player");
|
||||
}
|
||||
if (_tPlayer != null) return;
|
||||
|
||||
_tPlayer = GameManager.Instance.PlayerObj;
|
||||
|
||||
if (_tPlayer == null) _tPlayer = GameObject.FindWithTag("Player");
|
||||
|
||||
}
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
if (tPlayer != null)
|
||||
{
|
||||
tFollowTarget = tPlayer.transform;
|
||||
vcam.LookAt = tFollowTarget;
|
||||
vcam.Follow = tFollowTarget;
|
||||
|
||||
//playerFacedLeft = Mathf.Abs(tPlayer.transform.localEulerAngles.y) >= 180f;
|
||||
|
||||
////Debug.Log($"Faced left: {playerFacedLeft}");
|
||||
//Vector3 cameraOffset = followScript.FollowOffset;
|
||||
//cameraOffset.x = playerFacedLeft ? -offset.x : offset.x;
|
||||
//followScript.FollowOffset = Vector3.Lerp(followScript.FollowOffset, cameraOffset, Time.deltaTime);
|
||||
}
|
||||
if (_tPlayer == null) return;
|
||||
|
||||
_tFollowTarget = _tPlayer.transform;
|
||||
_virtualCamera.LookAt = _tFollowTarget;
|
||||
_virtualCamera.Follow = _tFollowTarget;
|
||||
}
|
||||
}
|
||||
@ -22,7 +22,7 @@ namespace RR.Game2D.Entities
|
||||
// Текущий активный чекпоинт (read-only)
|
||||
public Checkpoint Active => _active;
|
||||
|
||||
string PrefKey => $"CP_{SceneManager.GetActiveScene().name}";
|
||||
private string PrefKey => $"CP_{SceneManager.GetActiveScene().name}";
|
||||
|
||||
void Awake()
|
||||
{
|
||||
|
||||
@ -11,6 +11,7 @@ namespace RR.Game2D.Behaviour
|
||||
typeof(Animator))]
|
||||
public class EnemyController : MonoBehaviour, IDamageable
|
||||
{
|
||||
[SerializeField] public EnemySFXAsset sfxAsset;
|
||||
[SerializeField] private EnemyControllerConfiguration config;
|
||||
|
||||
private Health health;
|
||||
@ -18,25 +19,25 @@ namespace RR.Game2D.Behaviour
|
||||
|
||||
[HideInInspector] public float MaxHealth => health?.MaxHealth ?? 0;
|
||||
|
||||
private Animator animator;
|
||||
private Rigidbody2D rb;
|
||||
private Collider2D col;
|
||||
private Animator _animator;
|
||||
private Rigidbody2D _rb;
|
||||
private Collider2D _col;
|
||||
|
||||
private GameObject playerObj;
|
||||
private GameObject _playerObj;
|
||||
|
||||
// Аниматор
|
||||
private static readonly int Speed = Animator.StringToHash("Speed");
|
||||
|
||||
void Start()
|
||||
{
|
||||
rb = GetComponent<Rigidbody2D>();
|
||||
col = GetComponent<Collider2D>();
|
||||
animator = GetComponent<Animator>();
|
||||
_rb = GetComponent<Rigidbody2D>();
|
||||
_col = GetComponent<Collider2D>();
|
||||
_animator = GetComponent<Animator>();
|
||||
|
||||
playerObj = GameManager.Instance.PlayerObj;
|
||||
if (playerObj == null)
|
||||
_playerObj = GameManager.Instance.PlayerObj;
|
||||
if (_playerObj == null)
|
||||
{
|
||||
playerObj = GameObject.FindGameObjectWithTag("Player");
|
||||
_playerObj = GameObject.FindGameObjectWithTag("Player");
|
||||
}
|
||||
|
||||
health = GetComponent<Health>();
|
||||
@ -51,10 +52,10 @@ namespace RR.Game2D.Behaviour
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
if (!playerObj) return;
|
||||
if (!_playerObj) return;
|
||||
// if (rb.linearVelocity.x > 0.0001f) Debug.Log(rb.linearVelocity.x);
|
||||
|
||||
Vector3 playerCenter = playerObj.transform.position;
|
||||
Vector3 playerCenter = _playerObj.transform.position;
|
||||
|
||||
if (PlayerInSight())
|
||||
{
|
||||
@ -63,7 +64,7 @@ namespace RR.Game2D.Behaviour
|
||||
|
||||
if (dist > 0)
|
||||
{
|
||||
rb.linearVelocity = new Vector2(config.moveSpeed * toPlayer.normalized.x, 0);
|
||||
_rb.linearVelocity = new Vector2(config.moveSpeed * toPlayer.normalized.x, 0);
|
||||
}
|
||||
// if (dist > 0)
|
||||
// rb.linearVelocity = toPlayer / dist * moveSpeed;
|
||||
@ -72,11 +73,11 @@ namespace RR.Game2D.Behaviour
|
||||
}
|
||||
else
|
||||
{
|
||||
rb.linearVelocity = Vector2.MoveTowards(
|
||||
rb.linearVelocity, Vector2.zero, config.acceleration * Time.fixedDeltaTime);
|
||||
_rb.linearVelocity = Vector2.MoveTowards(
|
||||
_rb.linearVelocity, Vector2.zero, config.acceleration * Time.fixedDeltaTime);
|
||||
}
|
||||
|
||||
animator.SetFloat(Speed, Mathf.Abs(rb.linearVelocity.magnitude));
|
||||
_animator.SetFloat(Speed, Mathf.Abs(_rb.linearVelocity.magnitude));
|
||||
}
|
||||
|
||||
void OnCollisionEnter2D(Collision2D collision)
|
||||
@ -84,7 +85,7 @@ namespace RR.Game2D.Behaviour
|
||||
if (collision.collider.CompareTag("Player"))
|
||||
{
|
||||
Rigidbody2D playerRb = collision.collider.GetComponent<Rigidbody2D>();
|
||||
playerObj.TryGetComponent(out PlayerController playerController);
|
||||
_playerObj.TryGetComponent(out PlayerController playerController);
|
||||
if (playerRb == null) return;
|
||||
Vector2 contactNormal = collision.GetContact(0).normal;
|
||||
if (contactNormal.y < -0.5f)
|
||||
@ -102,13 +103,13 @@ namespace RR.Game2D.Behaviour
|
||||
|
||||
private bool PlayerInSight()
|
||||
{
|
||||
if (!playerObj) return false;
|
||||
if (!_playerObj) return false;
|
||||
|
||||
Vector3 playerPos = playerObj.transform.position;
|
||||
Collider2D playerCol = playerObj.GetComponent<Collider2D>();
|
||||
Vector3 playerPos = _playerObj.transform.position;
|
||||
Collider2D playerCol = _playerObj.GetComponent<Collider2D>();
|
||||
playerPos.y = playerCol.bounds.center.y;
|
||||
|
||||
Vector2 eyePos = new(rb.position.x, col.bounds.center.y);
|
||||
Vector2 eyePos = new(_rb.position.x, _col.bounds.center.y);
|
||||
|
||||
Vector2 toPlayer = (Vector2)playerPos - eyePos;
|
||||
float dist = toPlayer.magnitude;
|
||||
@ -122,7 +123,7 @@ namespace RR.Game2D.Behaviour
|
||||
|
||||
int mask = config.obstacleMask;
|
||||
mask &= ~(1 << gameObject.layer);
|
||||
mask &= ~(1 << playerObj.layer);
|
||||
mask &= ~(1 << _playerObj.layer);
|
||||
|
||||
Vector2 origin = eyePos + forward.normalized * 0.05f;
|
||||
|
||||
@ -142,16 +143,16 @@ namespace RR.Game2D.Behaviour
|
||||
}
|
||||
public void Die()
|
||||
{
|
||||
animator.Play("Death");
|
||||
_animator.Play("Death");
|
||||
// Destroy(gameObject);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
if (!playerObj) return;
|
||||
if (!_playerObj) return;
|
||||
|
||||
Vector2 origin = new(rb.position.x, col.bounds.center.y);
|
||||
Vector2 origin = new(_rb.position.x, _col.bounds.center.y);
|
||||
Vector2 forward = transform.localEulerAngles.y >= 180f ? Vector2.right : Vector2.left;
|
||||
float half = config.viewAngle * 0.5f;
|
||||
|
||||
@ -163,11 +164,11 @@ namespace RR.Game2D.Behaviour
|
||||
Gizmos.DrawLine(origin, origin + edgeB * config.viewDistance);
|
||||
Gizmos.DrawWireSphere(origin, config.viewDistance);
|
||||
|
||||
Vector2 toPlayer = (Vector2)playerObj.transform.position - origin;
|
||||
Vector2 toPlayer = (Vector2)_playerObj.transform.position - origin;
|
||||
if (toPlayer.magnitude <= config.viewDistance)
|
||||
{
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawLine(transform.position, playerObj.transform.position);
|
||||
Gizmos.DrawLine(transform.position, _playerObj.transform.position);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
using RR.Common.Interfaces;
|
||||
using RR.Game2D.Behaviour.ScriptableObjects;
|
||||
using RR.Game2D.Core.Managers;
|
||||
|
||||
namespace RR.Game2D.Behaviour
|
||||
@ -37,15 +38,20 @@ namespace RR.Game2D.Behaviour
|
||||
|
||||
[Header("Здоровье")]
|
||||
[SerializeField] private int maxHealth = 3;
|
||||
private Health health;
|
||||
public float CurrentHealth => health?.CurrentHealth ?? 0;
|
||||
public float MaxHealth => health?.MaxHealth ?? 0;
|
||||
private Health _health;
|
||||
public float CurrentHealth => _health?.CurrentHealth ?? 0;
|
||||
public float MaxHealth => _health?.MaxHealth ?? 0;
|
||||
|
||||
[Header("FX")]
|
||||
[SerializeField] public SFXAsset stepSounds;
|
||||
[SerializeField] public SFXAsset hurtSounds;
|
||||
[SerializeField] public SFXAsset jumpSounds;
|
||||
|
||||
private Rigidbody2D rb;
|
||||
// private Collider2D col;
|
||||
|
||||
private float inputX;
|
||||
private bool jumpPressed, jumpReleased, jumpHold;
|
||||
private float _inputX;
|
||||
private bool _jumpPressed, _jumpReleased, _jumpHold;
|
||||
|
||||
private float _fallSpeedYDampingChangeThreshold;
|
||||
|
||||
@ -84,28 +90,28 @@ namespace RR.Game2D.Behaviour
|
||||
if (animator == null)
|
||||
Debug.LogError($"[{name}] Animator не найден!");
|
||||
|
||||
health = GetComponent<Health>();
|
||||
if (health == null)
|
||||
_health = GetComponent<Health>();
|
||||
if (_health == null)
|
||||
{
|
||||
health = gameObject.AddComponent<Health>();
|
||||
_health = gameObject.AddComponent<Health>();
|
||||
}
|
||||
health.ResetHealth();
|
||||
health.SetOwner(this);
|
||||
health.SetMaxHealth(maxHealth);
|
||||
_health.ResetHealth();
|
||||
_health.SetOwner(this);
|
||||
_health.SetMaxHealth(maxHealth);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// --- Ввод ---
|
||||
Vector2 move = moveAction ? moveAction.action.ReadValue<Vector2>() : Vector2.zero;
|
||||
inputX = Mathf.Abs(move.x) > 0.01f ? Mathf.Sign(move.x) : 0f;
|
||||
_inputX = Mathf.Abs(move.x) > 0.01f ? Mathf.Sign(move.x) : 0f;
|
||||
|
||||
jumpPressed |= jumpAction.action.WasPressedThisFrame();
|
||||
jumpReleased |= jumpAction.action.WasReleasedThisFrame();
|
||||
jumpHold |= jumpAction.action.IsPressed();
|
||||
_jumpPressed |= jumpAction.action.WasPressedThisFrame();
|
||||
_jumpReleased |= jumpAction.action.WasReleasedThisFrame();
|
||||
_jumpHold |= jumpAction.action.IsPressed();
|
||||
|
||||
if (inputX != 0f)
|
||||
transform.localEulerAngles = Mathf.Sign(inputX) > 0 ? Vector3.zero : new Vector3(0, 180f, 0);
|
||||
if (_inputX != 0f)
|
||||
transform.localEulerAngles = Mathf.Sign(_inputX) > 0 ? Vector3.zero : new Vector3(0, 180f, 0);
|
||||
|
||||
if (rb.linearVelocity.y < _fallSpeedYDampingChangeThreshold && !CameraManager.instance.IsLerpingYDamping && !CameraManager.instance.LerpedFromPlayerFalling)
|
||||
{
|
||||
@ -127,7 +133,7 @@ namespace RR.Game2D.Behaviour
|
||||
private void FixedUpdate()
|
||||
{
|
||||
// Горизонтальное движение
|
||||
float target = inputX * moveSpeed;
|
||||
float target = _inputX * moveSpeed;
|
||||
float rate = (Mathf.Abs(target) > 0.01) ? accel : decel;
|
||||
float velocityX = Mathf.MoveTowards(rb.linearVelocity.x, target, rate * Time.fixedDeltaTime);
|
||||
|
||||
@ -135,15 +141,15 @@ namespace RR.Game2D.Behaviour
|
||||
newVelocity.x = velocityX;
|
||||
|
||||
// Вертикальное движение
|
||||
if ((jumpPressed || jumpHold)&& IsGrounded)
|
||||
if ((_jumpPressed || _jumpHold)&& IsGrounded)
|
||||
newVelocity.y = jumpVelocity;
|
||||
|
||||
if (jumpReleased && newVelocity.y > 0)
|
||||
if (_jumpReleased && newVelocity.y > 0)
|
||||
newVelocity.y /= Mathf.Max(1f, jumpCut);
|
||||
|
||||
rb.linearVelocity = newVelocity;
|
||||
|
||||
jumpPressed = jumpReleased = jumpHold = false;
|
||||
_jumpPressed = _jumpReleased = _jumpHold = false;
|
||||
|
||||
// Смерть
|
||||
// if (transform.position.y < deathY) Die();
|
||||
@ -170,11 +176,11 @@ namespace RR.Game2D.Behaviour
|
||||
|
||||
public void TakeDamage(float amount)
|
||||
{
|
||||
health.TakeDamage(amount);
|
||||
_health.TakeDamage(amount);
|
||||
}
|
||||
public void Heal(float amount)
|
||||
{
|
||||
health.Heal(amount);
|
||||
_health.Heal(amount);
|
||||
}
|
||||
|
||||
public void Die()
|
||||
|
||||
@ -8,14 +8,14 @@ namespace RR.Game2D.Behaviour
|
||||
{
|
||||
[SerializeField] private float maxHealth = 3;
|
||||
[SerializeField] private float currentHealth;
|
||||
private IDamageable owner;
|
||||
private IDamageable _owner;
|
||||
|
||||
public float MaxHealth => maxHealth;
|
||||
public float CurrentHealth => currentHealth;
|
||||
|
||||
public void SetOwner(IDamageable healthOwner)
|
||||
{
|
||||
owner = healthOwner;
|
||||
_owner = healthOwner;
|
||||
}
|
||||
|
||||
public void SetMaxHealth(float value)
|
||||
@ -29,7 +29,7 @@ namespace RR.Game2D.Behaviour
|
||||
currentHealth -= amount;
|
||||
if (currentHealth <= 0)
|
||||
{
|
||||
owner?.Die();
|
||||
_owner?.Die();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,16 +7,16 @@ namespace RR.Game2D.Behaviour
|
||||
public class JumpPad2D : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private float verticalBand = 0.5f;
|
||||
private BoxCollider2D col;
|
||||
private BoxCollider2D _col;
|
||||
|
||||
public Action<GameObject> PlayerJumped;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
col = GetComponent<BoxCollider2D>();
|
||||
_col = GetComponent<BoxCollider2D>();
|
||||
|
||||
if (!col.isTrigger)
|
||||
col.isTrigger = true;
|
||||
if (!_col.isTrigger)
|
||||
_col.isTrigger = true;
|
||||
}
|
||||
|
||||
//private void OnTriggerEnter2D(Collider2D other)
|
||||
@ -60,7 +60,7 @@ namespace RR.Game2D.Behaviour
|
||||
PlayerController playerController = other.GetComponent<PlayerController>();
|
||||
Rigidbody2D playerRB = other.GetComponent<Rigidbody2D>();
|
||||
|
||||
if (Mathf.Abs(other.transform.position.y - col.bounds.max.y) <= verticalBand)
|
||||
if (Mathf.Abs(other.transform.position.y - _col.bounds.max.y) <= verticalBand)
|
||||
{
|
||||
Vector2 newPlayerVelocity = playerRB.linearVelocity;
|
||||
newPlayerVelocity.y = playerController.jumpVelocity;
|
||||
|
||||
@ -29,13 +29,13 @@ public class LightDimmer : MonoBehaviour
|
||||
[SerializeField] [Min(0)] private float startBloomIntensity = 0f;
|
||||
[SerializeField] [Min(0)] private float targetBloomIntensity = 1f;
|
||||
|
||||
private Transform playerTransform;
|
||||
private Transform _playerTransform;
|
||||
|
||||
// Храним все коллайдеры игрока, которые в данный момент пересекают триггер
|
||||
private readonly HashSet<Collider2D> playerColliders = new HashSet<Collider2D>();
|
||||
private readonly HashSet<Collider2D> _playerColliders = new HashSet<Collider2D>();
|
||||
|
||||
private float boundsMin;
|
||||
private float boundsMax;
|
||||
private float _boundsMin;
|
||||
private float _boundsMax;
|
||||
private Volume[] _volumes;
|
||||
|
||||
/// <summary>
|
||||
@ -75,7 +75,7 @@ public class LightDimmer : MonoBehaviour
|
||||
// Пытаемся найти игрока на сцене для удобства — это позволит скрипту работать, даже если playerTransform не задан вручную.
|
||||
var playerObj = GameObject.FindGameObjectWithTag(playerTag);
|
||||
if (playerObj != null)
|
||||
playerTransform = playerObj.transform;
|
||||
_playerTransform = playerObj.transform;
|
||||
|
||||
// Кэшируем Volume (если есть) для каждого источника света. Volume может находиться на родителе или выше.
|
||||
for (int i = 0; i < lights.Length; i++)
|
||||
@ -112,7 +112,7 @@ public class LightDimmer : MonoBehaviour
|
||||
|
||||
UpdateBounds();
|
||||
|
||||
if (playerTransform == null) playerTransform = GameManager.Instance.PlayerObj.transform;
|
||||
if (_playerTransform == null) _playerTransform = GameManager.Instance.PlayerObj.transform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -122,18 +122,18 @@ public class LightDimmer : MonoBehaviour
|
||||
private void Update()
|
||||
{
|
||||
// Требуем наличие: playerTransform, массив lights и targetCollider
|
||||
if (!playerTransform || lights == null || lights.Length == 0 || targetCollider == null)
|
||||
if (!_playerTransform || lights == null || lights.Length == 0 || targetCollider == null)
|
||||
return;
|
||||
// Debug.Log($"{name}: Player Transform Detected");
|
||||
|
||||
// Проверяем, что игрок действительно внутри триггера, учитываем все коллайдеры (на случай CompositeCollider/мультиколлайдеров)
|
||||
bool playerInside = playerColliders.Count > 0;
|
||||
bool playerInside = _playerColliders.Count > 0;
|
||||
if (!playerInside)
|
||||
return;
|
||||
|
||||
// Debug.Log($"{name}: Player Inside Trigger");
|
||||
|
||||
Vector3 playerPos = playerTransform.position;
|
||||
Vector3 playerPos = _playerTransform.position;
|
||||
|
||||
// Дополнительная проверка: AABB bounds коллайдера (быстрая фильтрация), чтобы избежать лишних вычислений
|
||||
// if (!targetCollider.bounds.Contains(playerPos))
|
||||
@ -148,10 +148,10 @@ public class LightDimmer : MonoBehaviour
|
||||
|
||||
float t = 0f;
|
||||
// Если boundsMin==boundsMax — делить нельзя, поэтому проверяем приблизительное равенство
|
||||
if (!Mathf.Approximately(boundsMax, boundsMin))
|
||||
if (!Mathf.Approximately(_boundsMax, _boundsMin))
|
||||
{
|
||||
// Нормализуем позицию игрока по отрезку [boundsMin, boundsMax]
|
||||
t = Mathf.InverseLerp(boundsMin, boundsMax, playerCurrent);
|
||||
t = Mathf.InverseLerp(_boundsMin, _boundsMax, playerCurrent);
|
||||
t = Mathf.Clamp01(t);
|
||||
}
|
||||
|
||||
@ -207,11 +207,11 @@ public class LightDimmer : MonoBehaviour
|
||||
if (!other.CompareTag(playerTag)) return;
|
||||
|
||||
// Запоминаем коллайдер игрока
|
||||
playerColliders.Add(other);
|
||||
_playerColliders.Add(other);
|
||||
|
||||
// Сохраняем Transform игрока (на случай, если раньше не найден)
|
||||
if (playerTransform == null)
|
||||
playerTransform = other.transform;
|
||||
if (_playerTransform == null)
|
||||
_playerTransform = other.transform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -223,7 +223,7 @@ public class LightDimmer : MonoBehaviour
|
||||
if (!other.CompareTag(playerTag)) return;
|
||||
|
||||
// Убираем коллайдер из множества; если множество пустое — игрок полностью вышел
|
||||
playerColliders.Remove(other);
|
||||
_playerColliders.Remove(other);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -233,13 +233,13 @@ public class LightDimmer : MonoBehaviour
|
||||
private void UpdateBounds()
|
||||
{
|
||||
var b = targetCollider.bounds;
|
||||
boundsMin = b.min.x;
|
||||
boundsMax = b.max.x;
|
||||
_boundsMin = b.min.x;
|
||||
_boundsMax = b.max.x;
|
||||
|
||||
if (useYProgress)
|
||||
{
|
||||
boundsMin = b.min.y;
|
||||
boundsMax = b.max.y;
|
||||
_boundsMin = b.min.y;
|
||||
_boundsMax = b.max.y;
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,10 +257,10 @@ public class LightDimmer : MonoBehaviour
|
||||
Gizmos.DrawLine(new Vector3(b.max.x, b.max.y, 0f), new Vector3(b.min.x, b.max.y, 0f));
|
||||
Gizmos.DrawLine(new Vector3(b.min.x, b.max.y, 0f), new Vector3(b.min.x, b.min.y, 0f));
|
||||
|
||||
if (playerTransform != null)
|
||||
if (_playerTransform != null)
|
||||
{
|
||||
Gizmos.color = Color.cyan;
|
||||
Vector3 p = playerTransform.position;
|
||||
Vector3 p = _playerTransform.position;
|
||||
Gizmos.DrawSphere(new Vector3(p.x, p.y, 0f), 0.05f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,23 +7,23 @@ namespace RR.Game2D.Core.Managers
|
||||
[SerializeField][Range(-1f, 3f)] private float parallaxFactorX = 0.5f;
|
||||
[SerializeField][Range(-1f, 3f)] private float parallaxFactorY = 0.5f;
|
||||
[SerializeField] private bool lockYAxis = false;
|
||||
private Transform cameraTransform;
|
||||
private Vector3 previousCameraPosition;
|
||||
private Transform _cameraTransform;
|
||||
private Vector3 _previousCameraPosition;
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (Camera.main != null) cameraTransform = Camera.main.transform;
|
||||
previousCameraPosition = cameraTransform.position;
|
||||
if (Camera.main != null) _cameraTransform = Camera.main.transform;
|
||||
_previousCameraPosition = _cameraTransform.position;
|
||||
}
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
Vector3 delta = cameraTransform.position - previousCameraPosition;
|
||||
Vector3 delta = _cameraTransform.position - _previousCameraPosition;
|
||||
if (lockYAxis)
|
||||
transform.position += new Vector3(delta.x * parallaxFactorX, 0, 0);
|
||||
else
|
||||
transform.position += new Vector3(delta.x * parallaxFactorX, delta.y * parallaxFactorY, 0);
|
||||
previousCameraPosition = cameraTransform.position;
|
||||
_previousCameraPosition = _cameraTransform.position;
|
||||
}
|
||||
}
|
||||
}
|
||||
8
Assets/Scripts/Behaviour/ThrowProjectiles.meta
Normal file
8
Assets/Scripts/Behaviour/ThrowProjectiles.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1549e18bd441b344d921fdc83cf31355
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,6 +1,7 @@
|
||||
using UnityEngine;
|
||||
using RR.Game2D.Entities.Projectiles;
|
||||
using RR.Game2D.Behaviour.ScriptableObjects;
|
||||
using RR.Game2D.Core.Managers;
|
||||
|
||||
namespace RR.Game2D.Behaviour
|
||||
{
|
||||
@ -9,7 +10,7 @@ namespace RR.Game2D.Behaviour
|
||||
[SerializeField] private EnemyFireConfiguration config;
|
||||
|
||||
private float lastThrowTime = -999f;
|
||||
private EnemyBasicProjectile projectile;
|
||||
private EnemyBasicProjectile _projectile;
|
||||
|
||||
void Start()
|
||||
{
|
||||
@ -35,7 +36,7 @@ namespace RR.Game2D.Behaviour
|
||||
private void OnDestroy()
|
||||
{
|
||||
// При смерти врага сго снаряд тоже пропадает
|
||||
if (projectile != null) projectile.Despawn();
|
||||
if (_projectile != null) _projectile.Despawn();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -49,18 +50,21 @@ namespace RR.Game2D.Behaviour
|
||||
Collider2D enemyCol = GetComponent<Collider2D>();
|
||||
Vector2 throwPosition = new(1.4f * throwDirection.x + transform.position.x, enemyCol.bounds.center.y);
|
||||
|
||||
projectile = Instantiate(config.projectilePrefab, throwPosition, Quaternion.identity);
|
||||
projectile.owner = gameObject;
|
||||
projectile.maxLifetime = config.projectileLifetime;
|
||||
projectile.despawnInstantly = config.projectileDespawnInstantly;
|
||||
projectile.fallGravityScale = config.projectileFallGravityScale;
|
||||
_projectile = Instantiate(config.projectilePrefab, throwPosition, Quaternion.identity);
|
||||
_projectile.owner = gameObject;
|
||||
_projectile.maxLifetime = config.projectileLifetime;
|
||||
_projectile.despawnInstantly = config.projectileDespawnInstantly;
|
||||
_projectile.fallGravityScale = config.projectileFallGravityScale;
|
||||
|
||||
Collider2D projectileCol = projectile.GetComponent<Collider2D>();
|
||||
Collider2D projectileCol = _projectile.GetComponent<Collider2D>();
|
||||
|
||||
projectile.transform.localRotation = throwDirection.x < 0 ? Quaternion.Inverse(projectile.transform.localRotation) : projectile.transform.localRotation;
|
||||
_projectile.transform.localRotation = throwDirection.x < 0 ? Quaternion.Inverse(_projectile.transform.localRotation) : _projectile.transform.localRotation;
|
||||
|
||||
projectile.transform.position = throwPosition;
|
||||
projectile.Launch(throwDirection, config.throwSpeed);
|
||||
_projectile.transform.position = throwPosition;
|
||||
_projectile.Launch(throwDirection, config.throwSpeed);
|
||||
|
||||
if (config.shotSounds.Length > 0)
|
||||
GameManager.Instance.Audio.PlayRandomSfxAt(config.shotSounds, throwPosition);
|
||||
|
||||
if (enemyCol && projectileCol) Physics2D.IgnoreCollision(enemyCol, projectileCol, true);
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
using UnityEngine;
|
||||
using RR.Game2D.Behaviour.ScriptableObjects;
|
||||
using RR.Game2D.Core.Managers;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using RR.Game2D.Entities.Projectiles;
|
||||
|
||||
@ -20,14 +22,17 @@ namespace RR.Game2D.Behaviour
|
||||
[SerializeField] private Transform launchPoint;
|
||||
[SerializeField] public Transform attachPoint;
|
||||
|
||||
private PickableProjectile pickableProjectile;
|
||||
private Collider2D col;
|
||||
[Header("FX")]
|
||||
[SerializeField] private SFXAsset throwSounds;
|
||||
|
||||
private PickableProjectile _pickableProjectile;
|
||||
private Collider2D _col;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (!attachPoint)
|
||||
Debug.LogWarning("PlayerFireScript: attachPoint не задан. Будет использован корень игрока.");
|
||||
col = GetComponent<Collider2D>();
|
||||
_col = GetComponent<Collider2D>();
|
||||
}
|
||||
|
||||
void Update()
|
||||
@ -35,10 +40,10 @@ namespace RR.Game2D.Behaviour
|
||||
//if (!Input.GetButtonDown("Fire1")) return;
|
||||
if (!fireButton.action.WasPressedThisFrame()) return;
|
||||
|
||||
if (pickableProjectile == null)
|
||||
pickableProjectile = PickableProjectile.Instance;
|
||||
if (_pickableProjectile == null)
|
||||
_pickableProjectile = PickableProjectile.Instance;
|
||||
|
||||
if (pickableProjectile == null)
|
||||
if (_pickableProjectile == null)
|
||||
{
|
||||
if (!spawnIfMissing || projectilePrefab == null)
|
||||
{
|
||||
@ -47,12 +52,12 @@ namespace RR.Game2D.Behaviour
|
||||
}
|
||||
|
||||
Vector3 spawnPos = attachPoint ? attachPoint.position : transform.position;
|
||||
pickableProjectile = Instantiate(projectilePrefab, spawnPos, Quaternion.identity);
|
||||
pickableProjectile.TryPickup(gameObject, attachPoint);
|
||||
_pickableProjectile = Instantiate(projectilePrefab, spawnPos, Quaternion.identity);
|
||||
_pickableProjectile.TryPickup(gameObject, attachPoint);
|
||||
return;
|
||||
}
|
||||
// Бросок
|
||||
if (pickableProjectile.CurrentState == PickableProjectile.State.Held && pickableProjectile.owner == gameObject) Throw();
|
||||
if (_pickableProjectile.CurrentState == PickableProjectile.State.Held && _pickableProjectile.owner == gameObject) Throw();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -68,18 +73,20 @@ namespace RR.Game2D.Behaviour
|
||||
Vector2 launchPos = new (1.4f * facing + launchPoint.position.x, launchPoint.position.y);
|
||||
//Debug.Log(col.bounds.center.y);
|
||||
launchAxis.x = launchAxis.x == 0 ? launchAxis.x : directionX.x;
|
||||
|
||||
if (throwSounds.soundEffects.Length > 0)
|
||||
GameManager.Instance.Audio.PlayRandomSfxAt(throwSounds.soundEffects, transform.position);
|
||||
|
||||
Vector3 projectileScale = pickableProjectile.transform.localScale;
|
||||
pickableProjectile.transform.localScale = new Vector3(Mathf.Abs(projectileScale.x) * -facing, projectileScale.y, projectileScale.z);
|
||||
|
||||
pickableProjectile.transform.position = launchPos;
|
||||
pickableProjectile.Launch(launchAxis, throwSpeed, gameObject);
|
||||
Vector3 projectileScale = _pickableProjectile.transform.localScale;
|
||||
_pickableProjectile.transform.localScale = new Vector3(Mathf.Abs(projectileScale.x) * -facing, projectileScale.y, projectileScale.z);
|
||||
_pickableProjectile.transform.position = launchPos;
|
||||
_pickableProjectile.Launch(launchAxis, throwSpeed, gameObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Метод для привязки снаряда к игроку.
|
||||
/// </summary>
|
||||
/// <param name="proj">Снаряд</param>
|
||||
public void BindProjectile(PickableProjectile proj) => pickableProjectile = proj;
|
||||
public void BindProjectile(PickableProjectile proj) => _pickableProjectile = proj;
|
||||
}
|
||||
}
|
||||
@ -36,9 +36,9 @@ namespace RR.Common.Entities
|
||||
[SerializeField] private bool modulateColor = false;
|
||||
[SerializeField] private Gradient colorOverCycle;
|
||||
|
||||
float blinkOffset;
|
||||
Material _matInstance;
|
||||
Color _baseEmission = Color.white;
|
||||
private float _blinkOffset;
|
||||
private Material _matInstance;
|
||||
private Color _baseEmission = Color.white;
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
@ -58,7 +58,7 @@ namespace RR.Common.Entities
|
||||
_matInstance.EnableKeyword("_EMISSION");
|
||||
}
|
||||
}
|
||||
blinkOffset = Random.Range(blinkJitter.x, blinkJitter.y);
|
||||
_blinkOffset = Random.Range(blinkJitter.x, blinkJitter.y);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
@ -72,7 +72,7 @@ namespace RR.Common.Entities
|
||||
{
|
||||
case Mode.Blink:
|
||||
// пила с джиттером
|
||||
phase = Mathf.Repeat((time + blinkOffset) * Mathf.Max(0.0001f, frequency), 1f);
|
||||
phase = Mathf.Repeat((time + _blinkOffset) * Mathf.Max(0.0001f, frequency), 1f);
|
||||
k = phase < Mathf.Clamp01(duty) ? 1f : 0f;
|
||||
break;
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ namespace RR.Common.Behaviour
|
||||
[SerializeField, Range(0f, 10f)] private float angleX = 0f;
|
||||
[SerializeField, Range(0f, 10f)] private float angleY = 0f;
|
||||
[SerializeField, Range(0f, 10f)] private float angleZ = 0f;
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
transform.Rotate(new Vector3(angleX, angleY, angleZ));
|
||||
|
||||
@ -8,11 +8,11 @@ namespace RR.Game2D.Entities.Hazards
|
||||
[RequireComponent(typeof(Collider2D))]
|
||||
public class Trap : MonoBehaviour
|
||||
{
|
||||
private Collider2D col;
|
||||
private Collider2D _col;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
col = GetComponent<Collider2D>();
|
||||
_col = GetComponent<Collider2D>();
|
||||
}
|
||||
|
||||
private void OnCollisionEnter2D(Collision2D collision)
|
||||
@ -32,7 +32,7 @@ namespace RR.Game2D.Entities.Hazards
|
||||
|
||||
private void OnTriggerEnter2D(Collider2D other)
|
||||
{
|
||||
if (!col.isTrigger) return;
|
||||
if (!_col.isTrigger) return;
|
||||
|
||||
if (other.CompareTag("Player"))
|
||||
{
|
||||
|
||||
@ -10,21 +10,21 @@ public class PlayerRunVFX : MonoBehaviour
|
||||
[SerializeField] private Vector2 offset = Vector2.zero;
|
||||
[SerializeField] private float requiredPlayerRunTime;
|
||||
|
||||
private GameObject player;
|
||||
private Rigidbody2D playerRB;
|
||||
private PlayerController playerController;
|
||||
private float startRunTime = 0;
|
||||
private GameObject _player;
|
||||
private Rigidbody2D _playerRB;
|
||||
private PlayerController _playerController;
|
||||
private float _startRunTime = 0;
|
||||
|
||||
private Vector3 particlesVelocityDirection;
|
||||
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
player = GameManager.Instance.PlayerObj;
|
||||
playerRB = player.GetComponent<Rigidbody2D>();
|
||||
playerController = player.GetComponent<PlayerController>();
|
||||
_player = GameManager.Instance.PlayerObj;
|
||||
_playerRB = _player.GetComponent<Rigidbody2D>();
|
||||
_playerController = _player.GetComponent<PlayerController>();
|
||||
|
||||
if (player == null) player = GameObject.FindGameObjectWithTag("Player");
|
||||
if (_player == null) _player = GameObject.FindGameObjectWithTag("Player");
|
||||
|
||||
particlesVelocityDirection = runVFX.GetVector3("ParticlesVelocityDirection");
|
||||
runVFX.Stop();
|
||||
@ -35,34 +35,34 @@ public class PlayerRunVFX : MonoBehaviour
|
||||
void Update()
|
||||
{
|
||||
|
||||
if (playerController.IsGrounded) transform.position = player.transform.position
|
||||
+ new Vector3(offset.x * Mathf.Sign(playerRB.linearVelocityX), offset.y, 0f);
|
||||
else transform.position = new Vector3(player.transform.position.x, transform.position.y, transform.position.z);
|
||||
if (_playerController.IsGrounded) transform.position = _player.transform.position
|
||||
+ new Vector3(offset.x * Mathf.Sign(_playerRB.linearVelocityX), offset.y, 0f);
|
||||
else transform.position = new Vector3(_player.transform.position.x, transform.position.y, transform.position.z);
|
||||
|
||||
if (!runVFX.enabled) runVFX.enabled = true;
|
||||
|
||||
if (Mathf.Abs(playerRB.linearVelocityX) >= 0.01f && playerController.IsGrounded)
|
||||
if (Mathf.Abs(_playerRB.linearVelocityX) >= 0.01f && _playerController.IsGrounded)
|
||||
{
|
||||
if (startRunTime == 0) startRunTime = Time.time;
|
||||
if (_startRunTime == 0) _startRunTime = Time.time;
|
||||
|
||||
if (Time.time - startRunTime < requiredPlayerRunTime) return;
|
||||
if (Time.time - _startRunTime < requiredPlayerRunTime) return;
|
||||
runVFX.Play();
|
||||
runVFX.SetVector3("ParticlesVelocityDirection", new Vector3(particlesVelocityDirection.x * Mathf.Sign(playerRB.linearVelocityX),
|
||||
runVFX.SetVector3("ParticlesVelocityDirection", new Vector3(particlesVelocityDirection.x * Mathf.Sign(_playerRB.linearVelocityX),
|
||||
particlesVelocityDirection.y,
|
||||
particlesVelocityDirection.z));
|
||||
return;
|
||||
}
|
||||
if (playerRB.linearVelocityY >= 0.25f * playerController.jumpVelocity)
|
||||
if (_playerRB.linearVelocityY >= 0.25f * _playerController.jumpVelocity)
|
||||
{
|
||||
runVFX.SetVector3("ParticlesVelocityDirection", new Vector3(particlesVelocityDirection.x * Mathf.Sign(playerRB.linearVelocityX),
|
||||
playerRB.linearVelocityY,
|
||||
runVFX.SetVector3("ParticlesVelocityDirection", new Vector3(particlesVelocityDirection.x * Mathf.Sign(_playerRB.linearVelocityX),
|
||||
_playerRB.linearVelocityY,
|
||||
particlesVelocityDirection.z));
|
||||
runVFX.Play();
|
||||
if (playerRB.linearVelocityX == 0) startRunTime = 0;
|
||||
if (_playerRB.linearVelocityX == 0) _startRunTime = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
startRunTime = 0;
|
||||
_startRunTime = 0;
|
||||
runVFX.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,23 +8,8 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
rb.bodyType = RigidbodyType2D.Kinematic;
|
||||
col.isTrigger = false;
|
||||
_rb.bodyType = RigidbodyType2D.Kinematic;
|
||||
_col.isTrigger = false;
|
||||
}
|
||||
|
||||
//protected override void OnHit(Collision2D target, Vector2 point, Vector2 relativeVelocity)
|
||||
//{
|
||||
//var player = GameManager.Instance.PlayerObj;
|
||||
|
||||
//if (target.collider.CompareTag("Player"))
|
||||
// player.GetComponent<PlayerController>().Die();
|
||||
//else if (target.collider.CompareTag("Projectile") || target.collider.CompareTag("Enemy"))
|
||||
// Despawn();
|
||||
|
||||
// if (!target.collider.CompareTag(owner.tag))
|
||||
// Despawn();
|
||||
|
||||
// base.OnHit(target, point, relativeVelocity);
|
||||
//}
|
||||
}
|
||||
}
|
||||
@ -13,19 +13,19 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
rb.gravityScale = 0;
|
||||
_rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
_rb.gravityScale = 0;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Time.time - launchTime>= maxLifetime)
|
||||
if (Time.time - _launchTime>= maxLifetime)
|
||||
{
|
||||
if (despawnInstantly) Despawn();
|
||||
else
|
||||
{
|
||||
rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
rb.gravityScale = fallGravityScale;
|
||||
_rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
_rb.gravityScale = fallGravityScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,34 +4,28 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
{
|
||||
public class PhysicsProjectile : BasicProjectile
|
||||
{
|
||||
//protected override void OnEnable()
|
||||
//{
|
||||
// remainingPierce = maxPierce;
|
||||
// if (maxLifetime > 0f)
|
||||
// Invoke(nameof(Despawn), maxLifetime);
|
||||
//}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
_rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
}
|
||||
|
||||
public override void Launch(Vector2 direction, float speed = -1f, GameObject thrower = null)
|
||||
{
|
||||
this.owner = thrower;
|
||||
launched = true;
|
||||
_launched = true;
|
||||
|
||||
Vector2 dir = direction.sqrMagnitude > 0.0001f ? direction.normalized : Vector2.right;
|
||||
float finalSpeed = (speed > 0f) ? speed : initialSpeed;
|
||||
|
||||
rb.simulated = true;
|
||||
rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
_rb.simulated = true;
|
||||
_rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
|
||||
rb.linearVelocity = Vector2.zero;
|
||||
rb.angularVelocity = 0f;
|
||||
_rb.linearVelocity = Vector2.zero;
|
||||
_rb.angularVelocity = 0f;
|
||||
|
||||
rb.AddForce(finalSpeed * rb.mass * dir, ForceMode2D.Impulse);
|
||||
_rb.AddForce(finalSpeed * _rb.mass * dir, ForceMode2D.Impulse);
|
||||
|
||||
transform.right = dir;
|
||||
|
||||
|
||||
@ -71,11 +71,11 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
protected override void Awake()
|
||||
{
|
||||
// Получение ссылок на компоненты Rigidbody2D и Collider
|
||||
rb = GetComponent<Rigidbody2D>();
|
||||
_rb = GetComponent<Rigidbody2D>();
|
||||
|
||||
col = GetComponent<CapsuleCollider2D>();
|
||||
_col = GetComponent<CapsuleCollider2D>();
|
||||
// Пока в Awake оставляем коллайдер в режиме триггера — это переставим в Start/другие состояния по необходимости
|
||||
col.isTrigger = true;
|
||||
_col.isTrigger = true;
|
||||
|
||||
// Простая реализация singleton-а — предотвращаем дублирование снаряда, если это ожидаемое поведение проекта
|
||||
if (Instance != null && Instance != this)
|
||||
@ -119,8 +119,8 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
/// </summary>
|
||||
private void Start()
|
||||
{
|
||||
rb.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
|
||||
col.isTrigger = false;
|
||||
_rb.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
|
||||
_col.isTrigger = false;
|
||||
|
||||
if (CurrentState != State.Held)
|
||||
BecomeGrounded();
|
||||
@ -136,16 +136,16 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
// Если не нужно блокировать при приземлении — проверяем скорость и переводим в состояние 'Grounded'
|
||||
if (!lockWhenLanded && CurrentState == State.Airborne)
|
||||
{
|
||||
if (rb.linearVelocity.sqrMagnitude < (groundVelocity * groundVelocity))
|
||||
if (_rb.linearVelocity.sqrMagnitude < (groundVelocity * groundVelocity))
|
||||
BecomeGrounded();
|
||||
}
|
||||
|
||||
// В полёте и при возврате снаряд ориентируется по вектору скорости
|
||||
if ((CurrentState == State.Airborne || CurrentState == State.Returning) && rb.linearVelocity.sqrMagnitude > 0.0001f)
|
||||
transform.up = rb.linearVelocity.normalized;
|
||||
if ((CurrentState == State.Airborne || CurrentState == State.Returning) && _rb.linearVelocity.sqrMagnitude > 0.0001f)
|
||||
transform.up = _rb.linearVelocity.normalized;
|
||||
|
||||
// Дополнительная страховка перехода в grounded по скорости
|
||||
if (CurrentState == State.Airborne && rb.linearVelocity.magnitude < groundVelocity)
|
||||
if (CurrentState == State.Airborne && _rb.linearVelocity.magnitude < groundVelocity)
|
||||
BecomeGrounded();
|
||||
|
||||
// Если снаряд когда-то был в руках — он может начать возвращаться автоматически
|
||||
@ -319,10 +319,10 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
holderAttachPoint = newOwner.transform;
|
||||
|
||||
// Отключаем физическое поведение и делаем снаряд кинематическим, чтобы он "встал" в руки игрока
|
||||
rb.linearVelocity = Vector2.zero;
|
||||
rb.angularVelocity = 0f;
|
||||
rb.bodyType = RigidbodyType2D.Kinematic;
|
||||
col.enabled = false;
|
||||
_rb.linearVelocity = Vector2.zero;
|
||||
_rb.angularVelocity = 0f;
|
||||
_rb.bodyType = RigidbodyType2D.Kinematic;
|
||||
_col.enabled = false;
|
||||
|
||||
transform.SetParent(holderAttachPoint);
|
||||
// Устанавливаем позицию и вращение относительно точки привязки.
|
||||
@ -334,7 +334,7 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
//StartCoroutine(IgnoreOwnerTemporarily(owner, ignoreOwnerTimeOnThrow));
|
||||
|
||||
CurrentState = State.Held;
|
||||
launched = false;
|
||||
_launched = false;
|
||||
hadBeenHeld = true;
|
||||
|
||||
// При подборе убираем jumpPad, чтобы игрок не случайно "прыгнул" с него
|
||||
@ -384,7 +384,7 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
|
||||
if (bounceCounter > maxBounces) return false;
|
||||
|
||||
Vector2 velocityIn = rb.linearVelocity;
|
||||
Vector2 velocityIn = _rb.linearVelocity;
|
||||
float speed = velocityIn.magnitude;
|
||||
|
||||
if (speed < minBounceSpeed) return false;
|
||||
@ -393,7 +393,7 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
Vector2 direction = Vector2.Reflect(velocityIn, collision.contacts[0].normal);
|
||||
|
||||
// Здесь используется bounciness физического материала коллайдера
|
||||
rb.linearVelocity = col.sharedMaterial.bounciness * direction;
|
||||
_rb.linearVelocity = _col.sharedMaterial.bounciness * direction;
|
||||
|
||||
|
||||
if (collision.collider.CompareTag("Ground") || collision.collider.CompareTag("Trap"))
|
||||
@ -430,18 +430,18 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
lastKnownHolder = thrower;
|
||||
holderAttachPoint = null;
|
||||
|
||||
rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
col.enabled = true;
|
||||
col.isTrigger = false;
|
||||
_rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
_col.enabled = true;
|
||||
_col.isTrigger = false;
|
||||
|
||||
launched = true;
|
||||
_launched = true;
|
||||
|
||||
Vector2 launchDirection = direction.sqrMagnitude > 0.0001f ? direction.normalized : Vector2.right;
|
||||
float finalSpeed = (speed > 0f) ? speed : initialSpeed;
|
||||
|
||||
rb.linearVelocity = Vector2.zero;
|
||||
rb.angularVelocity = 0f;
|
||||
rb.AddForce(finalSpeed * rb.mass * launchDirection, ForceMode2D.Impulse);
|
||||
_rb.linearVelocity = Vector2.zero;
|
||||
_rb.angularVelocity = 0f;
|
||||
_rb.AddForce(finalSpeed * _rb.mass * launchDirection, ForceMode2D.Impulse);
|
||||
|
||||
// Ориентируем снаряд по направлению скорости
|
||||
transform.up = launchDirection;
|
||||
@ -496,11 +496,11 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
else
|
||||
{
|
||||
// Если камеры нет — проверяем дистанцию до владельца как запасной критерий видимости
|
||||
Vector2 toOwnerTest = (Vector2)attachPoint.position - rb.position;
|
||||
Vector2 toOwnerTest = (Vector2)attachPoint.position - _rb.position;
|
||||
isVisible = (toOwnerTest.magnitude <= recallStartDistance);
|
||||
}
|
||||
|
||||
Vector2 toOwner = (Vector2)attachPoint.position - rb.position;
|
||||
Vector2 toOwner = (Vector2)attachPoint.position - _rb.position;
|
||||
float dist = toOwner.magnitude;
|
||||
|
||||
if (CurrentState != State.Returning)
|
||||
@ -509,8 +509,8 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
{
|
||||
// Переходим в режим возврата: включаем физику и делаем триггер, чтобы не мешать столкновениям
|
||||
CurrentState = State.Returning;
|
||||
rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
col.isTrigger = true;
|
||||
_rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
_col.isTrigger = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -519,11 +519,11 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 dir = (dist > 0.001f) ? (toOwner / dist) : rb.linearVelocity.normalized;
|
||||
rb.linearVelocity = dir * recallSpeed;
|
||||
Vector2 dir = (dist > 0.001f) ? (toOwner / dist) : _rb.linearVelocity.normalized;
|
||||
_rb.linearVelocity = dir * recallSpeed;
|
||||
|
||||
if (rb.linearVelocity.sqrMagnitude > 0.01f)
|
||||
transform.up = rb.linearVelocity.normalized;
|
||||
if (_rb.linearVelocity.sqrMagnitude > 0.01f)
|
||||
transform.up = _rb.linearVelocity.normalized;
|
||||
|
||||
// Если достаточно близко — автоматически подбираем
|
||||
if (dist <= recallArriveDistance)
|
||||
@ -547,23 +547,23 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
/// </summary>
|
||||
private void BecomeGrounded()
|
||||
{
|
||||
launched = false;
|
||||
_launched = false;
|
||||
CurrentState = State.Grounded;
|
||||
|
||||
if (lockWhenLanded)
|
||||
{
|
||||
// Полностью останавливаем и делаем кинематическим
|
||||
rb.linearVelocity = Vector2.zero;
|
||||
rb.angularVelocity = 0f;
|
||||
rb.bodyType = RigidbodyType2D.Kinematic;
|
||||
_rb.linearVelocity = Vector2.zero;
|
||||
_rb.angularVelocity = 0f;
|
||||
_rb.bodyType = RigidbodyType2D.Kinematic;
|
||||
}
|
||||
else
|
||||
{
|
||||
rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
_rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
}
|
||||
|
||||
col.enabled = true;
|
||||
col.isTrigger = true;
|
||||
_col.enabled = true;
|
||||
_col.isTrigger = true;
|
||||
|
||||
// Отвязываем от родителя
|
||||
transform.SetParent(null, true);
|
||||
@ -580,8 +580,8 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
private void MoveJumpPad()
|
||||
{
|
||||
// Размеры коллайдера используются для определения смещения платформы
|
||||
float sizeX = col.bounds.size.y;
|
||||
float sizeY = col.bounds.size.x;
|
||||
float sizeX = _col.bounds.size.y;
|
||||
float sizeY = _col.bounds.size.x;
|
||||
|
||||
Vector3 jumpPadPos = transform.position;
|
||||
|
||||
|
||||
@ -17,10 +17,6 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
[SerializeField] protected LayerMask hitLayers = ~0;
|
||||
[SerializeField] protected int maxPierce = 0;
|
||||
|
||||
//[Header("Гравитация/физика")]
|
||||
//[SerializeField] protected bool useGravity = false;
|
||||
//[SerializeField] protected float gravityScale = 1f;
|
||||
|
||||
[Header("FX")]
|
||||
[SerializeField] protected GameObject hitVfxPrefab;
|
||||
[SerializeField] protected AudioClip hitSfx;
|
||||
@ -28,44 +24,34 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
|
||||
[Header("Другое")]
|
||||
[SerializeField] private bool alignRotationToVelocity = true;
|
||||
//[SerializeField] float damage = 10f;
|
||||
//[SerializeField] float knockback = 0f;
|
||||
|
||||
protected Rigidbody2D rb;
|
||||
protected Collider2D col;
|
||||
protected Rigidbody2D _rb;
|
||||
protected Collider2D _col;
|
||||
|
||||
protected int remainingPierce;
|
||||
protected bool launched;
|
||||
protected float launchTime;
|
||||
protected int _remainingPierce;
|
||||
protected bool _launched;
|
||||
protected float _launchTime;
|
||||
public GameObject owner;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
rb = GetComponent<Rigidbody2D>();
|
||||
col = GetComponent<Collider2D>();
|
||||
|
||||
//// Базовые настройки физики
|
||||
//rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
////rb.gravityScale = useGravity ? gravityScale : 0f;
|
||||
//rb.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
|
||||
//col.isTrigger = false;
|
||||
_rb = GetComponent<Rigidbody2D>();
|
||||
_col = GetComponent<Collider2D>();
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
remainingPierce = maxPierce;
|
||||
//if (maxLifetime > 0f)
|
||||
// Invoke(nameof(Despawn), maxLifetime);
|
||||
_remainingPierce = maxPierce;
|
||||
}
|
||||
|
||||
protected virtual void FixedUpdate()
|
||||
{
|
||||
if (!launched) return;
|
||||
if (!_launched) return;
|
||||
|
||||
if (alignRotationToVelocity && rb.linearVelocity.sqrMagnitude > 0.0001f)
|
||||
if (alignRotationToVelocity && _rb.linearVelocity.sqrMagnitude > 0.0001f)
|
||||
{
|
||||
float angle = Mathf.Atan2(rb.linearVelocity.y, rb.linearVelocity.x) * Mathf.Rad2Deg;
|
||||
rb.SetRotation(angle);
|
||||
float angle = Mathf.Atan2(_rb.linearVelocity.y, _rb.linearVelocity.x) * Mathf.Rad2Deg;
|
||||
_rb.SetRotation(angle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,25 +64,25 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
|
||||
protected virtual void OnTriggerEnter2D(Collider2D other)
|
||||
{
|
||||
if (!col.isTrigger) return;
|
||||
if (!_col.isTrigger) return;
|
||||
if (!IsInHitLayer(other.gameObject.layer)) return;
|
||||
|
||||
Vector2 point = other.ClosestPoint(transform.position);
|
||||
OnHit(other, point, rb.linearVelocity);
|
||||
OnHit(other, point, _rb.linearVelocity);
|
||||
}
|
||||
|
||||
public virtual void Launch(Vector2 direction, float speed = -1f, GameObject thrower = null)
|
||||
{
|
||||
this.owner = thrower;
|
||||
launched = true;
|
||||
_launched = true;
|
||||
|
||||
float finalSpeed = (speed > 0f) ? speed : initialSpeed;
|
||||
rb.linearVelocity = direction.normalized * finalSpeed;
|
||||
_rb.linearVelocity = direction.normalized * finalSpeed;
|
||||
|
||||
if (thrower != null && ignoreOwnerTime > 0f)
|
||||
StartCoroutine(IgnoreOwnerTemporarily(thrower, ignoreOwnerTime));
|
||||
|
||||
launchTime = Time.time;
|
||||
_launchTime = Time.time;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -108,12 +94,12 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
{
|
||||
Collider2D[] ownerColliders = who.GetComponentsInChildren<Collider2D>();
|
||||
foreach (var oc in ownerColliders)
|
||||
if (oc && col) Physics2D.IgnoreCollision(col, oc, true);
|
||||
if (oc && _col) Physics2D.IgnoreCollision(_col, oc, true);
|
||||
|
||||
yield return new WaitForSeconds(time);
|
||||
|
||||
foreach (var oc in ownerColliders)
|
||||
if (oc && col) Physics2D.IgnoreCollision(col, oc, false);
|
||||
if (oc && _col) Physics2D.IgnoreCollision(_col, oc, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -156,9 +142,9 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
|
||||
PlayFX(point);
|
||||
|
||||
if (remainingPierce > 0)
|
||||
if (_remainingPierce > 0)
|
||||
{
|
||||
remainingPierce--;
|
||||
_remainingPierce--;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -176,9 +162,9 @@ namespace RR.Game2D.Entities.Projectiles
|
||||
TryDealDamage(otherCol, point, relativeVelocity);
|
||||
PlayFX(point);
|
||||
|
||||
if (remainingPierce > 0)
|
||||
if (_remainingPierce > 0)
|
||||
{
|
||||
remainingPierce--;
|
||||
_remainingPierce--;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -18,3 +18,16 @@ MonoBehaviour:
|
||||
projectileLifetime: 1
|
||||
projectileDespawnInstantly: 1
|
||||
projectileFallGravityScale: 3
|
||||
shotSounds:
|
||||
- sound: {fileID: 8300000, guid: f5084f4cf2fabc74fae40a5a9ebc2718, type: 3}
|
||||
volume: 1.5
|
||||
pitch: 1
|
||||
- sound: {fileID: 8300000, guid: eb475b242c9b6ec448dfec33ec8da9f2, type: 3}
|
||||
volume: 1
|
||||
pitch: 1
|
||||
- sound: {fileID: 8300000, guid: f5084f4cf2fabc74fae40a5a9ebc2718, type: 3}
|
||||
volume: 1.5
|
||||
pitch: 0.9
|
||||
- sound: {fileID: 8300000, guid: eb475b242c9b6ec448dfec33ec8da9f2, type: 3}
|
||||
volume: 1
|
||||
pitch: 0.9
|
||||
|
||||
@ -18,3 +18,7 @@ MonoBehaviour:
|
||||
projectileLifetime: 999
|
||||
projectileDespawnInstantly: 1
|
||||
projectileFallGravityScale: 3
|
||||
shotSounds:
|
||||
- sound: {fileID: 8300000, guid: a0166fbc7106f42498be14d005a200f4, type: 3}
|
||||
volume: 1
|
||||
pitch: 1
|
||||
|
||||
@ -18,3 +18,16 @@ MonoBehaviour:
|
||||
projectileLifetime: 1
|
||||
projectileDespawnInstantly: 0
|
||||
projectileFallGravityScale: 3
|
||||
shotSounds:
|
||||
- sound: {fileID: 8300000, guid: f5084f4cf2fabc74fae40a5a9ebc2718, type: 3}
|
||||
volume: 1.5
|
||||
pitch: 1
|
||||
- sound: {fileID: 8300000, guid: eb475b242c9b6ec448dfec33ec8da9f2, type: 3}
|
||||
volume: 1
|
||||
pitch: 1
|
||||
- sound: {fileID: 8300000, guid: f5084f4cf2fabc74fae40a5a9ebc2718, type: 3}
|
||||
volume: 1.5
|
||||
pitch: 0.9
|
||||
- sound: {fileID: 8300000, guid: eb475b242c9b6ec448dfec33ec8da9f2, type: 3}
|
||||
volume: 1
|
||||
pitch: 0.9
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 7d0ab526e27a165469927c990b5cfaba, type: 3}
|
||||
m_Name: MainEnemySFXAsset
|
||||
m_EditorClassIdentifier: Assembly-CSharp::RR.Game2D.Behaviour.ScriptableObjects.EnemySFXAsset
|
||||
stepSounds: {fileID: 11400000, guid: 37fe07ddcac109a46a86ba44df16d551, type: 2}
|
||||
hurtSounds: {fileID: 11400000, guid: 16067cac1ebba8144b39d4b576bf38b0, type: 2}
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9cb4dd9d30f2420439e056018daf622a
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -2,7 +2,7 @@ using UnityEngine;
|
||||
|
||||
namespace RR.Game2D.Behaviour.ScriptableObjects
|
||||
{
|
||||
[CreateAssetMenu(fileName = "EnemyControllerConfiguration", menuName = "Scriptable Objects/EnemyControllerConfiguration")]
|
||||
[CreateAssetMenu(fileName = "EnemyControllerConfiguration", menuName = "Behaviour/Controllers/EnemyControllerConfiguration")]
|
||||
public class EnemyControllerConfiguration : ScriptableObject
|
||||
{
|
||||
[Header("Обзор")]
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using RR.Common.Managers;
|
||||
using RR.Game2D.Entities.Projectiles;
|
||||
|
||||
namespace RR.Game2D.Behaviour.ScriptableObjects
|
||||
{
|
||||
[CreateAssetMenu(fileName = "EnemyFireConfiguration", menuName = "Scriptable Objects/EnemyFireConfiguration")]
|
||||
[CreateAssetMenu(fileName = "EnemyFireConfiguration", menuName = "Behaviour/Fire/EnemyFireConfiguration")]
|
||||
public class EnemyFireConfiguration : ScriptableObject
|
||||
{
|
||||
[Header("Бросок")]
|
||||
@ -15,6 +17,9 @@ namespace RR.Game2D.Behaviour.ScriptableObjects
|
||||
public float projectileLifetime = 1f;
|
||||
public bool projectileDespawnInstantly = false;
|
||||
public float projectileFallGravityScale = 3f;
|
||||
|
||||
[Header("FX (Опционально)")]
|
||||
public SoundEffect[] shotSounds;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
11
Assets/Scripts/ScriptableObjects/EnemySFXAsset.cs
Normal file
11
Assets/Scripts/ScriptableObjects/EnemySFXAsset.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace RR.Game2D.Behaviour.ScriptableObjects
|
||||
{
|
||||
[CreateAssetMenu(fileName = "SFXAsset", menuName = "Audio/SFX Assets/EnemySFXAsset")]
|
||||
public class EnemySFXAsset : ScriptableObject
|
||||
{
|
||||
public SFXAsset stepSounds;
|
||||
public SFXAsset hurtSounds;
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/ScriptableObjects/EnemySFXAsset.cs.meta
Normal file
2
Assets/Scripts/ScriptableObjects/EnemySFXAsset.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d0ab526e27a165469927c990b5cfaba
|
||||
12
Assets/Scripts/ScriptableObjects/SFXAsset.cs
Normal file
12
Assets/Scripts/ScriptableObjects/SFXAsset.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
using RR.Common.Managers;
|
||||
|
||||
namespace RR.Game2D.Behaviour.ScriptableObjects
|
||||
{
|
||||
[CreateAssetMenu(fileName = "SFXAsset", menuName = "Audio/SFX Assets/SFXAsset")]
|
||||
public class SFXAsset : ScriptableObject
|
||||
{
|
||||
public SoundEffect[] soundEffects;
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/ScriptableObjects/SFXAsset.cs.meta
Normal file
2
Assets/Scripts/ScriptableObjects/SFXAsset.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b7a812250cb02a439b8c382ae42dd27
|
||||
8
Assets/Scripts/ScriptableObjects/SFXAssets.meta
Normal file
8
Assets/Scripts/ScriptableObjects/SFXAssets.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c4a0deea0455aac46944e746cbffa650
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,24 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 8b7a812250cb02a439b8c382ae42dd27, type: 3}
|
||||
m_Name: EnemyHurtSounds
|
||||
m_EditorClassIdentifier: Assembly-CSharp::RR.Game2D.Behaviour.ScriptableObjects.SFXAsset
|
||||
soundEffects:
|
||||
- sound: {fileID: 8300000, guid: 37f7526ec58db8843916100518133785, type: 3}
|
||||
volume: 1
|
||||
pitch: 1
|
||||
- sound: {fileID: 8300000, guid: 37f7526ec58db8843916100518133785, type: 3}
|
||||
volume: 1.2
|
||||
pitch: 0.9
|
||||
- sound: {fileID: 8300000, guid: 37f7526ec58db8843916100518133785, type: 3}
|
||||
volume: 0.9
|
||||
pitch: 1.1
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 16067cac1ebba8144b39d4b576bf38b0
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,18 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 8b7a812250cb02a439b8c382ae42dd27, type: 3}
|
||||
m_Name: PlayerJumpSounds
|
||||
m_EditorClassIdentifier: Assembly-CSharp::RR.Game2D.Behaviour.ScriptableObjects.SFXAsset
|
||||
soundEffects:
|
||||
- sound: {fileID: 8300000, guid: fa0b6b9872cd9b84bb24e35b24e57fdf, type: 3}
|
||||
volume: 1
|
||||
pitch: 1
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a63566742cc2d84c89928c8b988e4eb
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,24 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 8b7a812250cb02a439b8c382ae42dd27, type: 3}
|
||||
m_Name: PlayerThrowSounds
|
||||
m_EditorClassIdentifier: Assembly-CSharp::RR.Game2D.Behaviour.ScriptableObjects.SFXAsset
|
||||
soundEffects:
|
||||
- sound: {fileID: 8300000, guid: a9399f94f3fa20f44b8d76c30deda71c, type: 3}
|
||||
volume: 1
|
||||
pitch: 1
|
||||
- sound: {fileID: 8300000, guid: a9399f94f3fa20f44b8d76c30deda71c, type: 3}
|
||||
volume: 1.1
|
||||
pitch: 0.95
|
||||
- sound: {fileID: 8300000, guid: a9399f94f3fa20f44b8d76c30deda71c, type: 3}
|
||||
volume: 0.95
|
||||
pitch: 1.05
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b774d97282b77f45b08068d61682269
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,21 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 8b7a812250cb02a439b8c382ae42dd27, type: 3}
|
||||
m_Name: PlayetHurtSounds
|
||||
m_EditorClassIdentifier: Assembly-CSharp::RR.Game2D.Behaviour.ScriptableObjects.SFXAsset
|
||||
soundEffects:
|
||||
- sound: {fileID: 8300000, guid: f59cd1f6b437f7d4f8fa63bad1e466a5, type: 3}
|
||||
volume: 1
|
||||
pitch: 1
|
||||
- sound: {fileID: 8300000, guid: ce8d9dfcc94fcae46a52bd90ac0b0a19, type: 3}
|
||||
volume: 1
|
||||
pitch: 1
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 89e7f713913aecb40ada8c2f27c69303
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,33 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 8b7a812250cb02a439b8c382ae42dd27, type: 3}
|
||||
m_Name: StepsSounds_Level_1
|
||||
m_EditorClassIdentifier: Assembly-CSharp::RR.Game2D.Behaviour.ScriptableObjects.SFXAsset
|
||||
soundEffects:
|
||||
- sound: {fileID: 8300000, guid: 144cba17f4a47274d834d5e1fc28acb9, type: 3}
|
||||
volume: 1
|
||||
pitch: 1
|
||||
- sound: {fileID: 8300000, guid: 5f68c3b1c31c833458e189d0b7d622dd, type: 3}
|
||||
volume: 1
|
||||
pitch: 1
|
||||
- sound: {fileID: 8300000, guid: 144cba17f4a47274d834d5e1fc28acb9, type: 3}
|
||||
volume: 1
|
||||
pitch: 1.05
|
||||
- sound: {fileID: 8300000, guid: 5f68c3b1c31c833458e189d0b7d622dd, type: 3}
|
||||
volume: 1
|
||||
pitch: 1.05
|
||||
- sound: {fileID: 8300000, guid: 144cba17f4a47274d834d5e1fc28acb9, type: 3}
|
||||
volume: 1
|
||||
pitch: 0.95
|
||||
- sound: {fileID: 8300000, guid: 5f68c3b1c31c833458e189d0b7d622dd, type: 3}
|
||||
volume: 1
|
||||
pitch: 0.95
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37fe07ddcac109a46a86ba44df16d551
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -10,13 +10,13 @@ namespace RR.Common.UI
|
||||
[SerializeField] TextMeshProUGUI title;
|
||||
[SerializeField] Button btn;
|
||||
|
||||
private int world;
|
||||
private int stage;
|
||||
private int _world;
|
||||
private int _stage;
|
||||
|
||||
public void Setup(string levelSceneName, int levelWorld, int levelStage)
|
||||
{
|
||||
world = levelWorld;
|
||||
stage = levelStage;
|
||||
_world = levelWorld;
|
||||
_stage = levelStage;
|
||||
if (title) title.text = levelSceneName; // "1-3, 1-1 и т.д."
|
||||
if (btn) { btn.onClick.RemoveAllListeners(); btn.onClick.AddListener(OnClick); }
|
||||
}
|
||||
@ -34,7 +34,7 @@ namespace RR.Common.UI
|
||||
void OnClick()
|
||||
{
|
||||
// через GameManager (предпочтительно)
|
||||
GameManager.Instance.LoadLevel(world, stage);
|
||||
GameManager.Instance.LoadLevel(_world, _stage);
|
||||
|
||||
// Фоллбэк, если нужно:
|
||||
// UnityEngine.SceneManagement.SceneManager.LoadScene(sceneName);
|
||||
|
||||
@ -20,7 +20,7 @@ namespace RR.Common.UI
|
||||
[SerializeField] private Button closeButton;
|
||||
[SerializeField] private float fadeDuration = 0.15f;
|
||||
|
||||
readonly List<LevelButton> levelsPool = new();
|
||||
private readonly List<LevelButton> _levelsPool = new();
|
||||
|
||||
void Awake()
|
||||
{
|
||||
@ -56,8 +56,8 @@ namespace RR.Common.UI
|
||||
void BuildIfNeeded()
|
||||
{
|
||||
// Очистим/пересоберём (можно кэшировать, но пересборка надёжнее при изменениях Build Settings)
|
||||
foreach (var b in levelsPool) if (b) Destroy(b.gameObject);
|
||||
levelsPool.Clear();
|
||||
foreach (var b in _levelsPool) if (b) Destroy(b.gameObject);
|
||||
_levelsPool.Clear();
|
||||
|
||||
var levels = EnumerateLevelScenesInBuild()
|
||||
.OrderBy(e => e.world)
|
||||
@ -72,7 +72,7 @@ namespace RR.Common.UI
|
||||
if (lv.world == 1) btn.SetColor(Color.green);
|
||||
else if (lv.world == 2) btn.SetColor(Color.blue);
|
||||
|
||||
levelsPool.Add(btn);
|
||||
_levelsPool.Add(btn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,11 +10,6 @@ namespace RR.Common.UI
|
||||
[SerializeField] private Button newGameButton;
|
||||
[SerializeField] private Button quitButton;
|
||||
|
||||
//private void Awake()
|
||||
//{
|
||||
// Bootstrap();
|
||||
//}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Bootstrap();
|
||||
|
||||
@ -16,11 +16,11 @@ namespace RR.Common.UI
|
||||
[Tooltip("Следить и возвращать фокус внутрь модалки, если он уходит наружу.")]
|
||||
public bool enforce = true;
|
||||
|
||||
bool wasOpenLastFrame;
|
||||
GameObject prevSelectedGlobal;
|
||||
readonly List<Selectable> outside = new();
|
||||
readonly Dictionary<Selectable, bool> outsidePrev = new();
|
||||
Selectable lastModalSelected;
|
||||
private bool _wasOpenLastFrame;
|
||||
private GameObject _prevSelectedGlobal;
|
||||
private readonly List<Selectable> _outside = new();
|
||||
private readonly Dictionary<Selectable, bool> _outsidePrev = new();
|
||||
private Selectable _lastModalSelected;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
@ -31,40 +31,35 @@ namespace RR.Common.UI
|
||||
}
|
||||
}
|
||||
|
||||
//void OnEnable()
|
||||
//{
|
||||
// if (modalRoot != null && modalRoot.activeSelf) OnModalOpened();
|
||||
//}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (modalRoot == null) return;
|
||||
|
||||
bool isOpen = modalRoot.activeSelf;
|
||||
if (isOpen && !wasOpenLastFrame) OnModalOpened();
|
||||
else if (!isOpen && wasOpenLastFrame) OnModalClosed();
|
||||
if (isOpen && !_wasOpenLastFrame) OnModalOpened();
|
||||
else if (!isOpen && _wasOpenLastFrame) OnModalClosed();
|
||||
|
||||
wasOpenLastFrame = isOpen;
|
||||
_wasOpenLastFrame = isOpen;
|
||||
|
||||
if (isOpen && enforce) EnsureFocusInsideModal();
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
if (wasOpenLastFrame) OnModalClosed();
|
||||
if (_wasOpenLastFrame) OnModalClosed();
|
||||
}
|
||||
|
||||
void OnModalOpened()
|
||||
{
|
||||
// запомнить, что было выделено до открытия
|
||||
prevSelectedGlobal = EventSystem.current ? EventSystem.current.currentSelectedGameObject : null;
|
||||
_prevSelectedGlobal = EventSystem.current ? EventSystem.current.currentSelectedGameObject : null;
|
||||
|
||||
// выключить интерактив вне модалки
|
||||
CollectOutsideSelectables();
|
||||
foreach (var s in outside)
|
||||
foreach (var s in _outside)
|
||||
{
|
||||
if (!s) continue;
|
||||
outsidePrev[s] = s.interactable;
|
||||
_outsidePrev[s] = s.interactable;
|
||||
s.interactable = false;
|
||||
}
|
||||
|
||||
@ -82,36 +77,36 @@ namespace RR.Common.UI
|
||||
{
|
||||
EventSystem.current.SetSelectedGameObject(null);
|
||||
EventSystem.current.SetSelectedGameObject(toSelect);
|
||||
lastModalSelected = toSelect.GetComponent<Selectable>();
|
||||
_lastModalSelected = toSelect.GetComponent<Selectable>();
|
||||
}
|
||||
}
|
||||
|
||||
void OnModalClosed()
|
||||
{
|
||||
foreach (var kv in outsidePrev)
|
||||
foreach (var kv in _outsidePrev)
|
||||
{
|
||||
var s = kv.Key;
|
||||
if (s) s.interactable = kv.Value;
|
||||
}
|
||||
outsidePrev.Clear();
|
||||
outside.Clear();
|
||||
_outsidePrev.Clear();
|
||||
_outside.Clear();
|
||||
|
||||
if (EventSystem.current)
|
||||
{
|
||||
if (prevSelectedGlobal && prevSelectedGlobal.activeInHierarchy)
|
||||
EventSystem.current.SetSelectedGameObject(prevSelectedGlobal);
|
||||
if (_prevSelectedGlobal && _prevSelectedGlobal.activeInHierarchy)
|
||||
EventSystem.current.SetSelectedGameObject(_prevSelectedGlobal);
|
||||
else
|
||||
EventSystem.current.SetSelectedGameObject(null);
|
||||
}
|
||||
|
||||
lastModalSelected = null;
|
||||
prevSelectedGlobal = null;
|
||||
_lastModalSelected = null;
|
||||
_prevSelectedGlobal = null;
|
||||
}
|
||||
|
||||
void CollectOutsideSelectables()
|
||||
{
|
||||
outside.Clear();
|
||||
outsidePrev.Clear();
|
||||
_outside.Clear();
|
||||
_outsidePrev.Clear();
|
||||
|
||||
// ✅ Новый API Unity 6
|
||||
var all = Object.FindObjectsByType<Selectable>(
|
||||
@ -122,7 +117,7 @@ namespace RR.Common.UI
|
||||
{
|
||||
if (!s || !s.gameObject.activeInHierarchy) continue;
|
||||
if (!IsUnderModal(s.transform))
|
||||
outside.Add(s);
|
||||
_outside.Add(s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,19 +138,19 @@ namespace RR.Common.UI
|
||||
if (cur == null || !IsUnderModal(cur.transform))
|
||||
{
|
||||
GameObject fallback =
|
||||
(lastModalSelected && lastModalSelected.gameObject.activeInHierarchy) ? lastModalSelected.gameObject :
|
||||
(_lastModalSelected && _lastModalSelected.gameObject.activeInHierarchy) ? _lastModalSelected.gameObject :
|
||||
(firstSelected && firstSelected.gameObject.activeInHierarchy) ? firstSelected.gameObject :
|
||||
modalRoot.GetComponentInChildren<Selectable>()?.gameObject;
|
||||
|
||||
if (fallback)
|
||||
{
|
||||
EventSystem.current.SetSelectedGameObject(fallback);
|
||||
lastModalSelected = fallback.GetComponent<Selectable>();
|
||||
_lastModalSelected = fallback.GetComponent<Selectable>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lastModalSelected = cur.GetComponent<Selectable>();
|
||||
_lastModalSelected = cur.GetComponent<Selectable>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user