항상 무료 플랜만 찾아다니며 사용했는데 그러다 보니 제약도 많고 내가 원하는 것들을 써보지도 못하고 끝나는 경우가 많았다.

 

그래서 테스트나 간단하게 사용하기 위한 용도로 저렴한 서버를 찾다가 NHN에 적당한 가격을 찾게 되어 사용해 보기로 한다.

 

 

서버의 사양은 가격만큼 낮지만 간단하게 개발용으로 쓰면서 공부하기에는 부족하지 않을 것이라고 생각된다.

 

일단 큰 금액이 아니기 때문에 즉시 결제하고 바로 활용해 보기로 한다.

 

 

웹 환경은 php가 필요하기 때문에 선택한다. 그에 필요한 Apache도 함께 설치된다.

 

 

접근 포트를 미리 선택해 놓으면 기본 보안 그룹 설정이 반영된다고 하는데 리눅스 터미널은 무조건 필요하지 않을까 싶어서 선택해 주었고 FTP 포트는 쓰긴 할 것 같아서 선택했다.

 

이 부분은 나중에 보안그룹에서 변경이나 추가해서 설정이 가능하다고 하니 일단 이렇게 진행하기로 한다.

 

이후로 FTP 정보, DB 정보를 입력하고 혹시 모르니 따로 메모해 둔다.

 

 

마지막으로 키페어(서버 접속 인증 키)에 대한 안내가 나오는데 이게 있어야 서버에 SSH 연결을 할  수 있고 보안을 위해서 신청 시 잘 보관하지 않았다가 이걸 잃어버리면 서버에 연결할 수 없기 때문에 주의해야 한다.

 

기존 키페어가 없으니 적당한 이름을 넣어주고 새로 만들어 생성된 키를 다운로드하여서 잘 보관하도록 한다.

 

 

 

신청하고 나면 5분 이내로 서버가 생성되고 클라우드 호스팅 콘솔 페이지에서 서버의 ip나 사용량 등 세부적인 사항들을 확인할 수 있다.

 

윈도우 서버를 사용해 본 경험이 있긴 하지만 그건 이미 세팅이 완료된 상태에서 원격으로 접속한 것뿐이었다.

이렇게 서버를 열어본 게 처음이고 거기다 리눅스를 사용해 본 적도 없기 때문에 앞으로 서버를 사용하면서 다양하고 새로운 정보와 문제들과 마주할 것으로 생각되는데 나중에 이 정보들이 다시 필요한 상황이 왔을 때 참고가 되도록 자세하게 잘 정리해 보도록 해야겠다.

728x90
반응형

'Develop > Server' 카테고리의 다른 글

리눅스 명령어 - ls  (0) 2025.03.01
[NHN Cloud Hosting - Linux] php 테스트  (1) 2025.03.01
[NHN Cloud Hosting - Linux] mysql 테스트  (0) 2025.03.01
[NHN Cloud Hosting - Linux] SSH로 서버 접속  (0) 2025.03.01
SSH와 RDP  (0) 2025.03.01

버전 : Unity 6

 

구글 계정에 연동과정

 

Google Sign In SDK에서 ID 토큰, 액세스 토큰을 받는다.

 

Firebase Authentication으로 Google ID 토큰을 Firebase로 전달하고 이를 인증한다.

 

Google Sign In SDK는 구글 계정으로 로그인할 수 있지만 이후 로그인한 사용자를 앱의 인증 시스템에서 관리할 방법이 없다.

 

또한 Google ID 토큰을 앱에서 직접 검증하는 것은 보안상 위험하기 때문에 파이어베이스를 통해서 토큰을 검증하고 관리하여 안전하게 관리할 수 있고 파이어베이스의 다양한 기능과 연계하여 사용할 수도 있다.

 

1. 파이어베이스 인증 SDK 설치

Firebase Authentication SDK

 

Google 로그인과 Unity를 사용하여 인증하기  |  Firebase

의견 보내기 Google 로그인과 Unity를 사용하여 인증하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Google 로그인을 앱에 통합하여 사용자가 Google 계정으로

firebase.google.com

 

