내일배움캠프 67일차 TIL : UGS 적용, 스토브 빌드

woollim·2024년 12월 27일
0

내일배움캠프TIL

목록 보기
60/65
post-thumbnail

■ 개요

○ 오늘 계획

  • UGS
  • 스토브 빌드
  • 미로맵
  • 잡몹 애니메이션 점검하기
  • 버그잡기


■ UGS

○ 개요

  • Unity의 UGS(Unity Gaming Services)는 Unity가 제공하는 클라우드 기반의 게임 서비스 플랫폼
  • 이 서비스는 게임 개발자들에게 강력한 툴과 기능을 제공하여 멀티플레이어 게임, 분석, 운영, 수익화 등을 쉽게 구현할 수 있도록 도움
  • 참고문서

○ 주요 기능

  • Multiplayer Services
    멀티플레이어 서버를 설정하고 관리할 수 있는 기능.
    매치메이킹(Matchmaking)을 지원하여 플레이어를 연결.

  • Analytics
    플레이어 행동 데이터를 수집 및 분석하여 게임 디자인과 마케팅 전략을 최적화.

  • Economy & Monetization
    게임 내 경제 시스템 관리, 가상 상품 및 통화 구현.
    광고 및 인앱 구매를 통해 수익화 지원.

  • LiveOps
    게임의 라이브 상태를 실시간으로 관리.
    업데이트 배포 및 이벤트를 손쉽게 운영.

  • Cloud Save
    플레이어 데이터를 클라우드에 저장하여 크로스 플랫폼 저장 및 복구 지원.

  • Authentication
    플레이어 인증 및 로그인 서비스 제공.

  • 이 중 우리프로젝트에 쓰일 것은 Analytics


○ Analytics

Analytics 기능은 게임 개발자가 플레이어 데이터를 분석하여 게임 플레이 경험을 최적화하고, 의사 결정을 데이터 기반으로 내릴 수 있도록 도와주는 도구

  • 플레이어 행동 데이터 수집

    • 플레이어의 행동, 이벤트, 게임 내 활동을 자동으로 기록.
    • 커스텀 이벤트 정의를 통해 특정 데이터 수집 가능.
    • 플레이어 세그먼트(예: 신규 사용자, 재방문 사용자)에 따라 데이터를 분류.
  • 데이터 시각화 및 보고서

    • 대시보드에서 다양한 데이터의 시각화를 제공하여 게임의 성과를 한눈에 확인.
    • KPI(Key Performance Indicator) 추적:
      • DAU(일간 활성 사용자)
      • MAU(월간 활성 사용자)
      • ARPU(사용자당 평균 수익)
    • 사용자 정의 보고서를 생성하여 맞춤형 분석 가능.
  • 실시간 분석

    • 게임 출시 후 실시간으로 데이터 수집 및 분석.
    • 즉각적인 피드백을 통해 게임 내 문제를 식별하고 대응 가능.
  • 플레이어 유지 및 참여 분석

    • 코호트 분석: 특정 그룹(예: 특정 시기에 가입한 사용자)의 행동 패턴을 추적.
    • 유저 리텐션(사용자 유지율) 데이터 제공.
  • A/B 테스트 지원

    • 게임의 두 가지 버전을 비교하여 더 나은 결과를 도출하는 실험 가능.
    • 업데이트 및 기능의 효과를 객관적으로 측정.
  • 데이터 기반 의사결정 지원

    • 수집된 데이터를 통해 콘텐츠 업데이트, 밸런스 조정, 마케팅 캠페인 최적화.
    • 사용자 세분화를 통해 타겟팅된 전략을 실행.
  • 데이터 보안 및 규정 준수

    • GDPR, CCPA 등 데이터 보호 규정을 준수.
    • 민감한 사용자 데이터를 안전하게 처리.

○ 프로젝트 내 코드

  • 게임 시작시 데이터 수집 시작하도록 함
