2026-05-14 2D Platformer Game 캐릭터 이동

This commit is contained in:
2026-05-14 18:01:14 +09:00
parent ea31d5a4e0
commit 764bc305f7
10 changed files with 450 additions and 14 deletions

Binary file not shown.

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 02c0fdb393749ab49a9e54c7282c6f09

View File

@@ -85,15 +85,113 @@ public partial class @GameInput: IInputActionCollection2, IDisposable
public @GameInput() public @GameInput()
{ {
asset = InputActionAsset.FromJson(@"{ asset = InputActionAsset.FromJson(@"{
""version"": 0, ""version"": 1,
""name"": ""GameInput"", ""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"": ""<Keyboard>/upArrow"",
""interactions"": """",
""processors"": """",
""groups"": """",
""action"": ""Move"",
""isComposite"": false,
""isPartOfComposite"": true
},
{
""name"": ""down"",
""id"": ""2306a862-a3c3-48b1-8a28-ce80c7d9e2ea"",
""path"": ""<Keyboard>/downArrow"",
""interactions"": """",
""processors"": """",
""groups"": """",
""action"": ""Move"",
""isComposite"": false,
""isPartOfComposite"": true
},
{
""name"": ""left"",
""id"": ""819efc78-8db1-481e-b737-4fef39f2fa3f"",
""path"": ""<Keyboard>/leftArrow"",
""interactions"": """",
""processors"": """",
""groups"": """",
""action"": ""Move"",
""isComposite"": false,
""isPartOfComposite"": true
},
{
""name"": ""right"",
""id"": ""eab43684-ffd8-44c3-bca7-03dce6685fbb"",
""path"": ""<Keyboard>/rightArrow"",
""interactions"": """",
""processors"": """",
""groups"": """",
""action"": ""Move"",
""isComposite"": false,
""isPartOfComposite"": true
},
{
""name"": """",
""id"": ""b9d8e2f3-4a5c-4b6d-8e7f-901234567890"",
""path"": ""<Keyboard>/space"",
""interactions"": """",
""processors"": """",
""groups"": """",
""action"": ""Jump"",
""isComposite"": false,
""isPartOfComposite"": false
}
]
}
],
""controlSchemes"": [] ""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() ~@GameInput()
{ {
UnityEngine.Debug.Assert(!m_Player.enabled, "This will cause a leak and performance issues, GameInput.Player.Disable() has not been called.");
} }
/// <summary> /// <summary>
@@ -165,4 +263,133 @@ public int FindBinding(InputBinding bindingMask, out InputAction action)
{ {
return asset.FindBinding(bindingMask, out action); return asset.FindBinding(bindingMask, out action);
} }
// Player
private readonly InputActionMap m_Player;
private List<IPlayerActions> m_PlayerActionsCallbackInterfaces = new List<IPlayerActions>();
private readonly InputAction m_Player_Move;
private readonly InputAction m_Player_Jump;
/// <summary>
/// Provides access to input actions defined in input action map "Player".
/// </summary>
public struct PlayerActions
{
private @GameInput m_Wrapper;
/// <summary>
/// Construct a new instance of the input action map wrapper class.
/// </summary>
public PlayerActions(@GameInput wrapper) { m_Wrapper = wrapper; }
/// <summary>
/// Provides access to the underlying input action "Player/Move".
/// </summary>
public InputAction @Move => m_Wrapper.m_Player_Move;
/// <summary>
/// Provides access to the underlying input action "Player/Jump".
/// </summary>
public InputAction @Jump => m_Wrapper.m_Player_Jump;
/// <summary>
/// Provides access to the underlying input action map instance.
/// </summary>
public InputActionMap Get() { return m_Wrapper.m_Player; }
/// <inheritdoc cref="UnityEngine.InputSystem.InputActionMap.Enable()" />
public void Enable() { Get().Enable(); }
/// <inheritdoc cref="UnityEngine.InputSystem.InputActionMap.Disable()" />
public void Disable() { Get().Disable(); }
/// <inheritdoc cref="UnityEngine.InputSystem.InputActionMap.enabled" />
public bool enabled => Get().enabled;
/// <summary>
/// Implicitly converts an <see ref="PlayerActions" /> to an <see ref="InputActionMap" /> instance.
/// </summary>
public static implicit operator InputActionMap(PlayerActions set) { return set.Get(); }
/// <summary>
/// Adds <see cref="InputAction.started"/>, <see cref="InputAction.performed"/> and <see cref="InputAction.canceled"/> callbacks provided via <param cref="instance" /> on all input actions contained in this map.
/// </summary>
/// <param name="instance">Callback instance.</param>
/// <remarks>
/// If <paramref name="instance" /> is <c>null</c> or <paramref name="instance"/> have already been added this method does nothing.
/// </remarks>
/// <seealso cref="PlayerActions" />
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;
}
/// <summary>
/// Removes <see cref="InputAction.started"/>, <see cref="InputAction.performed"/> and <see cref="InputAction.canceled"/> callbacks provided via <param cref="instance" /> on all input actions contained in this map.
/// </summary>
/// <remarks>
/// Calling this method when <paramref name="instance" /> have not previously been registered has no side-effects.
/// </remarks>
/// <seealso cref="PlayerActions" />
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;
}
/// <summary>
/// Unregisters <param cref="instance" /> and unregisters all input action callbacks via <see cref="PlayerActions.UnregisterCallbacks(IPlayerActions)" />.
/// </summary>
/// <seealso cref="PlayerActions.UnregisterCallbacks(IPlayerActions)" />
public void RemoveCallbacks(IPlayerActions instance)
{
if (m_Wrapper.m_PlayerActionsCallbackInterfaces.Remove(instance))
UnregisterCallbacks(instance);
}
/// <summary>
/// Replaces all existing callback instances and previously registered input action callbacks associated with them with callbacks provided via <param cref="instance" />.
/// </summary>
/// <remarks>
/// If <paramref name="instance" /> is <c>null</c>, calling this method will only unregister all existing callbacks but not register any new callbacks.
/// </remarks>
/// <seealso cref="PlayerActions.AddCallbacks(IPlayerActions)" />
/// <seealso cref="PlayerActions.RemoveCallbacks(IPlayerActions)" />
/// <seealso cref="PlayerActions.UnregisterCallbacks(IPlayerActions)" />
public void SetCallbacks(IPlayerActions instance)
{
foreach (var item in m_Wrapper.m_PlayerActionsCallbackInterfaces)
UnregisterCallbacks(item);
m_Wrapper.m_PlayerActionsCallbackInterfaces.Clear();
AddCallbacks(instance);
}
}
/// <summary>
/// Provides a new <see cref="PlayerActions" /> instance referencing this action map.
/// </summary>
public PlayerActions @Player => new PlayerActions(this);
/// <summary>
/// Interface to implement callback methods for all input action callbacks associated with input actions defined by "Player" which allows adding and removing callbacks.
/// </summary>
/// <seealso cref="PlayerActions.AddCallbacks(IPlayerActions)" />
/// <seealso cref="PlayerActions.RemoveCallbacks(IPlayerActions)" />
public interface IPlayerActions
{
/// <summary>
/// Method invoked when associated input action "Move" is either <see cref="UnityEngine.InputSystem.InputAction.started" />, <see cref="UnityEngine.InputSystem.InputAction.performed" /> or <see cref="UnityEngine.InputSystem.InputAction.canceled" />.
/// </summary>
/// <seealso cref="UnityEngine.InputSystem.InputAction.started" />
/// <seealso cref="UnityEngine.InputSystem.InputAction.performed" />
/// <seealso cref="UnityEngine.InputSystem.InputAction.canceled" />
void OnMove(InputAction.CallbackContext context);
/// <summary>
/// Method invoked when associated input action "Jump" is either <see cref="UnityEngine.InputSystem.InputAction.started" />, <see cref="UnityEngine.InputSystem.InputAction.performed" /> or <see cref="UnityEngine.InputSystem.InputAction.canceled" />.
/// </summary>
/// <seealso cref="UnityEngine.InputSystem.InputAction.started" />
/// <seealso cref="UnityEngine.InputSystem.InputAction.performed" />
/// <seealso cref="UnityEngine.InputSystem.InputAction.canceled" />
void OnJump(InputAction.CallbackContext context);
}
} }

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7d7ada469de944146b28b3ce90c9c5a8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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<Vector2> 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<Vector2>());
}
public void OnJump(InputAction.CallbackContext ctx)
{
if (ctx.phase == InputActionPhase.Started)
OnJump_Event?.Invoke();
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1ab82478c2bf3494eb4dd5cc16128e9f

View File

@@ -2,15 +2,60 @@
public class PlayerController : MonoBehaviour public class PlayerController : MonoBehaviour
{ {
// Start is called once before the first execution of Update after the MonoBehaviour is created [Header("Movement")]
void Start() [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<Rigidbody2D>();
} }
// Update is called once per frame private void Start()
void Update()
{ {
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);
} }
} }

View File

@@ -1,6 +1,99 @@
{ {
"version": 0, "version": 1,
"name": "GameInput", "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": "<Keyboard>/upArrow",
"interactions": "",
"processors": "",
"groups": "",
"action": "Move",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "down",
"id": "2306a862-a3c3-48b1-8a28-ce80c7d9e2ea",
"path": "<Keyboard>/downArrow",
"interactions": "",
"processors": "",
"groups": "",
"action": "Move",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "left",
"id": "819efc78-8db1-481e-b737-4fef39f2fa3f",
"path": "<Keyboard>/leftArrow",
"interactions": "",
"processors": "",
"groups": "",
"action": "Move",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "right",
"id": "eab43684-ffd8-44c3-bca7-03dce6685fbb",
"path": "<Keyboard>/rightArrow",
"interactions": "",
"processors": "",
"groups": "",
"action": "Move",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "",
"id": "b9d8e2f3-4a5c-4b6d-8e7f-901234567890",
"path": "<Keyboard>/space",
"interactions": "",
"processors": "",
"groups": "",
"action": "Jump",
"isComposite": false,
"isPartOfComposite": false
}
]
}
],
"controlSchemes": [] "controlSchemes": []
} }

Binary file not shown.