Quick Reference
- 기준은 Unity 6.5 (6000.5), Input System 1.14.2입니다. Interaction은 한 action의 언제 수행할지를 정하고, Control Scheme은 player가 사용할 장치 묶음을 정하며, rebinding은 binding의
overridePath만 runtime에서 바꿉니다. Tap,Hold,SlowTap,MultiTap,Press는 같은 키의 의미가 실제로 다를 때만 사용합니다. 단순히 입력 처리를 늦추기 위한 timer 대용으로 붙이면 phase와 timeout을 해석하기 어려워집니다.- rebinding 결과는 asset 원본을 덮어쓰지 않습니다. override JSON을 저장·복원하고, 같은 scheme에서 이미 쓰는 control인지 검사하며, 완료·취소 모두
RebindingOperation.Dispose()로 끝냅니다.
text
Jump: Button + Press
Charge: Button + Hold(duration=0.5초)
Move: Value/Vector2 + 2D Vector composite (W/A/S/D)
Keyboard&Mouse scheme: Keyboard + Mouse 필요
Gamepad scheme: Gamepad 필요Interaction과 Control Scheme 설정
- Action 또는 개별 Binding의 Interactions에
Press,Hold,Tap,SlowTap,MultiTap을 넣습니다. Binding에 둔 설정은 그 binding에만, Action에 둔 설정은 action 전체에 적용됩니다. 같은 action에 여러 interaction을 넣을 때 순서가 상태를 먼저 소유하는 interaction을 결정할 수 있으므로, 단발 공격과 차지 공격을 한 action에 계속 쌓기보다 행동을 분리할지도 검토합니다. - callback의 Started는 interaction이 입력을 시작해 관찰할 때, Performed는 조건을 만족해 행동을 실행할 때, Canceled는 release 또는 조건 실패로 끝날 때입니다.
Holdcharge bar는started에서 보이고,performed에서 발사하고,canceled에서는 UI와 임시 state를 정리합니다. Hold와SlowTap의 duration은 초 단위입니다. action 또는 binding에 duration을 직접 지정하지 않으면 Input System의 project-wide default interaction time을 사용합니다. 기획상 0.5초인지 1초인지처럼 정확한 조작감을 요구하면 action에 값을 명시하고, UI 진행률도 같은 timeout을 기준으로 계산합니다.- Control Schemes의 Device Requirement는 scheme이 성립하려면 필요한 장치입니다.
Keyboard&Mouse에 Keyboard와 Mouse를 모두 required로 두면 mouse가 없는 상태에서 그 scheme은 선택되지 않습니다.optional장치를 남용하면 player가 어떤 prompt를 봐야 하는지 불명확해집니다. - Binding Groups는 binding을 어느 control scheme에 속하게 할지 정합니다. scheme을 만들고 binding group을 비워 두면 모든 장치 binding이 함께 살아 있어, gamepad player의 키보드 입력이 gameplay에 들어오는 이유가 됩니다.
- 2D Vector composite는 up/down/left/right part에 각각 키를 넣어 하나의
Vector2로 읽습니다.Normalizeprocessor 또는 movement code의 normalize를 두 군데 모두 적용하면 analog stick의 세기까지 잃을 수 있습니다.
Rebinding과 스크립트 연결
csharp
using UnityEngine;
using UnityEngine.InputSystem;
public sealed class RebindJump : MonoBehaviour
{
[SerializeField] private InputActionReference jump;
[SerializeField] private int bindingIndex;
private InputActionRebindingExtensions.RebindingOperation operation;
public void StartRebind()
{
operation?.Cancel();
operation?.Dispose();
operation = jump.action.PerformInteractiveRebinding(bindingIndex)
.WithControlsExcluding("<Mouse>/position")
.WithCancelingThrough("<Keyboard>/escape")
.OnComplete(Finish)
.OnCancel(Cancel)
.Start();
}
private void Finish(InputActionRebindingExtensions.RebindingOperation completed)
{
string json = jump.action.actionMap.asset.SaveBindingOverridesAsJson();
PlayerPrefs.SetString("input.bindingOverrides", json);
PlayerPrefs.Save();
completed.Dispose();
operation = null;
}
private void Cancel(InputActionRebindingExtensions.RebindingOperation canceled)
{
canceled.Dispose();
operation = null;
}
}- 시작 시에는
LoadBindingOverridesFromJson으로 같은 action asset에 저장값을 복원합니다. JSON은 path override만 담으므로 asset의 action 이름·binding 구조를 크게 바꾼 뒤에는 이전 save가 더 이상 유효하지 않을 수 있습니다. version을 함께 저장하거나 load 실패 시RemoveAllBindingOverrides()로 기본값으로 되돌리는 경로를 둡니다. RebindingOperation은 unmanaged memory를 사용하므로 complete, cancel, owner destroy에 모두Dispose()가 필요합니다. rebind UI를 닫을 때 작업을 취소하지 않으면 뒤늦게 누른 키가 보이지 않는 action에 적용될 수 있습니다.- 패키지는 “같은 키가 두 gameplay 행동에 배정되면 안 된다”는 게임 규칙을 자동 판단하지 않습니다. 완료 전에 현재 scheme의 다른 binding
effectivePath를 비교하고, 중복이면 confirm·swap·거절 중 하나를 UX로 정합니다. composite의 part와 action 전체 binding도 구분해서 검사합니다. PlayerInput.onControlsChanged는 paired device, control scheme, rebind override가 바뀌는 때에 UI prompt 갱신 지점이 됩니다. C# Events behavior에서만 이 이벤트를 받으므로 PlayerInput Inspector와 함께 설정합니다.
자주 틀리는 부분
performed만 보고 charge state를 정리하면 release나 timeout 실패 후 UI가 남을 수 있습니다. Interaction을 쓰는 action은 started, performed, canceled를 상태 전이로 함께 설계하세요.
rebind를 저장했는데 다음 실행에 키가 돌아가는 문제는 asset을 다시 만들었기 때문이 아니라 override를 복원하지 않았기 때문인 경우가 많습니다. 저장과 load, reset, conflict 처리, dispose를 하나의 기능으로 닫으세요.
참고 링크
2 sources