From 764bc305f764fcd9b0a37308810b34cc1380a37c Mon Sep 17 00:00:00 2001 From: "DESKTOP-VVOCIJO\\PC" Date: Thu, 14 May 2026 18:01:14 +0900 Subject: [PATCH] =?UTF-8?q?2026-05-14=202D=20Platformer=20Game=20=EC=BA=90?= =?UTF-8?q?=EB=A6=AD=ED=84=B0=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/01_Scenes/GameScene.unity | 4 +- Assets/02_Scripts/GlobalObject.cs | 18 ++ Assets/02_Scripts/GlobalObject.cs.meta | 2 + Assets/02_Scripts/Input/GameInput.cs | 231 +++++++++++++++++- Assets/02_Scripts/Managers.meta | 8 + Assets/02_Scripts/Managers/InputManager.cs | 41 ++++ .../02_Scripts/Managers/InputManager.cs.meta | 2 + Assets/02_Scripts/Player/PlayerController.cs | 57 ++++- Assets/11_Input/GameInput.inputactions | 97 +++++++- ProjectSettings/TagManager.asset | 4 +- 10 files changed, 450 insertions(+), 14 deletions(-) create mode 100644 Assets/02_Scripts/GlobalObject.cs create mode 100644 Assets/02_Scripts/GlobalObject.cs.meta create mode 100644 Assets/02_Scripts/Managers.meta create mode 100644 Assets/02_Scripts/Managers/InputManager.cs create mode 100644 Assets/02_Scripts/Managers/InputManager.cs.meta diff --git a/Assets/01_Scenes/GameScene.unity b/Assets/01_Scenes/GameScene.unity index d77f9dd..6b65cca 100644 --- a/Assets/01_Scenes/GameScene.unity +++ b/Assets/01_Scenes/GameScene.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86c086574178c14cecd8a8445831f248f75eb9c1bd4eac89a40c2c6b63f4c247 -size 62499 +oid sha256:a9f37c1469a318e3d1d54c366e5ed8842e4eac4a2432ba42f13f8d1c2505e3d8 +size 66499 diff --git a/Assets/02_Scripts/GlobalObject.cs b/Assets/02_Scripts/GlobalObject.cs new file mode 100644 index 0000000..d7c5c19 --- /dev/null +++ b/Assets/02_Scripts/GlobalObject.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +public class GlobalObject : MonoBehaviour +{ + private static GlobalObject _instance; + void Awake() + { + if (_instance == null) + { + _instance = this; + DontDestroyOnLoad(gameObject); + } + else + { + Destroy(gameObject); + } + } +} \ No newline at end of file diff --git a/Assets/02_Scripts/GlobalObject.cs.meta b/Assets/02_Scripts/GlobalObject.cs.meta new file mode 100644 index 0000000..edfc60d --- /dev/null +++ b/Assets/02_Scripts/GlobalObject.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 02c0fdb393749ab49a9e54c7282c6f09 \ No newline at end of file diff --git a/Assets/02_Scripts/Input/GameInput.cs b/Assets/02_Scripts/Input/GameInput.cs index 6e40509..61508bf 100644 --- a/Assets/02_Scripts/Input/GameInput.cs +++ b/Assets/02_Scripts/Input/GameInput.cs @@ -85,15 +85,113 @@ public partial class @GameInput: IInputActionCollection2, IDisposable public @GameInput() { asset = InputActionAsset.FromJson(@"{ - ""version"": 0, + ""version"": 1, ""name"": ""GameInput"", - ""maps"": [], + ""maps"": [ + { + ""name"": ""Player"", + ""id"": ""e331468a-870b-4a9d-adfc-33c89a2aa65d"", + ""actions"": [ + { + ""name"": ""Move"", + ""type"": ""Value"", + ""id"": ""63ac178d-1333-427a-9f57-780afc877807"", + ""expectedControlType"": ""Vector2"", + ""processors"": """", + ""interactions"": """", + ""initialStateCheck"": true + }, + { + ""name"": ""Jump"", + ""type"": ""Button"", + ""id"": ""a8c7f1d2-3e4b-4a5c-9d6e-7f8901234567"", + ""expectedControlType"": """", + ""processors"": """", + ""interactions"": """", + ""initialStateCheck"": false + } + ], + ""bindings"": [ + { + ""name"": ""2D Vector"", + ""id"": ""1c7aa2cd-7385-4e38-8392-a1cecb8adc98"", + ""path"": ""2DVector"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""Move"", + ""isComposite"": true, + ""isPartOfComposite"": false + }, + { + ""name"": ""up"", + ""id"": ""50a77fe5-4fb2-4e7a-bd0c-973407f67e90"", + ""path"": ""/upArrow"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""Move"", + ""isComposite"": false, + ""isPartOfComposite"": true + }, + { + ""name"": ""down"", + ""id"": ""2306a862-a3c3-48b1-8a28-ce80c7d9e2ea"", + ""path"": ""/downArrow"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""Move"", + ""isComposite"": false, + ""isPartOfComposite"": true + }, + { + ""name"": ""left"", + ""id"": ""819efc78-8db1-481e-b737-4fef39f2fa3f"", + ""path"": ""/leftArrow"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""Move"", + ""isComposite"": false, + ""isPartOfComposite"": true + }, + { + ""name"": ""right"", + ""id"": ""eab43684-ffd8-44c3-bca7-03dce6685fbb"", + ""path"": ""/rightArrow"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""Move"", + ""isComposite"": false, + ""isPartOfComposite"": true + }, + { + ""name"": """", + ""id"": ""b9d8e2f3-4a5c-4b6d-8e7f-901234567890"", + ""path"": ""/space"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""Jump"", + ""isComposite"": false, + ""isPartOfComposite"": false + } + ] + } + ], ""controlSchemes"": [] }"); + // Player + m_Player = asset.FindActionMap("Player", throwIfNotFound: true); + m_Player_Move = m_Player.FindAction("Move", throwIfNotFound: true); + m_Player_Jump = m_Player.FindAction("Jump", throwIfNotFound: true); } ~@GameInput() { + UnityEngine.Debug.Assert(!m_Player.enabled, "This will cause a leak and performance issues, GameInput.Player.Disable() has not been called."); } /// @@ -165,4 +263,133 @@ public int FindBinding(InputBinding bindingMask, out InputAction action) { return asset.FindBinding(bindingMask, out action); } + + // Player + private readonly InputActionMap m_Player; + private List m_PlayerActionsCallbackInterfaces = new List(); + private readonly InputAction m_Player_Move; + private readonly InputAction m_Player_Jump; + /// + /// Provides access to input actions defined in input action map "Player". + /// + public struct PlayerActions + { + private @GameInput m_Wrapper; + + /// + /// Construct a new instance of the input action map wrapper class. + /// + public PlayerActions(@GameInput wrapper) { m_Wrapper = wrapper; } + /// + /// Provides access to the underlying input action "Player/Move". + /// + public InputAction @Move => m_Wrapper.m_Player_Move; + /// + /// Provides access to the underlying input action "Player/Jump". + /// + public InputAction @Jump => m_Wrapper.m_Player_Jump; + /// + /// Provides access to the underlying input action map instance. + /// + public InputActionMap Get() { return m_Wrapper.m_Player; } + /// + public void Enable() { Get().Enable(); } + /// + public void Disable() { Get().Disable(); } + /// + public bool enabled => Get().enabled; + /// + /// Implicitly converts an to an instance. + /// + public static implicit operator InputActionMap(PlayerActions set) { return set.Get(); } + /// + /// Adds , and callbacks provided via on all input actions contained in this map. + /// + /// Callback instance. + /// + /// If is null or have already been added this method does nothing. + /// + /// + public void AddCallbacks(IPlayerActions instance) + { + if (instance == null || m_Wrapper.m_PlayerActionsCallbackInterfaces.Contains(instance)) return; + m_Wrapper.m_PlayerActionsCallbackInterfaces.Add(instance); + @Move.started += instance.OnMove; + @Move.performed += instance.OnMove; + @Move.canceled += instance.OnMove; + @Jump.started += instance.OnJump; + @Jump.performed += instance.OnJump; + @Jump.canceled += instance.OnJump; + } + + /// + /// Removes , and callbacks provided via on all input actions contained in this map. + /// + /// + /// Calling this method when have not previously been registered has no side-effects. + /// + /// + private void UnregisterCallbacks(IPlayerActions instance) + { + @Move.started -= instance.OnMove; + @Move.performed -= instance.OnMove; + @Move.canceled -= instance.OnMove; + @Jump.started -= instance.OnJump; + @Jump.performed -= instance.OnJump; + @Jump.canceled -= instance.OnJump; + } + + /// + /// Unregisters and unregisters all input action callbacks via . + /// + /// + public void RemoveCallbacks(IPlayerActions instance) + { + if (m_Wrapper.m_PlayerActionsCallbackInterfaces.Remove(instance)) + UnregisterCallbacks(instance); + } + + /// + /// Replaces all existing callback instances and previously registered input action callbacks associated with them with callbacks provided via . + /// + /// + /// If is null, calling this method will only unregister all existing callbacks but not register any new callbacks. + /// + /// + /// + /// + public void SetCallbacks(IPlayerActions instance) + { + foreach (var item in m_Wrapper.m_PlayerActionsCallbackInterfaces) + UnregisterCallbacks(item); + m_Wrapper.m_PlayerActionsCallbackInterfaces.Clear(); + AddCallbacks(instance); + } + } + /// + /// Provides a new instance referencing this action map. + /// + public PlayerActions @Player => new PlayerActions(this); + /// + /// Interface to implement callback methods for all input action callbacks associated with input actions defined by "Player" which allows adding and removing callbacks. + /// + /// + /// + public interface IPlayerActions + { + /// + /// Method invoked when associated input action "Move" is either , or . + /// + /// + /// + /// + void OnMove(InputAction.CallbackContext context); + /// + /// Method invoked when associated input action "Jump" is either , or . + /// + /// + /// + /// + void OnJump(InputAction.CallbackContext context); + } } diff --git a/Assets/02_Scripts/Managers.meta b/Assets/02_Scripts/Managers.meta new file mode 100644 index 0000000..89db601 --- /dev/null +++ b/Assets/02_Scripts/Managers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7d7ada469de944146b28b3ce90c9c5a8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/02_Scripts/Managers/InputManager.cs b/Assets/02_Scripts/Managers/InputManager.cs new file mode 100644 index 0000000..7b4d316 --- /dev/null +++ b/Assets/02_Scripts/Managers/InputManager.cs @@ -0,0 +1,41 @@ +using System; +using UnityEngine; +using UnityEngine.InputSystem; + +public class InputManager : MonoBehaviour, GameInput.IPlayerActions +{ + public static InputManager Instance { get; private set; } + + private GameInput _input; + + public event Action OnMove_Event; + public event Action OnJump_Event; + + private void Awake() + { + if (Instance != null && Instance != this) + { + Destroy(gameObject); + return; + } + Instance = this; + + _input = new GameInput(); + _input.Player.SetCallbacks(this); + } + + private void OnEnable() => _input?.Player.Enable(); + private void OnDisable() => _input?.Player.Disable(); + private void OnDestroy() => _input?.Dispose(); + + public void OnMove(InputAction.CallbackContext ctx) + { + OnMove_Event?.Invoke(ctx.ReadValue()); + } + + public void OnJump(InputAction.CallbackContext ctx) + { + if (ctx.phase == InputActionPhase.Started) + OnJump_Event?.Invoke(); + } +} diff --git a/Assets/02_Scripts/Managers/InputManager.cs.meta b/Assets/02_Scripts/Managers/InputManager.cs.meta new file mode 100644 index 0000000..38ce1c4 --- /dev/null +++ b/Assets/02_Scripts/Managers/InputManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 1ab82478c2bf3494eb4dd5cc16128e9f \ No newline at end of file diff --git a/Assets/02_Scripts/Player/PlayerController.cs b/Assets/02_Scripts/Player/PlayerController.cs index 37a249b..2337210 100644 --- a/Assets/02_Scripts/Player/PlayerController.cs +++ b/Assets/02_Scripts/Player/PlayerController.cs @@ -2,15 +2,60 @@ public class PlayerController : MonoBehaviour { - // Start is called once before the first execution of Update after the MonoBehaviour is created - void Start() + [Header("Movement")] + [SerializeField] private float moveSpeed = 5f; + + [Header("Jump")] + [SerializeField] private float jumpForce = 12f; + [SerializeField] private Transform groundCheck; + [SerializeField] private float groundCheckRadius = 0.1f; + [SerializeField] private LayerMask groundLayer; + + private Rigidbody2D rb; + private float moveInputX = 0f; + private bool isGrounded; + + private void Awake() { - + rb = GetComponent(); } - // Update is called once per frame - void Update() + private void Start() { - + InputManager.Instance.OnMove_Event += OnMoveInput; + InputManager.Instance.OnJump_Event += OnJumpInput; + } + + private void OnDestroy() + { + if (InputManager.Instance != null) + { + InputManager.Instance.OnMove_Event -= OnMoveInput; + InputManager.Instance.OnJump_Event -= OnJumpInput; + } + } + + private void FixedUpdate() + { + isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer); + rb.linearVelocity = new Vector2(moveInputX * moveSpeed, rb.linearVelocity.y); + } + + private void OnMoveInput(Vector2 value) + { + moveInputX = value.x == 0f ? 0f : Mathf.Sign(value.x); + } + + private void OnJumpInput() + { + if (isGrounded) + rb.linearVelocity = new Vector2(rb.linearVelocity.x, jumpForce); + } + + private void OnDrawGizmosSelected() + { + if (groundCheck == null) return; + Gizmos.color = isGrounded ? Color.green : Color.red; + Gizmos.DrawWireSphere(groundCheck.position, groundCheckRadius); } } diff --git a/Assets/11_Input/GameInput.inputactions b/Assets/11_Input/GameInput.inputactions index 366c48a..81ac07e 100644 --- a/Assets/11_Input/GameInput.inputactions +++ b/Assets/11_Input/GameInput.inputactions @@ -1,6 +1,99 @@ { - "version": 0, + "version": 1, "name": "GameInput", - "maps": [], + "maps": [ + { + "name": "Player", + "id": "e331468a-870b-4a9d-adfc-33c89a2aa65d", + "actions": [ + { + "name": "Move", + "type": "Value", + "id": "63ac178d-1333-427a-9f57-780afc877807", + "expectedControlType": "Vector2", + "processors": "", + "interactions": "", + "initialStateCheck": true + }, + { + "name": "Jump", + "type": "Button", + "id": "a8c7f1d2-3e4b-4a5c-9d6e-7f8901234567", + "expectedControlType": "", + "processors": "", + "interactions": "", + "initialStateCheck": false + } + ], + "bindings": [ + { + "name": "2D Vector", + "id": "1c7aa2cd-7385-4e38-8392-a1cecb8adc98", + "path": "2DVector", + "interactions": "", + "processors": "", + "groups": "", + "action": "Move", + "isComposite": true, + "isPartOfComposite": false + }, + { + "name": "up", + "id": "50a77fe5-4fb2-4e7a-bd0c-973407f67e90", + "path": "/upArrow", + "interactions": "", + "processors": "", + "groups": "", + "action": "Move", + "isComposite": false, + "isPartOfComposite": true + }, + { + "name": "down", + "id": "2306a862-a3c3-48b1-8a28-ce80c7d9e2ea", + "path": "/downArrow", + "interactions": "", + "processors": "", + "groups": "", + "action": "Move", + "isComposite": false, + "isPartOfComposite": true + }, + { + "name": "left", + "id": "819efc78-8db1-481e-b737-4fef39f2fa3f", + "path": "/leftArrow", + "interactions": "", + "processors": "", + "groups": "", + "action": "Move", + "isComposite": false, + "isPartOfComposite": true + }, + { + "name": "right", + "id": "eab43684-ffd8-44c3-bca7-03dce6685fbb", + "path": "/rightArrow", + "interactions": "", + "processors": "", + "groups": "", + "action": "Move", + "isComposite": false, + "isPartOfComposite": true + }, + { + "name": "", + "id": "b9d8e2f3-4a5c-4b6d-8e7f-901234567890", + "path": "/space", + "interactions": "", + "processors": "", + "groups": "", + "action": "Jump", + "isComposite": false, + "isPartOfComposite": false + } + ] + } + ], "controlSchemes": [] } \ No newline at end of file diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset index 5102174..b41941b 100644 --- a/ProjectSettings/TagManager.asset +++ b/ProjectSettings/TagManager.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c5724a690fc85c8ff2cdd7cd4de871fc692f50f7e8ff13992b3e175da80aeb3 -size 558 +oid sha256:6fd895357f68c28a46bc0c75ed7d3a1e61eb96e55b3b1d34bf9919cad44b033c +size 564