Firebase Authentication

 

다운로드한 압축 파일에서 FirebaseAuth.unitypackage 패키지를 프로젝트에 임포트

 

FirebaseAuth

 

2. Google-Signin-Unity

Google-SignIn-Unity

 

GitHub - googlesamples/google-signin-unity: Google Sign-In API plugin for Unity game engine. Works with Android and iOS.

Google Sign-In API plugin for Unity game engine. Works with Android and iOS. - googlesamples/google-signin-unity

github.com

 

최신버전 1.0.4 사용

 

* 프로젝트에 임포트하면 Unity.Task 관련해서 충돌 에러가 발생하는데 Assets > Parse  폴더를 지우면 해결 가능하다.

 

설치 후 패키지 문제 없는지 테스트 빌드를 진행

 

gradle 에러가 발생해서 빌드에 실패한다. 안드로이드 빌드 시 자주 발생하는 에러로 이런 경우 프로젝트 세팅의 최소 타겟 API를 올리면 해결되는 경우가 많은데 먼저 이 부분을 확인해서 다시 빌드해 본다.

 

Minimum API Level 23 -> 24로 변경 후 다시 빌드하니 해결되었다.

 

3. Key Store 생성

파이어베이스에서 인증 정보를 저장하고 관리할 프로젝트를 생성해야 하는데 이때 유니티 프로젝트의 SHA 키가 필요하다.

 

먼저 유니티에서 키스토어를 생성하고 SHA를 확인해 둔다.

 

1. 키스토어 생성

 

 

2. SHA 확인

키스토어를 열어보기 위해서는 keytool을 사용해야 하는데 유니티 에디터를 설치하면 포함되어 있기 때문에 에디터 설치 경로에서 

keytool.exe 파일이 위치한 경로에서 명령 프롬프터를 켜서 'keytool -list -keystore [키스토어 경로]' 를 실행한다.

 

 


* 구글 계정 인증에는 SHA-1 이 필요한데 Unity 6 버전의 keytool을 사용했더니 256만 뜨고 나머지 지문들은 생략된다.

   다른 에디터 버전의 keytool을 사용해서 SHA-1을 확인하고 메모해 둔다.

 

해당 키는 잠시 메모해 둔다.

 

4. 파이어베이스 프로젝트 세팅

Firebase

 

Firebase | Google's Mobile and Web App Development Platform

개발자가 사용자가 좋아할 만한 앱과 게임을 빌드하도록 지원하는 Google의 모바일 및 웹 앱 개발 플랫폼인 Firebase에 대해 알아보세요.

firebase.google.com

 

로그인 인증을 처리할 프로젝트를 생성한다.

 

 

유니티 플랫폼을 선택해서 앱을 추가한다.

 

 

여기서 디지털 지문 추가에서 키스토어의 SHA 키를 입력한다.

 

Authentication 항목으로 들어가서 로그인 제공업체를 추가한다.

 

 

Google을 선택하고 사용설정을 해준다.

 

5. 클라이언트 ID 확인

Google Cloud

 

Google 클라우드 플랫폼

로그인 Google 클라우드 플랫폼으로 이동

accounts.google.com

 

구글 클라우드에 접속하면 파이어베이스에서 생성했던 프로젝트와 동일한 정보로 프로젝트가 생성되어 있다.

 

이 중에서 사용자 인증 정보 항목에서 OAuth 2.0 클라이언트 ID를 사용해서 유니티에서 접속을 시도한다.

 

 

6. 로그인 스크립트

유니티로 돌아가서 로그인 스크립트를 구현한다.

 

* 에러

SignIn 함수 호출 시 계정 선택 UI 팝업이 뜬 후 계정을 선택하고 나서 반응이 없는 현상이 있었는데 결과를 받아서 처리하는 콜백에서 에러가 발생했었다.

 

이때 메인스레드에서 처리되도록 Dispatcher 함수를  구현해서 처리하니 문제가 해결되긴 했는데 정확한 원인은 확인을 못한 부분이다.

 

using System.Collections.Generic;
using UnityEngine;

public class MainThreadDispatcher : MonoBehaviour
{
    private static MainThreadDispatcher instance;
    private readonly Queue<System.Action> executionQueue = new Queue<System.Action>();

    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    private void Update()
    {
        lock (executionQueue)
        {
            while (executionQueue.Count > 0)
            {
                executionQueue.Dequeue()?.Invoke();
            }
        }
    }

    public static void RunOnMainThread(System.Action action)
    {
        if (instance != null)
        {
            lock (instance.executionQueue)
            {
                instance.executionQueue.Enqueue(action);
            }
        }
    }
}

 

 

디스패처를 사용해 SignIn 함수 결과를 처리한다.

 

using Google;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;

public class GoogleLogin : MonoBehaviour
{
    private string web_client_id = "구글 클라우드의 클라이언트 ID";

    private void Awake()
    {
        Init();
    }

    private void Init()
    {
        GoogleSignIn.Configuration = new GoogleSignInConfiguration
        {
            WebClientId = web_client_id,
            UseGameSignIn = false,
            RequestEmail = true,
            RequestIdToken = true
        };
    }

    public void SignIn()
    {
        DebugMessage.Instance.ShowMessage("Calling SignIn");
        Debug.Log("Calling SignIn");
        GoogleSignIn.DefaultInstance.SignIn().ContinueWith(
          OnAuthenticationFinished);
    }

    internal void OnAuthenticationFinished(Task<GoogleSignInUser> task)
    {
        Debug.Log("Authentication finished, processing on main thread");
        MainThreadDispatcher.RunOnMainThread(() => ProcessAuthResult(task));
    }

    private void ProcessAuthResult(Task<GoogleSignInUser> task)
    {
        Debug.Log("Auth Result");
        if (task.IsFaulted)
        {
            using (IEnumerator<System.Exception> enumerator = task.Exception.InnerExceptions.GetEnumerator())
            {
                if (enumerator.MoveNext())
                {
                    GoogleSignIn.SignInException error = (GoogleSignIn.SignInException)enumerator.Current;
                    DebugMessage.Instance.ShowMessage("Got Error: " + error.Status + " " + error.Message);
                    Debug.Log("Got Error: " + error.Status + " " + error.Message);
                }
                else
                {
                    DebugMessage.Instance.ShowMessage("Got Unexpected Exception?!?" + task.Exception);
                    Debug.Log("Got Unexpected Exception?!?" + task.Exception);
                }
            }
        }
        else if (task.IsCanceled)
        {
            DebugMessage.Instance.ShowMessage("Canceled");
            Debug.Log("Canceled");
        }
        else
        {
            DebugMessage.Instance.ShowMessage("Welcome: " + task.Result.DisplayName + "!");
            DebugMessage.Instance.ShowMessage(task.Result.Email + "!");
            DebugMessage.Instance.ShowMessage(task.Result.IdToken + "!");

            Debug.Log("Welcome: " + task.Result.DisplayName + "!");
            Debug.Log(task.Result.Email + "!");
            Debug.Log(task.Result.IdToken + "!");
        }
    }
}

 

 

폰트에 한글이 지원되지 않아서 깨진 것 빼고는 로그인 성공 후 들어오는 리턴 정보를 로그로 찍은 값들이 잘 출력되는 게 확인된다.

 

 

728x90
반응형

'Develop > Unity' 카테고리의 다른 글

InputSystem 기본 사용법  (0) 2025.03.25
유니티 기본 물리 샘플  (0) 2025.03.21
2D 애니메이션, 이펙트  (1) 2024.12.03
Input System 사용시 UI 상호작용 안될때  (0) 2024.11.18
유니티 프로젝트 창 검색 활용  (1) 2024.06.30

최근에 UI 애니메이션을 작업하다 정리가 필요한 부분이 있어서 작성한다.

 

2D Sprite

2D 스프라이트의 애니메이션은 리소스와 Animator를 가지고 만들 수 있다.

Sprite Renderer Animation

 

원하는 프레임마다 스프라이트를 변경하는 방식으로 애니메이션을 만들 수 있다.

 

UI Animation

UI 경우에도 애니메이션으로 컨트롤하는 경우에는 동일한 방식으로 처리된다.

UI Animation

 

Effect

Sprite Renderer를 사용하는 상황에서 뭔가 발산하는 이펙트를 사용한다면 어떻게 하는 게 좋을까 생각하면서 파티클 시스템과 오브젝트를 직접 제어하는 방법 두 가지를 사용해 보았다.

 

 

있는 리소소 가지고 대충 테스트만 하려고 만들다 보니 별로 이뻐 보이진 않는다.

 

이러한 상황에서는 오브젝트를 가지고 직접 제어하는 게 나은 방식인 거 같다.

 

 

실제로 사용한다면 풀링을 해서 쓰겠지만 그럼에도 상당히 많은 오브젝트를 뿜어낸다면 파티클을 쓰는 게 적합하다고 보인다.

 

상황에 맞게 잘 조율하는 게 필요하다.

 

위에서 사용한 코드

 

using UnityEngine;

public class Coin : MonoBehaviour
{
    private const float power = 10f;
    private void OnEnable()
    {
        transform.position = Vector3.zero;
        ApplyForce();
    }

    private void ApplyForce()
    {
        var rb = GetComponent<Rigidbody2D>();
        float randomHorizontal = Random.Range(-1f, 1f); // -1 to 1 for left/right
        Vector2 direction = new Vector2(randomHorizontal, 1f).normalized;
        rb.AddForce(direction * power, ForceMode2D.Impulse);
    }
}

using UnityEngine;

public class Coin : MonoBehaviour
{
    private const float power = 10f;
    private void OnEnable()
    {
        transform.position = Vector3.zero;
        ApplyForce();
    }

    private void ApplyForce()
    {
        var rb = GetComponent<Rigidbody2D>();
        float randomHorizontal = Random.Range(-1f, 1f); // -1 to 1 for left/right
        Vector2 direction = new Vector2(randomHorizontal, 1f).normalized;
        rb.AddForce(direction * power, ForceMode2D.Impulse);
    }
}

 

대충 동전이 뿜어지는 듯한 모습을 중점으로 만들었다.

 

Coin 간에는 충돌처리하면 초기 한 위치에 모여있을 때 서로 부딪혀서 Physics2D > Layer Collision Matrix를 꺼두었다.

 

바닥에 충돌 후 튕기는 것과 미끄러지는 정도는 Phsics Material로 조절한다 (Friction 마찰력, Bounciness 탄성력)

 

UI Effect

위 내용들은 겸사겸사로 같이 정리한 내용이고 이 글을 쓰기 시작한 이유는 이 부분 때문이었다.

 

상황은 대충 이렇다.

 

간단한 퍼즐 게임을 만드는 중에 스프라이트 렌더러를 쓰기에는 귀찮은 부분들이 있어서 간단하게 만들려고 UI를 베이스로 해서 게임 로직들을 만들었고 그렇게 진행하다 보니 효과를 추가하는 과정에서 물리적인 부분을 사용할 수 없어 직접 위치를 이동시켜서 유사하게 재현할 수밖에 없었다.

 

UI Animation

 

using UnityEngine;

public class UICoinMaster : MonoBehaviour
{
    [SerializeField] UICoin[] uiCoins;

    bool isOn = false;
    public void OnClick_UICoinMaster()
    {
        if (isOn)
        {
            foreach( var coin in uiCoins)
            {
                coin.gameObject.SetActive(false);
            }
            isOn = false;
        }
        else
        {
            foreach (var coin in uiCoins)
            {
                coin.gameObject.SetActive(true);
            }
            isOn = true;
        }
    }
}


using UnityEngine;

public class UICoin : MonoBehaviour
{
    [SerializeField] private float initialForce = 10f;
    [SerializeField] private float gravity = 9.8f;
    [SerializeField] private float bounceForce = 0.5f;
    [SerializeField] private bool isMoving = false;

    private RectTransform rect;
    private Vector2 velocity;
    private Vector2 originPos;
    private void Awake()
    {
        rect = GetComponent<RectTransform>();
        originPos = rect.position;
    }

    private void OnEnable()
    {
        ApplyPower();
    }

    private void OnDisable()
    {
        rect.position = originPos;
    }

    private void ApplyPower()
    {
        float randomX = Random.Range(-1f, 1f);
        velocity = new Vector2(randomX, 1f).normalized * initialForce;
        isMoving = true;
    }

    private void Update()
    {
        if (!isMoving) return;

        velocity.y -= gravity * Time.deltaTime;

        rect.anchoredPosition += velocity * Time.deltaTime;

        if (rect.anchoredPosition.y < 0)
        {
            rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, 0);
            velocity.y = -velocity.y * bounceForce;
            velocity.x *= 0.8f;
            
            if (Mathf.Abs(velocity.y) < 0.1f)
            {
                isMoving = false;
            }
        }
    }
}

 

UI 크기에 맞춰서 값들을 적절하게 세팅하면 그럴듯해 보인다. 구현하는 데는 크게 무리가 없지만 UI 가지고 이래도 되나 싶은 생각이 들기도 한다.

 

개인적으로는 필요한 기능만 직접 구현해서 쓰는 걸 선호하는 편이라 잘 쓰진 않지만 위처럼 UI를 제어하는 데는 DoTween을 사용하는 게 더 간단하고 다양한 동작들도 처리할 수 있을 것이다.

 

UI Particle System

한 번쯤은 'UI위에 파티클 뿌리기'에 대해서 많은 고민과 탐구를 해보았을 것이다. 이 경우 나는 주로 카메라의 렌더링 모드를 Screen Space - Camera로 세팅해서 파티클을 보이게 하는 방법을 사용했다. 그런데 이 방법은 원하는 파티클을 사용할 때나 좌표계를 다룰 때 은근히 귀찮고 까로운면이 있었다.

 

그래서 이번에 좀 더 찾다 보니 좋은 방법을 알게 되었다.

 

https://github.com/Unity-UI-Extensions/com.unity.uiextensions.git

 

GitHub - Unity-UI-Extensions/com.unity.uiextensions

Contribute to Unity-UI-Extensions/com.unity.uiextensions development by creating an account on GitHub.

github.com

 

 

UI Extensions 라이브러리로 여기에서 UIParticle System을 사용하면 파티클을 UI 위에 렌더링 할 수 있는 상태로 만들 수 있다.

 

해당 라이브러리에 대해서는 알고는 있었는데 파티클 관련 기능이 있었다는 건 이번에 알게 되었다.

 

이와 관련해서 UIParticle System 사용방법과 파티클의 기본 사용방법을 배우기 좋은 영상을 메모해 둔다.

 

https://www.youtube.com/watch?v=hiRdux33UCs

 

파티클을 조금 참고해서 만들어 적용시켜 본다.

 

효과를 주고 싶은 UI의 자식에 파티클을 할당하면 UI와 동일한 렌더링 우선순위로 처리가 된다는 점에서 원하는 기능 그 자체였다.

 

 

Performance

겸사겸사로 추가된 내용들이 많지만 결국 UI로 동작들을 구현해 버리면 성능상에 좋지 않은 건 사실이고 권장되는 방식도 아니다.

가장 큰 이유는 UI는 변경될 때마다 캔버스가 리빌드를 돌리기 때문에 이러한 동작이 과도하게 발생되며 이 연산은 CPU에서 처리하기 때문에 신경이 안 쓰일 수 없지만 어느 정도 타협해서 사용한다면 괜찮지 않을까 생각도 든다.

 

UI로 만들어봤자 엄청나게 복잡한 게임도 아닐 것이고 퍼즐 게임 정도면 성능상에 이슈를 발생시킬 만큼은 아닐 것이라고 감히 예상한다.

 

정말 괜찮은지는 프로파일링을 해봐야겠지만 궁금하기도 하니 나중에 시간 날 때 게임 오브젝트와 UI로 구현한 것을 각각 최대한 비슷하게 만들어 놓고 성능을 한 번 비교해 보는 것이 괜찮을 것 같다.

 

728x90
반응형

+ Recent posts