async void Awake()
{
    await InitializeUnityServices();
    // UGS 초기화 비동기로
}

private void Start()
{
    AnalyticsService.Instance.StartDataCollection();
    // 분석 데이터 수집 시작
}

private async Task InitializeUnityServices()
{
    try
    {
        await UnityServices.InitializeAsync();
        if (UnityServices.State == ServicesInitializationState.Initialized)
        {
            Debug.Log("USG 초기화");
        }
    }
    catch (Exception e)
    {
        Debug.LogError($"UGS 실패: {e.Message}");
    }
}


■ MazeStage

  • 미로 스테이지에 입장하면 그때 그때 미로를 타일맵으로 만든다.
  • 풀을 이용해서 최적화 할 필요가 있음(보상상자도)
using System.Runtime.CompilerServices;
using UnityEngine;

public enum MazeTileType
{
    NONE = 0,
    EMPTY,
    WALL,
}

public class MazeGenerator : MonoBehaviour
{
    [SerializeField] private GameObject tilePrefab;
    [SerializeField] private int mazeSize = 100;
    private MazeTileType[,] maze;
    private float tileSize = 1.8f;

    private void Awake()
    {
        
        maze = new MazeTileType[mazeSize, mazeSize];
    }

    private void Start()
    {
        GenerateMap();
        Render();
    }

    /// <summary>
    /// maze 각 위치에 저장된 값에 맞게 미로를 랜더링하는 함수입니다.
    /// </summary>
    private void Render()
    {

        for (int x = 0; x < mazeSize; x++)
        {
            for (int z = 0; z < mazeSize; z++)
            {
                if (maze[x, z] == MazeTileType.WALL)
                {
                    Vector3 localPosition = new Vector3(
                        x * tileSize - (mazeSize * tileSize / 2),
                        0,
                        z * tileSize - (mazeSize * tileSize / 2)
                    );

                    GameObject tile = Instantiate(tilePrefab, transform);
                    tile.transform.localPosition = localPosition;
                }
            }
        }
    }

    /// <summary>
    /// 미로 벽, 빈칸 위치를 지정하는 함수입니다.
    /// </summary>
    private void GenerateMap()
    {
        // 모든 칸을 벽으로 초기화
        for (int x = 0; x < mazeSize; x++)
        {
            for (int z = 0; z < mazeSize; z++)
            {
                maze[x, z] = MazeTileType.WALL;
            }
        }

        // 내부 미로 초기화
        for (int x = 1; x < mazeSize - 1; x++)
        {
            for (int z = 1; z < mazeSize - 1; z++)
            {
                if (x % 2 == 1 && z % 2 == 1)
                {
                    maze[x, z] = MazeTileType.EMPTY;
                }
            }
        }

        // 시작점 열기 (좌측 상단)
        maze[1, 0] = MazeTileType.EMPTY;

        // 출구 열기 (우측 하단)
        maze[mazeSize - 2, mazeSize - 1] = MazeTileType.EMPTY;

        // 랜덤 경로 생성
        for (int x = 1; x < mazeSize - 1; x++)
        {
            for (int z = 1; z < mazeSize - 1; z++)
            {
                if (z % 2 == 0 || x % 2 == 0)
                {
                    continue;
                }

                if (z == mazeSize - 2 && x == mazeSize - 2)
                {
                    continue;
                }

                if (x == mazeSize - 2)
                {
                    maze[x, z + 1] = MazeTileType.EMPTY;
                    continue;
                }

                if (z == mazeSize - 2)
                {
                    maze[x + 1, z] = MazeTileType.EMPTY;
                    continue;
                }

                if (Random.Range(1, 100) % 2 == 0)
                {
                    maze[x, z + 1] = MazeTileType.EMPTY;
                }
                else
                {
                    maze[x + 1, z] = MazeTileType.EMPTY;
                }
            }
        }
    }
}

0개의 댓글