UDN
Search public documentation:

CLIKChatBoxKR
English Translation
日本語訳
中国翻译

Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 홈 > 유저 인터페이스와 HUD > Scaleform GFx > 간단한 채팅 박스 만드는 법

간단한 채팅 박스 만드는 법


문서 변경내역: James Tan 작성. 홍성진 번역. UDK 2011년 9월 버전으로 최종 테스트.

개요


게임플레이 중 사용할 수 있는 아주 기본적인 여러줄 멀티플레이어 채팅창을 만드는 데 필요한 작업을 단계별로 다뤄보는 중고급 튜토리얼입니다. 모든 키보드 입력을 캡처하여, 채팅창에 포커스가 잡혀있을 때는 게임이 키보드를 캡처하지 못하도록 하기도 해야겠죠. 채팅 입력을 시작하는 데는 두 가지 방법, 마우스 클릭 또는 키보드 명령을 통하는 방법을 제공합니다.

이 튜토리얼은 스케일폼과 CLIK 위젯 설정과 사용에 매우 익숙한 사용자를 대상으로 하며, 스케일폼 기반 HUD 에 돌아가는 마우스 커서가 있다는 것을 가정합니다. 리플리케이션 에 대한 해박한 지식 역시 필요합니다.

ALERT! 중요: 이 튜토리얼은 토글가능 마우스 튜토리얼 역시도 필요로 합니다.

플래시 셋업


텍스트 인풋 박스

  • HUD 위에 CLIK TextInput 위젯을 떨굽니다. (C:\UDK\UDK-2011-09\Development\Flash\CLIK\components\TextInput.FLA)
  • 인스턴스 이름을 chatInput 이라 짓습니다.
  • Component Inspector (CS4) 또는 Component Parameters rollout (CS5) 를 열고 'actAsButton' 를 켭니다.

전송 버튼

  • 다음으로 TextInput 위젯 옆에 CLIK Button 위젯을 떨굽니다. (C:\UDK\UDK-2011-09\Development\Flash\CLIK\components\Button.FLA)
  • 인스턴스 이름을 chatSendBtn 이라 짓습니다.
  • Component Inspector (CS4) 또는 Component Parameters rollout (CS5) 를 열고 버튼의 label 필드에 'Send' 라 입력합니다.

여러줄 스크롤가능 채팅 로그

  • TextInput 위젯 위에 CLIK Text Area 위젯을 떨굽니다. (C:\UDK\UDK-2011-09\Development\Flash\CLIK\components\TextArea.FLA)
  • 인스턴스 이름을 chatLog 라 짓습니다.
  • Component Inspector (CS4) 또는 Component Parameters rollout (CS5) 를 열고 'editable' 을 끕니다.
  • TextInput 위젯 오른쪽에 CLIK Scroll Bar 위젯을 떨굽니다. (C:\UDK\UDK-2011-09\Development\Flash\CLIK\components\Scrollbar.FLA)
  • 인스턴스 이름을 chatScrollBar 라 짓습니다.
  • Text Area 를 선택하고 Component Inspector (CS4) 또는 Component Parameters rollout (CS5) 를 열고 Text Area 의 scrollBar 필드를 chatScrollBar 로 설정합니다.

채팅 폼

  • 스테이지에 있는 네 위젯을 근처로 모아 박스를 이루도록 줄을 맞춥니다. 위젯은 필요한 대로 늘일(비균등 스케일 적용할) 수 있습니다.
  • 스테이지의 위젯 넷을 모두 선택하고 우클릭한 뒤 Convert to Symbol 을 선택합니다.
  • Name 은 chatForm 으로 설정합니다.
  • Type 은 Movie Clip 으로 설정합니다.
  • Export for ActionScript 와 Export in frame 1 을 켭니다.
  • Identifier 를 chatForm 으로 설정합니다.
  • Class 를 gfx.core.UIComponent 로 설정합니다.
  • OK 를 누릅니다.
  • 스테이지에서 chatForm 무비 클립을 지워, 라이브러리에 놔둡니다.

채팅 창

  • \Development\Flash\CLIK\demos\com\Scaleform\Window.as 파일을 \Development\Flash\CLIK\gfx\controls\Window.as 로 복사합니다.
  • 이 클래스 파일을 열고 7 번째 (클래스 정의) 줄을 이렇게 바꿉니다:

ActionScript
class gfx.controls.Window extends UIComponent {

  • \Development\Flash\CLIK\demos\WindowDemo.FLA 파일을 엽니다.
  • 이 파일의 라이브러리 패널로 갑니다.
  • WindowSkinned 심볼을 선택합니다.
  • WindowSkinned 심볼에 우클릭한 다음 Copy 를 선택합니다.
  • HUD FLA 파일로 돌아옵니다.
  • 스테이지에 우클릭하고 Paste 를 선택하여 윈도우 심볼을 자리에 붙여넣습니다.
  • 스테이지 좌하단 근처에 창 위치를 맞춥니다.
  • 인스턴스 이름을 chatWindow 라 짓습니다.
  • 스테이지에 chatWindow 를 선택한 상태로 Component Inspector (CS4) 또는 Component Parameters rollout (CS5) 를 엽니다.
  • formSource 를 chatForm 으로 설정합니다.
  • formType 이 심볼로 설정되어있는지 확인합니다.
  • maxHeight 와 maxWidget 를 400 으로 설정합니다.
  • minHeight 와 minWidget 를 200 으로 설정합니다.
  • offsetBottom 는 24, offsetLeft 는 20, offsetRight 는 20, offsetTop 는 46 으로 설정합니다. 테스트를 거쳐 다른 값을 넣어도 괜찮습니다.
  • Title 은 Chat 로 설정합니다.
  • 라이브러리 패널에서 WindowSkinned 심볼에 우클릭한 다음 Properties 를 선택합니다.
  • Class 필드를 gfx.controls.Window 로 바꾸고 OK 를 누릅니다.
  • 심볼을 다시 우클릭하고 Component Definition 을 선택합니다.
  • Class 필드를 gfx.controls.Window 로 변경하고 OK 를 누릅니다.
  • 저장하고 퍼블리시한 다음 평소처럼 SWF 파일을 UDK 로 임포트합니다. 이제 스테이지에 드래그 가능한 채팅창이 생길 것이며, 여기에는 채팅 입력, 채팅 부분, 전송 버튼, 스크롤바가 들어 있습니다.

HUD 클래스 UnrealScript


HUD 클래스는 GFxMoviePlayer 를 확장해야 합니다. UnrealScript HUD 클래스 파일에 다음과 같이 새로운 변수를 추가합니다:

YourHUD.uc
var WorldInfo ThisWorld;
var SFPlayerController PC;

var array<string> chatMessages; // 여기에 모든 채팅 메시지가 담깁니다.
var bool bChatting;

// 채팅 시스템에 대한 CLIK 위젯입니다.
var GFxClikWidget MyChatInput, MyChatSendButton, MyChatLog;

Start()/Init() 함수를 다음과 같이 변경합니다. (빨강 선 추가):

YourHUD.uc
function Init(optional LocalPlayer player)
{
  super.Init(player);
  ThisWorld = GetPC().WorldInfo;

  Start();
  Advance(0);

  // ... 여기에 기타 초기화 코드 ...

  // PlayerController 를 가지고 HUD 레지스터
  PC = SFPlayerController(GetPC());
  PC.registerHUD(self);
}

(예전 마우스 튜토리얼에서의) ToggleCursor() 함수를 변경합니다.

YourHUD.uc
/** 마우스 커서를 껐다/켰다 토글합니다. */
function ToggleCursor(bool showCursor, float mx, float my)
{
  if (showCursor)
  {
    MouseContainer = CreateMouseCursor();
    MouseCursor = MouseContainer.GetObject("my_cursor");
    MouseCursor.SetPosition(mx,my);
    MouseContainer.SetBool("topmostLevel", true);
  }
  else
  {
    MouseContainer.Invoke("removeMovieClip", args);
    MouseContainer = none;
  }

  if (!bChatting)
  {
    bCaptureInput = showCursor;
    bIgnoreMouseInput = !showCursor;
  }
  else
  {
    bCaptureInput = true;
    bIgnoreMouseInput = false;
  }
}

이제 HUD 의 WidgetInitialized() 함수를 변경하여 채팅 텍스트 입력 칸과 채팅 전송 버튼을 마우스로 클릭하는 이벤트에 대한 이벤트 리스너를 셋업합니다:

YourHUD.uc
event bool WidgetInitialized(name WidgetName, name WidgetPath, GFxObject Widget)
{
  switch(WidgetName)
  {
  case ('chatInput'):
    MyChatInput = GFxClikWidget(Widget);
    MyChatInput.AddEventListener('CLIK_press', OnChat);
    break;

  case ('chatSendBtn'):
    MyChatSendButton = GFxClikWidget(Widget);
    MyChatSendButton.AddEventListener('CLIK_press', OnChatSend);
    break;

  case ('chatLog'):
    MyChatLog = GFxClikWidget(Widget);
    break;

  default:
    break;
  }

  return true;
}

OnChat() 이벤트 핸들러를 추가합니다.

YourHUD.uc
// 이벤트 핸들러 - 플레이어가 채팅 박스 텍스트 입력 칸을 클릭했을 때를 처리합니다.
function OnChat(GFxClikWidget.EventData ev)
{
  bChatting = true;
}

OnChatSend() 함수를 추가합니다. 이 함수는 Send 버튼이 눌리면 메시지를 방송(Broadcast)하고, 콘트롤을 게임에 넘깁니다.

YourHUD.uc
function OnChatSend(GFxClikWidget.EventData ev)
{
  local string Msg;

  Msg = MyChatInput.GetString("text");

  if (Msg != "")
  {
    PC.SendTextToServer(PC, Msg);
  }

  MyChatInput.SetString("text", "");
  self.bCaptureInput = false;
  bChatting = false;
}

이제 채팅 영역을 업데이트하는 함수 부분으로, 지금까지 Broadcast() 에서 받은 메시지를 표시합니다:

YourHUD.uc
function UpdateChatLog(string message)
{
  local string displayMsg;
  local int i;

  chatMessages.AddItem(message);

  displayMsg = "";

  for (i = 0; i < chatMessages.length; i++)
  {
    displayMsg @= chatMessages[i];
    displayMsg @= "\n";
  }

  MyChatLog.SetString("text", displayMsg);
  MyChatLog.SetFloat("position", MyChatLog.GetFloat("maxscroll"));
}

defaultproperties 에 위젯 바인딩과 기타 중요 변수를 추가합니다:

YourHUD.uc
defaultproperties
{
    WidgetBindings.Add((WidgetName="chatInput",WidgetClass=class'GFxClikWidget'))
    WidgetBindings.Add((WidgetName="chatSendBtn",WidgetClass=class'GFxClikWidget'))
    WidgetBindings.Add((WidgetName="chatLog",WidgetClass=class'GFxClikWidget'))

    bIgnoreMouseInput = true;
    bCaptureInput = false;
}

GameInfo 클래스 셋업


GameInfo 클래스를 엽니다.

UTDeathmatch 처럼 UTGame 이나 그 자손을 확장하지 않는다면, 자신의 GameInfo 클래스에는 다음과 같은 변수만 추가해 줍니다. 이미 선언되어 있는 변수라면 컴파일할 때 경고가 뜹니다. 그럴 경우엔 자신의 GameInfo 클래스에서 제거해 주면 됩니다.

YourGameInfo.uc
var class<BroadcastHandler> BroadcastHandlerClass;
var BroadcastHandler BroadcastHandler;   // 메시지 (텍스트와 현지화된) 브로드캐스트를 처리합니다.

다음으로 GameInfo 클래스의 InitGame() 함수에 다음 줄을 추가합니다:

YourGameInfo.uc
event InitGame( string Options, out string ErrorMessage )
{
    Super.InitGame(Options, ErrorMessage);
    BroadcastHandler = spawn(BroadcastHandlerClass);
}

GameInfo 클래스 안에, \Development\Src\Engine\Classes\GameInfo.uc 의 Broadcast 이벤트 클래스를 덮어쓸 것입니다.

YourGameInfo.uc
event Broadcast(Actor Sender, coerce string Msg, optional name Type)
{
  local SFPlayerController PC;
  local PlayerReplicationInfo PRI;

  // 이 코드는 Sender 의 PlayerReplicationInfo 를 구합니다. 그것을 PRI.PlayerName 과 함께 사용하여 Sender 의 이름을 구합니다.
  if (Pawn(Sender) != None)
  {
    PRI = Pawn(Sender).PlayerReplicationInfo;
  }
  else if (Controller(Sender) != None)
  {
    PRI = Controller(Sender).PlayerReplicationInfo;
  }

  // 이ㅣ 줄은 "Say" 를 실행합니다.
  BroadcastHandler.Broadcast(Sender, Msg, Type);

  // 모든 플레이어(PlayerControllers)에게 받은 메시지를 방송하는 곳입니다.
  if (WorldInfo != None)
  {
    ForEach WorldInfo.AllControllers(class'SFPlayerController',PC)
    {
      `Log(Self$":: Sending "$PC$" a broadcast message from "$PRI.PlayerName$" which is '"$Msg$"'.");
      PC.ReceiveBroadcast(PRI.PlayerName, Msg);
    }
  }
}

마지막으로 GameInfo 클래스의 defaultproperties 에 다음 줄을 추가합니다. 클래스 이름 적절히 수정하는 것 잊지 마시구요:

YourGameInfo.uc
defaultproperties
{
  PlayerControllerClass=class'SFPlayerController'
  BroadcastHandlerClass=class'Engine.BroadcastHandler'
  HUDType=class'SFTutorial.SFHudWrapper'
  bUseClassicHUD=true
}

PlayerController 클래스 셋업


PlayerController 클래스(이 경우엔 SFPlayerController)를 만들고 엽니다:

SFPlayerController.uc
class SFPlayerController extends UTPlayerController;

먼저 PlayerController 에서 HUD 안에 있는 함수를 쉽게 호출할 수 있도록, PlayerController 안에다 HUD 에 레지스터하는 함수를 만들겠습니다:

SFPlayerController.uc
var SFHud MySFHud;

function registerHUD(SFHud hud)
{
  MySFHud = hud;
}

다음 함수는 메시지를 서버에 전송하는 데 사용됩니다:

SFPlayerController.uc
exec function SendTextToServer(SFPlayerController PC, String TextToSend)
{
  `Log(Self$":: Client wants to send '"$TextToSend$"' to the server.");
  ServerReceiveText(PC, TextToSend);
}

이 함수는 서버 메시지를 받은 다음 방송하는 데 사용됩니다:

SFPlayerController.uc
reliable server function ServerReceiveText(SFPlayerController PC, String ReceivedText)
{
  WorldInfo.Game.Broadcast(PC, ReceivedText, 'Say');
}

마지막으로 서버에서의 방송을 기다리가, 도착하면 채팅창으로 보내주는 클라이언트 함수를 만들어 줘야 합니다:

SFPlayerController.uc
reliable client function ReceiveBroadcast(String PlayerName, String ReceivedText)
{
    `Log(Self$":: The Server sent me '"$ReceivedText$"' from "$PlayerName$".");
    MySFHud.UpdateChatLog(PlayerName @ ": " @ ReceivedText);
}

키보드 명령(Enter키 입력)을 통한 채팅

이 단계에서는 Enter 키를 채팅 시작 키는 물론 채팅 메시지를 전송(완료)하는 데도 사용하겠습니다. 물론 원하는 대로 다른 키를 사용해도 됩니다.

키 바인딩 추가

DefaultInput.ini 를 열고 다음 줄을 추가합니다:

.Bindings=(Name="Enter",Command="ChatHandler")

ALERT! : 눌린 키가 채팅에 쓰일 수 있도록 하려면, 다음 줄을 주석 처리하거나 지워 줘야 합니다:

.Bindings=(Name="Enter",Command="GBA_Use")

HUDWrapper 클래스 셋업

HUDWrapper 를 엽니다. HUD 의 인스턴스를 만드는 클래스인데요. 키가 눌리면 실행시킬 함수를 추가해 줍니다:

YourHUDWrapper.uc
exec function ChatHandler()
{
  HudMovie.ToggleChat(); // HudMovie 를 HUD 무비에 대한 리퍼런스로 대체합니다.
}

HUD 클래스 셋업

HUD 클래스를 엽니다.

먼저 선택된 키가 절대 HUD 무비의 입력으로 캡처되지는 않는지 확인해야 합니다. 그 작업은 포커스 무시 키 목록에 추가시키는 식으로 합니다. Start()/Init() 함수에 이 줄을 추가합니다:

AddFocusIgnoreKey('Enter');

다음, 키보드 명령을 통해 채팅에 들어가는 함수를 추가합니다. 이 함수는 HUDWrapper 에 의해 호출됩니다:

function ToggleChat()
{
  if (!bChatting)
  {
    bCaptureInput = true;
    OnChat();
  }
  else
  {
    bCaptureInput = false;
    OnChatSend();
  }
}

다음, OnChat() 와 OnChatSend() 함수 파라미터가 옵션이 될 수 있도록 변경합니다:

function OnChat(optional GFxClikWidget.EventData ev)
function OnChatSend(optional GFxClikWidget.EventData ev)

이제 OnChat() 함수에 다음 코드 줄을 추가합니다:

MyChatInput.SetBool("focused", true);

마지막으로 OnChatSend() 함수에 다음 코드 줄을 변경합니다:

MyChatLog.SetBool("focused", true);

스크립트를 다시 컴파일하고, HUD 를 테스트합니다.

내려받기