본문 바로가기
언리얼 엔진/Project

구글 설문 응답을 언리얼 그래픽에 실시간 연동하기 (Web API, VaRest)

by z03y 2025. 4. 10.

🗳️ 전체 프로젝트 소개

메인 과제는 구글 설문지 투표에 기반한 데이터를 언리얼로 가져와 사전 작업된 그래픽에 적용하는 것이다. '최고의 라면을 찾는 이벤트 쇼' 라는 컨셉으로 씬을 구성하여 추가적인 기능들을 함께 구현해보았다.

언리얼 기능 리스트

  • Appscript API 데이터 연동하여 변수로 저장
  • 투표 값 텍스트 표출
  • 투표 값에 기반한 막대 그래프 애니메이션
  • 투표 값의 % 표출
  • % 값 출력 전 랜덤으로 돌아가는 숫자 애니메이션
  • 레벨 시퀀스 연동
  • 최고 값이 1개일 경우 '우세' 뱃지 머티리얼 표출
  • 최고 값이 2개 이상일 경우 '박빙' 뱃지 머티리얼 표출
  • 전체 내용 초기화 이벤트

 


 

🗳️ Google Form + Google Sheets 연결

웹에서 클릭만으로 투표를 할 수 있게 하고 그 결과가 Google Sheets에 자동 저장되도록 한다.

먼저 Google Form으로 새 질문지를 만들어 질문과 객관식 답변을 구성한다. 완성되었다면 중앙 상단의 응답 탭 > Sheets에 연결을 클릭하여 새 스프레드시트를 만들거나 기존 스프레드 시트와 연결한다.

 

시트를 열면 보라색의 '응답' 탭이 추가되어 응답 결과들이 쌓인 것을 볼 수 있다. 그리고 이 데이터의 결과를 정리하는 투표 집계용 시트를 만든다. 아래의 Sheet1이다. 한글은 언리얼에서 오류가 있을 수 있어 영문으로 바꿔준다. 투표 수에는 함수를 입력한다.

=COUNTIF(응답!B:B, "라면 이름")

 

 

🗳️ Apps Script 웹앱으로 배포

스프레드시트가 준비되었다면 상단 확장 프로그램 탭에서 Apps Script를 클릭한다.

 

아래 코드를 붙여넣는다. 이 코드는 Sheet1의 데이터를 읽고, A열의 값 = key, B열의 값 = value로 구성된 JSON 객체를 만들어서 외부에서 HTTP GET 요청으로 호출할 수 있는 API를 만들어 준다. 이 때 주의할 점으로 2번째 줄의 "Sheet1"은 투표 집계용 시트 이름과 한/영문 관계없이 정확히 일치해야 한다.

function doGet(e) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheet1");
  const data = sheet.getDataRange().getValues();


  const results = {};
  for (let i = 1; i < data.length; i++) {
    results[data[i][0]] = data[i][1];
  }


  return ContentService
    .createTextOutput(JSON.stringify(results))
    .setMimeType(ContentService.MimeType.JSON);
}

 

코드를 붙여넣고 배포를 누르면 나오는 창이다. 액세스 권한이 있는 사용자를 '모든 사용자'로 변경하고 배포한다. 오류 발생 시 버전 관리를 위해 설명에는 버전을 입력하면 좋다.

 

배포 후 나오는 URL을 복사한다. 이제 언리얼에서 이 주소를 읽는 블루프린트를 만들면 된다.
그런데 이 과정에서, 이런 메세지가 뜰 수도 있는데 정상이다.

Google hasn’t verified this app The app is requesting access to sensitive info in your Google Account. Until the developer (sujinhw22@gmail.com) verifies this app with Google, you shouldn't use it.Google hasn’t verified this app The app is requesting access to sensitive info in your Google Account. Until the developer (sujinhw22@gmail.com) verifies this app with Google, you shouldn't use it...
 
Apps Script로 만든 웹앱을 처음 배포할 때, 구글이 자동으로 검증되지 않은 앱 경고를 보여주게 된다. 우리가 만든 내용은 공개 API용으로만 사용할 것이기 때문에 민감한 정보에 접근하지 않으므로 "계속"을 눌러 해결한다. (한 번만 해주면 된다)

 

🗳️ 언리얼에서 Google Sheets API 불러오기

VaRest블루프린트를 기반으로 HTTP/JSON 통신을 간편하게 구현할 수 있게 도와주는 플러그인이다. 프로젝트에 VaRest를 설치하고 필요시 재시작을 한다.

 

VaRest Subsystem >  Construct Json Request > Set URL 순서대로 노드를 생성한다. Verb는 Get으로, URL에는 Apps script로 배포한 URL을 붙여넣는다.
여기서 Construct Json Request 노드는 REST API 호출을 구성하기 위한 시작점으로 요청(Request) 객체를 만드는 노드라고 볼 수 있다. Verb는 요청 방식(HTTP Method)으로 데이터를 가져오려면 Get, 새 데이터를 보내려면 Post, 데이터를 덮어쓰려면 Put, 데이터를 삭제하려면 Delete를 사용한다.

 

Bind Event to On Request Complete 노드를 추가한다. 앞에서 데이터 요청이 끝나고 서버로 부터 응답을 받았을 때 내가 원하는 처리를 할 수 있게 하는 이벤트 연결이다. Bind Event to On Request Complete 다음으로 연결되는 Execute Process Request는 전체 HTTP 요청을 시작(실행)하는 트리거임으로 반드시 추가한다. 

 

서버로부터 응답을 받았을 때 이벤트이다. Get Response Object 노드로 서버로 부터 온 응답을 Json 객체로 꺼내준다. 이후 Get String Field, Get Number Field, Get Bool Field, Get Object Field 등으로 원하는 값만 꺼낼 수 있다. 최고의 라면쇼 같은 경우는 투표 '수' 데이터가 필요하기 때문에 Get Number Field를 사용한다. Field Name에는 A열(Key) 라면 이름을 넣어준다. 그러면 해당 라면의 B열(Value) 투표 값을 얻을 수 있다.

 

그대로 사용해도 되지만 효율적으로 관리하기 위해 변수로 저장한다. 그리고 서버로부터 응답을 요청하고 받을 때 몇 초의 시간이 필요하여 디버깅용 Print string 노드를 추가했다. 준비가 되었을 때 'Ready!!' 문자열을 출력하게 한다.

 

🗳️ 데이터 변수와 그래픽 연동하기

이제 시각적인 그래픽을 구성한다. 블루프린트 객체로 막대바 역할을 할 Cube, 표 수와 % Text render를 만들고

 

약간의 트랜지션이 들어간 라면 이미지 그래픽을 레벨 시퀀서로 만든다.

 

결과 이벤트를 실행하면 레벨 시퀀스를 플레이하고 0.7초 뒤 막대 그래프 애니메이션을 구동한다. 타임라인을 사용하기 때문에 동시에 시작될 수 있도록 Sequence 노드를 사용한다. 타임라인은 4 가지 라면 모두 동일하나 값이 크거나 작음에 따라 속도가 달라지는 것을 방지하기 위해 Set Timeline Length 노드로 값에 따라 타임라인의 길이를 런타임 중 동적으로 바꿔 준다.

 

이어서 Text 제어이다. 막대그래프를 실행하고 0.3초 뒤 아래에서 위로 살짝 올라오는 트랜지션을 가미한 텍스트(표 수)가 등장한다.

 

0.2초 뒤 표 수 위에 전체 표에서 차지하는 비율, %로 나타내는 텍스트 애니메이션 이벤트를 작동시키고 또 약간의 시간 1초 뒤 결과 값을 비교하여 '우세', '박빙' 뱃지 머티리얼을 변경하는 이벤트가 나오게 한다.

 

% 이벤트이다. Set Text로 값만 넣는 것이 아니라 Set Timer by Function Name 노드를 사용하여 랜덤한 수가 무작위 반복되다가 등장하는 연출을 추가했다. 이 부분은 이전 포스팅에서 다룬 내용을 활용했다.


0.001단위로 출력되는 float 데이터를 0.1 단위로 줄이는 Function도 추가되어 있다. To Text(float) 노드를 열어 아래와 같이 세팅해면 된다.

 

다음은 전체 결과 값을 비교하고 최대 값이 1개일 경우 '우세' 머티리얼로 변경하고 2개 이상일 경우 '박빙' 머티리얼로 변경하는 MatChange 이벤트이다.

 

변수가 4개여서 간단한 방식으로 구현했다. 전체 값 중 가장 큰 값을 각 단일 값과 비교하고 참일 때 '박빙 검사기'라는 Integer 변수에 1을 더한다. 마지막으로 Integer의 최종 값이 2와 크거나 같은지 검사하여 참일 경우 Set Material로 '박빙'을, 거짓일 경우 '우세'로 변경한다.

 

변경된 머티리얼이 적용된 Plane을 등장시킨다. '박빙', '우세' 뱃지는 꽝! 하고 찍히는 애니메이션이 있어야 느낌이 살 것 같아 타임라인도 추가했다.

 

 


 

🗳️ 결과

간단한 기능 구현만 실행하려고 했는데 하다보니 비주얼을 포기 못하게 된.. ChatGPT의 도움을 받아 캐릭터도 추가하고 후다닥 무대 디자인까지 해버렸다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형