diff --git a/Assets/CameraLetterBox.cs b/Assets/CameraLetterBox.cs new file mode 100644 index 00000000..a8d5e3bf --- /dev/null +++ b/Assets/CameraLetterBox.cs @@ -0,0 +1,157 @@ +using UnityEngine; +using DG.Tweening; +using Cinemachine; + +public class CameraLetterbox : MonoBehaviour +{ + [SerializeField] private CinemachineVirtualCamera _virtualCamera; + [SerializeField] private RectTransform _topBar; + [SerializeField] private RectTransform _bottomBar; + [SerializeField] private RectTransform _leftBar; + [SerializeField] private RectTransform _rightBar; + [SerializeField] private float _transitionDuration = 0.5f; + [SerializeField] private Ease _easeType = Ease.InOutQuad; + + public enum AspectRatio + { + Ratio_4_3, // 4:3 + Ratio_8_7, // 8:7 + Ratio_21_9 // 21:9 + } + + [SerializeField] private AspectRatio _targetAspectRatio = AspectRatio.Ratio_4_3; + private Sequence _currentSequence; + private float _initialOrthographicSize; + + private void Awake() + { + if (_virtualCamera == null) + _virtualCamera = FindObjectOfType(); + + _initialOrthographicSize = _virtualCamera.m_Lens.OrthographicSize; + } + + private void Start() + { + SetAspectRatio(_targetAspectRatio, true); + } + + public void SetAspectRatio(AspectRatio ratio, bool immediate = false) + { + float targetRatio; + float defaultRatio = 16f / 9f; + + switch (ratio) + { + case AspectRatio.Ratio_4_3: + targetRatio = 4f / 3f; // 약 1.33:1 + break; + case AspectRatio.Ratio_8_7: + targetRatio = 8f / 7f; + break; + case AspectRatio.Ratio_21_9: + targetRatio = 21f / 9f; + break; + default: + targetRatio = 8f / 7f; + break; + } + + float currentRatio = (float)Screen.width / Screen.height; + + if (_currentSequence != null && _currentSequence.IsPlaying()) + { + _currentSequence.Kill(); + } + + // 시네머신 카메라 OrthographicSize 조정값 계산 + float targetOrthoSize = _initialOrthographicSize; + if (ratio == AspectRatio.Ratio_8_7) + { + targetOrthoSize = _initialOrthographicSize * (defaultRatio / targetRatio); + } + else if (ratio == AspectRatio.Ratio_21_9) + { + targetOrthoSize = _initialOrthographicSize; + } + + if (currentRatio > targetRatio) + { + float targetWidth = Screen.height * targetRatio; + float barWidth = (Screen.width - targetWidth) / 2f; + + if (immediate) + { + _leftBar.sizeDelta = new Vector2(barWidth, _leftBar.sizeDelta.y); + _rightBar.sizeDelta = new Vector2(barWidth, _rightBar.sizeDelta.y); + _topBar.sizeDelta = new Vector2(_topBar.sizeDelta.x, 0); + _bottomBar.sizeDelta = new Vector2(_bottomBar.sizeDelta.x, 0); + _virtualCamera.m_Lens.OrthographicSize = targetOrthoSize; + } + else + { + _currentSequence = DOTween.Sequence(); + + _currentSequence.Join(_topBar.DOSizeDelta(new Vector2(_topBar.sizeDelta.x, 0), _transitionDuration).SetEase(_easeType)); + _currentSequence.Join(_bottomBar.DOSizeDelta(new Vector2(_bottomBar.sizeDelta.x, 0), _transitionDuration).SetEase(_easeType)); + _currentSequence.Join(_leftBar.DOSizeDelta(new Vector2(barWidth, _leftBar.sizeDelta.y), _transitionDuration).SetEase(_easeType)); + _currentSequence.Join(_rightBar.DOSizeDelta(new Vector2(barWidth, _rightBar.sizeDelta.y), _transitionDuration).SetEase(_easeType)); + + // 시네머신 카메라 크기 애니메이션 + _currentSequence.Join(DOTween.To(() => _virtualCamera.m_Lens.OrthographicSize, + value => _virtualCamera.m_Lens.OrthographicSize = value, + targetOrthoSize, _transitionDuration).SetEase(_easeType)); + } + } + else + { + float targetHeight = Screen.width / targetRatio; + float barHeight = (Screen.height - targetHeight) / 2f; + + if (immediate) + { + _topBar.sizeDelta = new Vector2(_topBar.sizeDelta.x, barHeight); + _bottomBar.sizeDelta = new Vector2(_bottomBar.sizeDelta.x, barHeight); + _leftBar.sizeDelta = new Vector2(0, _leftBar.sizeDelta.y); + _rightBar.sizeDelta = new Vector2(0, _rightBar.sizeDelta.y); + _virtualCamera.m_Lens.OrthographicSize = targetOrthoSize; + } + else + { + _currentSequence = DOTween.Sequence(); + + _currentSequence.Join(_leftBar.DOSizeDelta(new Vector2(0, _leftBar.sizeDelta.y), _transitionDuration).SetEase(_easeType)); + _currentSequence.Join(_rightBar.DOSizeDelta(new Vector2(0, _rightBar.sizeDelta.y), _transitionDuration).SetEase(_easeType)); + _currentSequence.Join(_topBar.DOSizeDelta(new Vector2(_topBar.sizeDelta.x, barHeight), _transitionDuration).SetEase(_easeType)); + _currentSequence.Join(_bottomBar.DOSizeDelta(new Vector2(_bottomBar.sizeDelta.x, barHeight), _transitionDuration).SetEase(_easeType)); + + // 시네머신 카메라 크기 애니메이션 + _currentSequence.Join(DOTween.To(() => _virtualCamera.m_Lens.OrthographicSize, + value => _virtualCamera.m_Lens.OrthographicSize = value, + targetOrthoSize, _transitionDuration).SetEase(_easeType)); + } + } + } + + public void Set8to7Ratio() + { + SetAspectRatio(AspectRatio.Ratio_8_7); + } + + public void Set21to9Ratio() + { + SetAspectRatio(AspectRatio.Ratio_21_9); + } + public void Set4to3Ratio() + { + SetAspectRatio(AspectRatio.Ratio_4_3); + } + + private void OnDestroy() + { + if (_currentSequence != null) + { + _currentSequence.Kill(); + } + } +} \ No newline at end of file diff --git a/Assets/CameraLetterBox.cs.meta b/Assets/CameraLetterBox.cs.meta new file mode 100644 index 00000000..89d1be34 --- /dev/null +++ b/Assets/CameraLetterBox.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3410ea7ee17a8c444ab101a26d0d318f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/SuperArio.unity b/Assets/Scenes/SuperArio.unity index 806818d9..4c1bb7c4 100644 --- a/Assets/Scenes/SuperArio.unity +++ b/Assets/Scenes/SuperArio.unity @@ -218,6 +218,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: - {fileID: 160858917} + - {fileID: 1720010262} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} @@ -2641,6 +2642,81 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 489915034} m_CullTransparentMesh: 1 +--- !u!1 &514946465 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 514946466} + - component: {fileID: 514946468} + - component: {fileID: 514946467} + m_Layer: 5 + m_Name: Left + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &514946466 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 514946465} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1720010262} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 100, y: 0} + m_Pivot: {x: 0, y: 0.5} +--- !u!114 &514946467 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 514946465} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &514946468 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 514946465} + m_CullTransparentMesh: 1 --- !u!1 &589573980 GameObject: m_ObjectHideFlags: 0 @@ -3354,6 +3430,69 @@ Rigidbody2D: m_SleepingMode: 1 m_CollisionDetection: 0 m_Constraints: 0 +--- !u!1 &768279308 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 768279311} + - component: {fileID: 768279310} + - component: {fileID: 768279309} + m_Layer: 0 + m_Name: Shader + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &768279309 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 768279308} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4812dc66f40e3fc40919c71c28b01b4c, type: 3} + m_Name: + m_EditorClassIdentifier: + _volume: {fileID: 768279310} +--- !u!114 &768279310 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 768279308} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 172515602e62fb746b5d573b38a5fe58, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IsGlobal: 1 + priority: 0 + blendDistance: 0 + weight: 1 + sharedProfile: {fileID: 11400000, guid: 88b7ddfe43321bf45ba1ec414634ada3, type: 2} +--- !u!4 &768279311 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 768279308} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &778391937 GameObject: m_ObjectHideFlags: 0 @@ -5649,7 +5788,7 @@ GameObject: - component: {fileID: 1072397133} - component: {fileID: 1072397134} - component: {fileID: 1072397135} - m_Layer: 0 + m_Layer: 13 m_Name: Tilemap m_TagString: Untagged m_Icon: {fileID: 0} @@ -7402,7 +7541,7 @@ GameObject: - component: {fileID: 1251556826} m_Layer: 0 m_Name: StarBox - m_TagString: Untagged + m_TagString: Obstacle m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 @@ -7484,7 +7623,7 @@ BoxCollider2D: m_GameObject: {fileID: 1251556822} m_Enabled: 1 m_Density: 1 - m_Material: {fileID: 0} + m_Material: {fileID: 6200000, guid: bbf1a22622d8ac346ac2db0696312ffe, type: 2} m_IncludeLayers: serializedVersion: 2 m_Bits: 0 @@ -7518,7 +7657,7 @@ BoxCollider2D: adaptiveTiling: 0 m_AutoTiling: 0 serializedVersion: 2 - m_Size: {x: 0.5, y: 0.5} + m_Size: {x: 0.45, y: 0.45} m_EdgeRadius: 0 --- !u!114 &1251556826 MonoBehaviour: @@ -7584,7 +7723,7 @@ GameObject: - component: {fileID: 1314224578} m_Layer: 0 m_Name: HeartBox - m_TagString: Untagged + m_TagString: Obstacle m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 @@ -7678,7 +7817,7 @@ BoxCollider2D: m_GameObject: {fileID: 1314224575} m_Enabled: 1 m_Density: 1 - m_Material: {fileID: 0} + m_Material: {fileID: 6200000, guid: bbf1a22622d8ac346ac2db0696312ffe, type: 2} m_IncludeLayers: serializedVersion: 2 m_Bits: 0 @@ -7712,7 +7851,7 @@ BoxCollider2D: adaptiveTiling: 0 m_AutoTiling: 0 serializedVersion: 2 - m_Size: {x: 0.5, y: 0.5} + m_Size: {x: 0.45, y: 0.45} m_EdgeRadius: 0 --- !u!1 &1332213266 GameObject: @@ -7891,6 +8030,81 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 67366e4e2ddbdb24a9f1498ec1b5744b, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!1 &1362515004 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1362515005} + - component: {fileID: 1362515007} + - component: {fileID: 1362515006} + m_Layer: 5 + m_Name: Top + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1362515005 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1362515004} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1720010262} + 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} + m_SizeDelta: {x: 0, y: 100} + m_Pivot: {x: 0.5, y: 1} +--- !u!114 &1362515006 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1362515004} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1362515007 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1362515004} + m_CullTransparentMesh: 1 --- !u!1 &1362758707 GameObject: m_ObjectHideFlags: 0 @@ -9340,6 +9554,66 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!1 &1720010261 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1720010262} + - component: {fileID: 1720010263} + m_Layer: 5 + m_Name: LetterBox + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &1720010262 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1720010261} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1362515005} + - {fileID: 1732962661} + - {fileID: 514946466} + - {fileID: 1987850803} + m_Father: {fileID: 70859180} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1720010263 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1720010261} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3410ea7ee17a8c444ab101a26d0d318f, type: 3} + m_Name: + m_EditorClassIdentifier: + _virtualCamera: {fileID: 1984151337} + _topBar: {fileID: 1362515005} + _bottomBar: {fileID: 1732962661} + _leftBar: {fileID: 514946466} + _rightBar: {fileID: 1987850803} + _transitionDuration: 1 + _easeType: 7 + _targetAspectRatio: 0 --- !u!1 &1721653384 GameObject: m_ObjectHideFlags: 0 @@ -9477,6 +9751,81 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1721653384} m_CullTransparentMesh: 1 +--- !u!1 &1732962660 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1732962661} + - component: {fileID: 1732962663} + - component: {fileID: 1732962662} + m_Layer: 5 + m_Name: Bottom + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1732962661 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1732962660} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1720010262} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 100} + m_Pivot: {x: 0.5, y: 0} +--- !u!114 &1732962662 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1732962660} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1732962663 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1732962660} + m_CullTransparentMesh: 1 --- !u!1 &1780669273 GameObject: m_ObjectHideFlags: 0 @@ -10207,7 +10556,7 @@ GameObject: - component: {fileID: 1852582787} m_Layer: 0 m_Name: ExitBox - m_TagString: Untagged + m_TagString: Obstacle m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 @@ -10289,7 +10638,7 @@ BoxCollider2D: m_GameObject: {fileID: 1852582783} m_Enabled: 1 m_Density: 1 - m_Material: {fileID: 0} + m_Material: {fileID: 6200000, guid: bbf1a22622d8ac346ac2db0696312ffe, type: 2} m_IncludeLayers: serializedVersion: 2 m_Bits: 0 @@ -10323,7 +10672,7 @@ BoxCollider2D: adaptiveTiling: 0 m_AutoTiling: 0 serializedVersion: 2 - m_Size: {x: 0.5, y: 0.5} + m_Size: {x: 0.45, y: 0.45} m_EdgeRadius: 0 --- !u!114 &1852582787 MonoBehaviour: @@ -10716,6 +11065,81 @@ Transform: - {fileID: 85120895} m_Father: {fileID: 1448982496} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1987850802 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1987850803} + - component: {fileID: 1987850805} + - component: {fileID: 1987850804} + m_Layer: 5 + m_Name: Right + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1987850803 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1987850802} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1720010262} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 100, y: 0} + m_Pivot: {x: 1, y: 0.5} +--- !u!114 &1987850804 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1987850802} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1987850805 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1987850802} + m_CullTransparentMesh: 1 --- !u!1 &1991355565 GameObject: m_ObjectHideFlags: 0 @@ -11544,4 +11968,5 @@ SceneRoots: - {fileID: 1633679111} - {fileID: 255248416} - {fileID: 865558342} + - {fileID: 768279311} - {fileID: 900708986} diff --git a/Assets/Scripts/Runtime/CH2/SuperArio/ArioStore.cs b/Assets/Scripts/Runtime/CH2/SuperArio/ArioStore.cs index c92de1a3..e4de67cd 100644 --- a/Assets/Scripts/Runtime/CH2/SuperArio/ArioStore.cs +++ b/Assets/Scripts/Runtime/CH2/SuperArio/ArioStore.cs @@ -1,7 +1,6 @@ -using System; +using Runtime.ETC; using UnityEngine; using UnityEngine.InputSystem; -using System.Collections; namespace Runtime.CH2.SuperArio { @@ -23,18 +22,28 @@ public class ArioStore : MonoBehaviour private float _initialJumpPosition; private bool _isJumpHeld; private float _surfaceVelocityX; - private Coroutine _coroutine; + private Collider2D _collider; private void Start() { _initPos = transform.position; _rb = GetComponent(); + _collider = GetComponent(); _rb.isKinematic = true; _rb.constraints = RigidbodyConstraints2D.FreezeRotation; ArioManager.instance.OnEnterStore += EnterStore; ArioManager.instance.OpenStore += OpenWalls; } + private void OnDestroy() + { + if (ArioManager.instance != null) + { + ArioManager.instance.OnEnterStore -= EnterStore; + ArioManager.instance.OpenStore -= OpenWalls; + } + } + private void EnterStore(bool isTrue) { _rb.isKinematic = false; @@ -48,23 +57,17 @@ private void EnterStore(bool isTrue) public void ExitStore() { - if (_coroutine != null) - { - StopCoroutine(_coroutine); - _coroutine = null; - } - _rb.isKinematic = true; transform.position = _initPos; - // 벽 복구 - foreach (StoreWall storeWall in _storeWalls) + + foreach (var wall in _storeWalls) { - storeWall.gameObject.SetActive(true); + wall.gameObject.SetActive(true); } - foreach (GameObject openWall in _openWalls) + foreach (var wall in _openWalls) { - openWall.gameObject.SetActive(false); + wall.gameObject.SetActive(false); } ArioManager.instance.ExitStore(); @@ -75,20 +78,35 @@ private void FixedUpdate() { if (!ArioManager.instance.IsStore) return; + // 떨어지는 중일 때만 지면 상태 해제 + if (_rb.velocity.y < -0.5f) + { + _isGrounded = false; + } + + HandleMovement(); + } + + private void HandleMovement() + { + // 지면에 있을 때만 surface 속도 적용 if (_isGrounded) { - _surfaceVelocityX = _surface.speed; + _rb.velocity = new Vector2(_surfaceVelocityX, _rb.velocity.y); } - + + // 낙하 가속도 if (_rb.velocity.y < 0) { _rb.velocity += Vector2.up * (Physics2D.gravity.y * (_fallMultiplier - 1) * Time.fixedDeltaTime); } + // 낮은 점프 가속도 else if (_rb.velocity.y > 0 && !_isJumpHeld) { _rb.velocity += Vector2.up * (Physics2D.gravity.y * (_lowJumpMultiplier - 1) * Time.fixedDeltaTime); } + // 점프 중 이동 if (_isJumping) { _rb.velocity = new Vector2(_surfaceVelocityX, _rb.velocity.y); @@ -102,28 +120,29 @@ private void FixedUpdate() public void OnMove(InputAction.CallbackContext context) { - if (!ArioManager.instance.IsStore) - return; + if (!ArioManager.instance.IsStore) return; Vector2 moveInput = context.ReadValue(); - switch (context.phase) + // 즉시 점프 처리 + if (context.phase == InputActionPhase.Started && moveInput.y > 0) { - case InputActionPhase.Performed: - if (moveInput.y > 0 && _isGrounded && !_isJumping) - { - Jump(); - _isJumpHeld = true; - } - break; - case InputActionPhase.Canceled: - _isJumpHeld = false; - break; + if (_isGrounded) + { + Jump(); + _isJumpHeld = true; + } + } + else if (context.phase == InputActionPhase.Canceled) + { + _isJumpHeld = false; } } private void Jump() { + if (!_isGrounded) return; + _isJumping = true; _isGrounded = false; _initialJumpPosition = transform.position.y; @@ -134,75 +153,65 @@ private void OnCollisionStay2D(Collision2D other) { if (other.gameObject.TryGetComponent(out StoreWall wall)) { - if (wall.IsLeft) - { - _surface.speed = 3.5f; - _surfaceVelocityX = 3.5f; - } - else - { - _surface.speed = -3.5f; - _surfaceVelocityX = -3.5f; - } + _surfaceVelocityX = wall.IsLeft ? 3.5f : -3.5f; + if (_surface != null) + _surface.speed = _surfaceVelocityX; + return; } - else if (other.gameObject.TryGetComponent(out StoreGround ground)) + + // 박스와의 충돌 처리 + if (other.gameObject.CompareTag(GlobalConst.ObstacleStr)) { foreach (ContactPoint2D contact in other.contacts) { - if (Vector2.Dot(contact.normal, Vector2.up) > 0.5f) + if (Mathf.Abs(contact.normal.x) > 0.5f) { - if (contact.point.y < transform.position.y) - { - _isGrounded = true; - if (_rb.velocity.y <= 0) - { - _isJumping = false; - } - break; - } + float bounceForce = 5f; + Vector2 bounceDirection = contact.normal; + _rb.velocity = new Vector2(bounceDirection.x * bounceForce, _rb.velocity.y); } } + return; } - } - private void OnCollisionExit2D(Collision2D other) - { - if (!gameObject.activeInHierarchy) return; - + // 지면 체크 if (other.gameObject.TryGetComponent(out StoreGround ground)) { - _coroutine = StartCoroutine(GroundedBufferRoutine()); - } - } + // 이미 점프 중이면 지면 체크 스킵 + if (_isJumping && _rb.velocity.y > 0) return; - private IEnumerator GroundedBufferRoutine() - { - yield return new WaitForSeconds(0.1f); - if (!_isJumping) - { - _isGrounded = false; - } - } + foreach (ContactPoint2D contact in other.contacts) + { + // 지면 체크 조건 완화 + if (Vector2.Dot(contact.normal, Vector2.up) > 0.5f) + { + _isGrounded = true; + if (_rb.velocity.y <= 0) + { + _isJumping = false; + } - private void OnDisable() - { - if(_coroutine != null) - { - StopCoroutine(_coroutine); - _coroutine = null; + if (ground.TryGetComponent(out SurfaceEffector2D surfaceEffector)) + { + _surfaceVelocityX = surfaceEffector.speed; + _surface = surfaceEffector; + } + return; + } + } } } private void OpenWalls() { - foreach (StoreWall storeWall in _storeWalls) + foreach (var wall in _storeWalls) { - storeWall.gameObject.SetActive(false); + wall.gameObject.SetActive(false); } - foreach (GameObject openWall in _openWalls) + foreach (var wall in _openWalls) { - openWall.gameObject.SetActive(true); + wall.gameObject.SetActive(true); } } } diff --git a/Assets/Scripts/Runtime/CH2/SuperArio/ObstacleManager.cs b/Assets/Scripts/Runtime/CH2/SuperArio/ObstacleManager.cs index 66fee723..d4980776 100644 --- a/Assets/Scripts/Runtime/CH2/SuperArio/ObstacleManager.cs +++ b/Assets/Scripts/Runtime/CH2/SuperArio/ObstacleManager.cs @@ -29,7 +29,7 @@ private void SetStageData(string stage, ObstacleSpawnDataSet dataSet) _obstacleTypeCnt = stageData.ObstacleTypes; // 장애물 종류 수 _spawnDelay = 3.0f / stageData.Speed; - _spawnDelay = Mathf.Max(_spawnDelay, 0.5f); + _spawnDelay = Mathf.Max(_spawnDelay, 1f); _remainingSpawnCount = stageData.ObstacleCount; // 남은 스폰 카운트 초기화 } diff --git a/Assets/Scripts/Runtime/CH2/SuperArio/StoreBoxPhysics2D.physicsMaterial2D b/Assets/Scripts/Runtime/CH2/SuperArio/StoreBoxPhysics2D.physicsMaterial2D new file mode 100644 index 00000000..eabeb759 --- /dev/null +++ b/Assets/Scripts/Runtime/CH2/SuperArio/StoreBoxPhysics2D.physicsMaterial2D @@ -0,0 +1,11 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!62 &6200000 +PhysicsMaterial2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: StoreBoxPhysics2D + friction: 0 + bounciness: 0.5 diff --git a/Assets/Scripts/Runtime/CH2/SuperArio/StoreBoxPhysics2D.physicsMaterial2D.meta b/Assets/Scripts/Runtime/CH2/SuperArio/StoreBoxPhysics2D.physicsMaterial2D.meta new file mode 100644 index 00000000..7969e162 --- /dev/null +++ b/Assets/Scripts/Runtime/CH2/SuperArio/StoreBoxPhysics2D.physicsMaterial2D.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bbf1a22622d8ac346ac2db0696312ffe +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 6200000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Runtime/Input/InGameKeyBinder.cs b/Assets/Scripts/Runtime/Input/InGameKeyBinder.cs index 8b057038..16d36a62 100644 --- a/Assets/Scripts/Runtime/Input/InGameKeyBinder.cs +++ b/Assets/Scripts/Runtime/Input/InGameKeyBinder.cs @@ -58,7 +58,8 @@ public void SAKeyBinding(SAKeyBinder keyBinder, SettingsUIView settingsUIView) _gameOverControls.Player.Move.performed += keyBinder.EnterStoreKeyInput; _gameOverControls.Player.Move.performed += keyBinder.Ario.OnMove; _gameOverControls.Player.Move.canceled += keyBinder.Ario.OnMove; - + + _gameOverControls.Player.Move.started += keyBinder.ArioStore.OnMove; _gameOverControls.Player.Move.performed += keyBinder.ArioStore.OnMove; _gameOverControls.Player.Move.canceled += keyBinder.ArioStore.OnMove; _gameOverControls.Player.Interaction.performed += _ => keyBinder.ItemKeyInput(); diff --git a/Assets/_CH2/_SuperArio/VolumeProfiles.meta b/Assets/_CH2/_SuperArio/VolumeProfiles.meta new file mode 100644 index 00000000..7cdc92bc --- /dev/null +++ b/Assets/_CH2/_SuperArio/VolumeProfiles.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9415b56750fcc974794645ec7b89432e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_CH2/_SuperArio/VolumeProfiles/SuperArio Post-processing volume.asset b/Assets/_CH2/_SuperArio/VolumeProfiles/SuperArio Post-processing volume.asset new file mode 100644 index 00000000..ca6e7063 --- /dev/null +++ b/Assets/_CH2/_SuperArio/VolumeProfiles/SuperArio Post-processing volume.asset @@ -0,0 +1,91 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-9096742756361542843 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 4388191585ea44bb892b7a3954c42607, type: 3} + m_Name: Bleed + m_EditorClassIdentifier: + active: 1 + enable: + m_OverrideState: 1 + m_Value: 1 + bleedMode: + m_OverrideState: 1 + m_Value: 0 + bleedAmount: + m_OverrideState: 1 + m_Value: 1.52 + bleedDebug: + m_OverrideState: 1 + m_Value: 0 + mask: + m_OverrideState: 1 + m_Value: {fileID: 0} + dimension: 1 + maskChannel: + m_OverrideState: 1 + m_Value: 0 + GlobalPostProcessingSettings: + m_OverrideState: 1 + m_Value: 0 + bleedModeIndex: 0 +--- !u!114 &-6210844540213672365 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 052aaf852ee28b0478400254d6c5386b, type: 3} + m_Name: Warp + m_EditorClassIdentifier: + active: 1 + enable: + m_OverrideState: 1 + m_Value: 1 + fade: + m_OverrideState: 1 + m_Value: 0 + warpMode: + m_OverrideState: 1 + m_Value: 1 + warp: + m_OverrideState: 1 + m_Value: {x: 0.1, y: 0.3} + scale: + m_OverrideState: 1 + m_Value: 1 + mask: + m_OverrideState: 1 + m_Value: {fileID: 0} + dimension: 1 + maskChannel: + m_OverrideState: 1 + m_Value: 0 + GlobalPostProcessingSettings: + m_OverrideState: 0 + m_Value: 0 +--- !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: d7fd9488000d3734a9e00ee676215985, type: 3} + m_Name: SuperArio Post-processing volume + m_EditorClassIdentifier: + components: + - {fileID: -9096742756361542843} + - {fileID: -6210844540213672365} diff --git a/Assets/_CH2/_SuperArio/VolumeProfiles/SuperArio Post-processing volume.asset.meta b/Assets/_CH2/_SuperArio/VolumeProfiles/SuperArio Post-processing volume.asset.meta new file mode 100644 index 00000000..c77ed03a --- /dev/null +++ b/Assets/_CH2/_SuperArio/VolumeProfiles/SuperArio Post-processing volume.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 88b7ddfe43321bf45ba1ec414634ada3 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: