
유니티 TMP InputField 에서 Enter 를 눌렀을 때만 처리하려면 onSubmit 을 씁니다. onEndEdit 은 Enter 말고도 다른 곳을 클릭하거나 Esc 를 눌러 입력이 끝날 때마다 불리고, onValueChanged 는 글자가 바뀔 때마다 불립니다.
input.onValueChanged.AddListener(text => Debug.Log("바뀜 " + text)); // 글자가 바뀔 때마다
input.onSubmit.AddListener(text => Debug.Log("보냄 " + text)); // Enter · 모바일 키보드 완료
input.onEndEdit.AddListener(text => Debug.Log("끝 " + text)); // Enter · 다른 곳 클릭 · Esc
채팅창, 검색창, 닉네임 입력처럼 글자를 받는 화면은 「언제 처리할지」 가 중요합니다. 채팅을 onEndEdit 에 연결하면 입력칸 밖을 클릭만 해도 메시지가 나가 버립니다. 이 블로그의 예전 글 UI InputField 기본 기능 할당 in Script 는 예전 InputField 로 contentType 과 lineType 을 정하고 onValueChanged · onEndEdit 을 붙이는 예제였습니다. 이번 글에서는 TMP_InputField 로 Enter 를 누르면 메시지가 쌓이고, 입력칸이 비워진 뒤 바로 이어서 칠 수 있는 채팅 입력칸을 만들겠습니다. 세 이벤트가 언제 불리는지도 함께 정리하겠습니다.
C# (UNITY 3D)

▲ 아래 ChatInput 의 동작을 옮긴 웹 데모입니다(Unity 화면 아님). 이벤트가 불리는 순서는 TMP_InputField 소스와 같습니다.
Enter 를 누르면 onSubmit 이 먼저 불려 메시지가 올라가고 입력칸이 비워진 뒤 onEndEdit 이 불립니다. 다른 곳을 클릭하면 onEndEdit 만 불려 메시지는 나가지 않습니다. Esc 를 누르면 입력을 시작할 때의 글자로 되돌아갑니다.
1. 준비 — 입력칸 하나와 글자 둘
Hierarchy 에서 UI (Canvas) > Input Field - TextMeshPro 로 입력칸을, UI (Canvas) > Text - TextMeshPro 로 대화 내용과 글자 수를 보여 줄 글자 둘을 만듭니다(예전 버전 메뉴는 UI > …). ChatInput 은 입력칸 오브젝트에 직접 붙이고, text_log 칸에 대화 글자를, text_count 칸에 글자 수 글자를 끌어다 넣습니다.
using UnityEngine;
using TMPro;
TMP_InputField 와 TMP_Text 를 쓰기 위해 TMPro 를 사용합니다. 이번 코드는 Image 나 Button 을 쓰지 않아 UnityEngine.UI 는 필요 없습니다.
2. 채팅 입력칸 코드
using UnityEngine;
using TMPro;
//CodeFinder 코드파인더
//From https://codefinder.janndk.com/
[RequireComponent(typeof(TMP_InputField))]
public class ChatInput : MonoBehaviour
{
public TMP_Text text_log; // 보낸 말을 쌓아 보여 줄 글자
public TMP_Text text_count; // 「12/30」 처럼 글자 수를 보여 줄 글자
TMP_InputField input_chat;
void Awake()
{
input_chat = GetComponent<TMP_InputField>();
}
void Start()
{
input_chat.characterLimit = 30; // 30자까지만
input_chat.lineType = TMP_InputField.LineType.SingleLine; // Enter 는 줄바꿈이 아니라 보내기
input_chat.onValueChanged.RemoveAllListeners();
input_chat.onValueChanged.AddListener(Update_Count); // 글자가 바뀔 때마다
input_chat.onSubmit.RemoveAllListeners();
input_chat.onSubmit.AddListener(Send_Message); // Enter 를 눌렀을 때만
Update_Count(input_chat.text);
}
void Update_Count(string text)
{
if (text_count != null)
text_count.text = text.Length + "/" + input_chat.characterLimit;
}
void Send_Message(string text)
{
string message = text.Trim();
if (message.Length == 0)
return; // 빈 칸 · 공백만이면 안 보냄
if (text_log != null)
text_log.text += message + "\n";
input_chat.text = ""; // 비우면 onValueChanged 도 불려 0/30
input_chat.ActivateInputField(); // 이어서 바로 칠 수 있게 다시 포커스
}
}
Play 하면 글자 수 칸에 「0/30」 이 보이고, 칠 때마다 숫자가 올라갑니다. Enter 를 누르면 앞뒤 공백을 지운 메시지가 대화 글자에 한 줄 쌓이고 입력칸은 비워집니다. 공백만 넣고 Enter 를 누르면 아무것도 쌓이지 않습니다.
이 스크립트는 Unity 6000.6.3f1 에서 컴파일 오류 없이 들어갔고, 배치 모드에서 onSubmit 에 「 안녕하세요 」 를 넣으니 대화 글자에 「안녕하세요」 가 쌓이고 입력칸은 빈칸, 글자 수는 「0/30」 이 되었습니다. 다시 포커스가 잡히는 것은 Game 창에서 확인하지 못했습니다. TMP_InputField 소스를 보면 ActivateInputField 는 다음 LateUpdate 에 입력칸을 다시 열도록 예약하는 함수라, Enter 로 입력칸이 닫힌 뒤에 다시 열립니다.
변수(variable)
text_log(TMP_Text) : 보낸 메시지를 한 줄씩 쌓아 보여 줄 글자
text_count(TMP_Text) : 지금 글자 수와 최대 글자 수를 보여 줄 글자
input_chat(TMP_InputField) : 같은 오브젝트의 입력칸
함수(function)
Update_Count : 글자가 바뀔 때 불려 「5/30」 처럼 글자 수를 보여 줍니다.
Send_Message : Enter 를 누를 때 불려 메시지를 쌓고 입력칸을 비웁니다.
3. onValueChanged · onSubmit · onEndEdit 은 언제 불리나

Enter 로 끝내면 onSubmit 다음에 onEndEdit 이 불립니다. 모바일 키보드의 완료 버튼도 같은 길을 탑니다. 다른 곳을 클릭하면 onEndEdit 만 불립니다. Esc 를 눌러도 onSubmit 은 불리지 않습니다. Esc 는 Restore On ESC Key 가 켜져 있으면(기본값) 입력을 시작할 때의 글자로 되돌리고(글자가 바뀌어 있었다면 이때 onValueChanged 가 불립니다), 그 글자를 onEndEdit 에 넘깁니다.
Line Type 이 Multi Line Newline 이면 Enter 는 줄바꿈이 되어 onSubmit 이 불리지 않습니다. 채팅처럼 Enter 로 보내려면 Single Line 이나 Multi Line Submit 으로 둡니다.
4. 어떻게 끝내든 저장할 값은 onEndEdit
input_name.onEndEdit.AddListener(text =>
{
PlayerPrefs.SetString("nickname", text.Trim());
});
닉네임이나 설정값처럼 사용자가 Enter 를 누르지 않고 다른 곳을 눌러도 저장되어야 하는 값은 onEndEdit 이 맞습니다. 반대로 채팅 전송, 검색 실행처럼 「보내기」 의 뜻이 있는 동작은 onSubmit 에 둡니다.
5. 입력이 이상할 때 — 자주 하는 실수
onSubmit 과 onEndEdit 에 둘 다 연결했더니 onEndEdit 이 빈 글자를 받는다
onSubmit 안에서 입력칸을 비우면 그 뒤에 불리는 onEndEdit 은 비워진 글자를 받습니다. 배치 모드에서 불러 보니 onSubmit("msg") → onValueChanged("") → onEndEdit("") 순서였습니다. 보낸 메시지는 onSubmit 쪽에서 처리합니다.
input_age.contentType = TMP_InputField.ContentType.IntegerNumber;
input_age.onEndEdit.AddListener(text =>
{
if (int.TryParse(text, out int age))
Debug.Log("나이 " + age);
});
숫자만 받게 했는데 글자가 들어 있다
contentType 과 characterLimit 은 사용자가 칠 때만 걸립니다. 코드로 text 에 「12a3」 이나 40자짜리 글을 넣으면 그대로 들어가는 것을 확인했습니다. 빈칸도 올 수 있으니 숫자로 쓸 때는 int.TryParse 로 한 번 더 확인합니다.
함께 보기: 예전 InputField 로 contentType · lineType 을 정하는 기본 예제는 예전 글 UI InputField 기본 기능 할당 in Script 에 있습니다.
TMP_InputField 동작은 Unity 공식 문서 TMP_InputField (uGUI) 와 Unity 6000.6.3f1 의 ugui 패키지 소스를 기준으로 적었습니다.
'Unity3D > C#' 카테고리의 다른 글
| 유니티 Slider onValueChanged 로 값 표시 · 정수 단계 · 저장값 불러오기 (wholeNumbers, SetValueWithoutNotify) (0) | 2026.10.23 |
|---|---|
| 유니티 HEX 색상 코드 ↔ Color 변환 (Unity color from hex / to hex) (0) | 2026.10.22 |
| 유니티 토글(Toggle) 켜기/끄기 · 토글 그룹 하나만 고르기 (0) | 2026.10.21 |
| 유니티 드롭다운(TMP Dropdown) 값 읽기 · 옵션 코드로 넣기 (0) | 2026.10.20 |
| 유니티 타이머 카운트다운 · 스톱워치 · 일시정지 (Time.deltaTime, unscaledDeltaTime) (0) | 2026.10.19 |