사람들에게 도움이 되는 프로그램의 가장 중요한 미덕(?)은 '접근성'인 것 같고, 그 관점에서 보면 웹 기반으로 만드는 것이 정답인 것 같습니다. 몇 번 시도(?) 했다가 결과까지 가지는 못했던 것인데 또 한번 사부작 시도 해 보겠습니다.
이 내용은 Unity3D 문서에도 있는데, 한번 따라가 보도록 하죠. 인터넷 검색을 하니 2021버젼으로 검색이 되었는데 최신 버젼의 문서도 있네요.
https://docs.unity3d.com/kr/2023.2/Manual/webgl-interactingwithbrowserscripting.html
겸사겸사, 이럴 때마다 Editor도 한번씩 업그레이드 해주면 좋은 것 같네요. WebGL support는 꼭 포함시켜야겠네요.
또 이런 공부 할 때는, 동기부여가 되는 샘플을 가지고 하면 더 잘되죠.
설치가 되는 동안, Asset Store에서 이것저것 좀 살펴볼까요.
Tanks로 검색을 했더니, 이것이 딱 보이네요. 재밌어 보이는데, Tutorial이군요. 나중에 Tutorial도 한번 살펴보도록 하죠. Add to My Assets~!!
https://assetstore.unity.com/packages/essentials/tutorial-projects/tanks-tutorial-46209
자, 설치는 다 되었고, 프로젝트를 생성합니다.
프로젝트 템플릿은....???
랜더링 모드가 혹시 문제가 되지 않을까 싶어 한번 살펴보니, URP로 해야되겠네요.
프로젝트 템플릿도 받고~
프로젝트를 만들고, Tanks Tutorial부터 받아보겠습니다.
Windows/ Package Manager로 가서 내 에셋에서 찾아 받습니다.
아... 미리 프로젝트를 만들어 놓을 필요가 없었군요.import!
이런 것도...
자, 이어서 가져오겠습니다.
import 후, Complete_Game이라는 Scene을 열고 실행하면~
요렇게 귀엽게 나옵니다. ㅋㅋ. 배경 음악도 아주 신납니다.
이제 저 탱크를 써서 테스트를 해보죠.
원래있던 빈 Scene에 import 된 에셋 중, 배경과 탱크를 Scene에 추가합니다.
처음에 배경을 추가하면 너무 눈부시게 되어 있는데, Directional light의 intensity를 0으로 설정하면 됩니다.
실행을 하면 키보드WASD로 탱크를 움직일 수 있습니다.
여기까지는 Javascript 사용하는 것과 아무런 관련이 없어요.ㅋ
그냥 허공에 Cube 하나 띄워놔도 됩니다.
Unity 스트립트에서 JavaScript 함수 호출
이제 Unity 기술문서를 좀 볼까요??
무엇인고 하니~~~
Javascript로 된 함수를 Unity 스크립트에서 호출한다는 말인데, 이게 브라우져에 있는, 즉, Unity 외부에 있는 Javascript를 실행한다는 뜻은 아닙니다.
사실, 하고 싶은 것이 브라우져에 있는 함수와 유니티 내부의 함수가 서로 호출 할 수 있게 되길 바라는 것이라, 처음에는 저 문장이 제대로 보여지지 않았습니다. 그래도 이런 것을 배우면서 점진적으로 연동하는 과정으로 가는 것이니 이것도 중요하죠. 어쨌든, C#과 Javascript가 연동된다는 점 자체로, 꽤 재미(?)있기도 합니다.
jslib
Unity 프로젝트 내부에 있는 Javascript는 jslib라는 확장자를 가져야 하고, 형식은 아래와 같이 좀 특이한 형식을 취합니다. 다른 샘플 프로젝트에 있는 jslib를 보고 공부 해 보라는데...뭐야....제대로 가르쳐줘야지..
가이드 문서에 있는 샘플 코드는 아주 다양한 인자의 함수들이 포함되어 있어서, 분명 좋은 샘플인 것 같습니다.
요건 그냥 가이드 문서 내용대로 한번 해보겠습니다.
Assets 폴더 아래에 Plugins라는 폴더를 만듭니다.
그리고, 그 속에 *.jslib 파일을 하나 만듭니다.(저는 TankController.jslib라고 만들었습니다.). 이 파일은 Unity Editor에서 만들 수는 없는 것 같아 밖에서 만들었습니다.
이 파일을 편집기에서 열어, 아래 코드를 입력하고 저장합니다. 아래 코드 내용을 살펴보면 간단한 내용이며, 다양한 형태로 인자를 전달하기 위해서 여러가지 함수를 만든 것을 알 수 있습니다. 여기서 눈 여겨 볼 것은, 이 함수들이 Javascript로 만들어진 함수라는 것입니다. 브라우져의 HTML코드에 있는 Javascript가 아니란거죠.!!! Android library를 Unity에서 호출하듯, Javascript로 된 함수를 Unity가 호출 할 수 있게 해준다는 의미가 있겠습니다.
여기서 한 가지 흥미로운 점은, Hello 함수에서 window.alert를 호출한다는 것입니다. 이 window 객체는 브라우져의 객체이죠. 이걸 보면 뭔가 연결의 실마리가 전혀 없지는 않겠다는 희망(?)을 가질 수 있습니다.
mergeInto(LibraryManager.library, {
Hello: function () {
window.alert("Hello, world!");
},
HelloString: function (str) {
window.alert(UTF8ToString(str));
},
PrintFloatArray: function (array, size) {
for(var i = 0; i < size; i++)
console.log(HEAPF32[(array >> 2) + i]);
},
AddNumbers: function (x, y) {
return x + y;
},
StringReturnValueFunction: function () {
var returnStr = "bla";
var bufferSize = lengthBytesUTF8(returnStr) + 1;
var buffer = _malloc(bufferSize);
stringToUTF8(returnStr, buffer, bufferSize);
return buffer;
},
BindWebGLTexture: function (texture) {
GLctx.bindTexture(GLctx.TEXTURE_2D, GL.textures[texture]);
},
});
저장 후 에디터에서 해당 파일을 선택하면, inspector에 뭐가 설정 되는 것을 볼 수 있습니다. 일단, 우리는 WebGL에서 볼 것이니 그대로 저장하고 둡니다.
자, 이제 저 Javascript 함수를 호출할 코드를 탱크에 추가 해 보겠습니다.
Tank에는 아래와 같이 세 개의 스크립트 파일이 있습니다. 이 중, 탱크가 발사를 하면, Hello 함수를 호출하도록 하겠습니다.
Javascript코드, 즉, jslib 파일에 정의 된 함수를 호출하려면
using System.Runtime.InteropServices;
[DllImport("__Internal")]
요 두 가지를 반영해야 합니다.
발사하는 스크립트에 한번 반영 해 보겠습니다.
발사 스크립트 파일 상단에 요렇게 반영합니다. Hello 보다는 '쾅!' 팝업을 띄워보면 좋을 것 같아서, 팝업 띄울 문자열을 전달받는 HelloString 함수도 추가 해보았습니다.
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;
namespace Complete
{
public class TankShooting : MonoBehaviour
{
[DllImport("__Internal")]
private static extern void Hello();
[DllImport("__Internal")]
private static extern void HelloString(string str);
public int m_PlayerNumber = 1; // Used to identify the different players.
public Rigidbody m_Shell; // Prefab of the shell.
public Transform m_FireTransform; // A child of the tank where the shells are spawned.
public Slider m_AimSlider; // A child of the tank that displays the current launch force.
public AudioSource m_ShootingAudio; // Reference to the audio source used to play the shooting audio. NB: different to the movement audio source.
public AudioClip m_ChargingClip; // Audio that plays when each shot is charging up.
public AudioClip m_FireClip; // Audio that plays when each shot is fired.
public float m_MinLaunchForce = 15f; // The force given to the shell if the fire button is not held.
public float m_MaxLaunchForce = 30f; // The force given to the shell if the fire button is held for the max charge time.
public float m_MaxChargeTime = 0.75f; // How long the shell can charge for before it is fired at max force.
그 후, 원래 있던 Fire 함수의 가장 끝에, HelloString 함수 호출을 추가했습니다.
private void Fire ()
{
// Set the fired flag so only Fire is only called once.
m_Fired = true;
// Create an instance of the shell and store a reference to it's rigidbody.
Rigidbody shellInstance =
Instantiate (m_Shell, m_FireTransform.position, m_FireTransform.rotation) as Rigidbody;
// Set the shell's velocity to the launch force in the fire position's forward direction.
shellInstance.velocity = m_CurrentLaunchForce * m_FireTransform.forward;
// Change the clip to the firing clip and play it.
m_ShootingAudio.clip = m_FireClip;
m_ShootingAudio.Play ();
// Reset the launch force. This is a precaution in case of missing button events.
m_CurrentLaunchForce = m_MinLaunchForce;
HelloString("Pang");
}
이제, 실행 해 보겠습니다.
File/ Build Setting으로 가서 WebGL 빌드로 설정을 합니다. 이때 Scene이 혹시 Complete Scene으로 되어 있다면 변경도 해줘야 하구요. 얼마전까지는 WebGL로 변경하면 텍스쳐 관련 설정 오류가 꼭 났었는데 수정이 되었나보네요. 따로 웹서버 돌리고 있는 것이 있다면, Build해서 그 서버에서 확인하면 되고, 따로 서버가 없으면 Build And Run을 하면 Unity에 내장 된 Nodejs 서버로 실행 시켜 줍니다.
결과는 요렇게 뜨고, 스페이스 키 눌러서 실행하면, 기대했던 alert 창도 잘 뜹니다.
어찌되었든, Unity 내부의 스크립트로 브라우져의 무엇인가를 제어한 것이라 고무적이죠. window 객체 뿐만 아니라 document 객체도 접근 할 수 있다면 할 수 있는 것이 훨씬 많아지겠네요.
일단 첫번째 예는 Unity 에서 내부의 Javascript 코드를 실행하는 예였고, 이 예가 실행되는 환경이 브라우져인 경우, window 객체에 접근 가능하다는 것을 확인하였습니다. 다른 객체도 접근 가능하지 않을까 싶으니 차차 확인 해 보기로 하고, 가이드 분서를 좀 더 살펴보도록 하겠습니다.
https://github.com/red112/unity_javascript
'공허의 유산 > 사상의 도구' 카테고리의 다른 글
[Unity3D/WebGL] 브라우저 스크립팅과 상호 작용(3) (0) | 2023.10.09 |
---|---|
[Unity3D/WebGL] 브라우저 스크립팅과 상호 작용(2) (1) | 2023.10.07 |
DCInside 고갤 조회수 높은 글의 제목 분석 (0) | 2023.09.20 |
민관협력지원플랫폼을 통한 Naver Cloud Platform 입문 (1) | 2023.09.09 |
DC Inside 고민 갤러리 데이터 수집 - 목록 (2) | 2023.09.01 |
댓글