내일배움캠프 49일차 TIL : HashSet, Resources, 에셋 번들, 어드레서블

woollim·2024년 12월 2일
0

내일배움캠프TIL

목록 보기
42/65
post-thumbnail

■ 개요

오늘 계획

  • 오전 내 할일
    • 피그마, 데이터베이스 시트 정리
    • Json 저장 구현
      • 로컬 저장
    • 구글 시트에서 일괄파싱 기능 연구해서 추가
      • 게임킬때 일괄 파싱 할 수 있도록
    • 스테이지 자동 배정
      • 일단 스테이지 데이터베이스 접근하기
      • 랜덤값 받아서 ID로 구별


■ HashSet

○ 개념

  • HashSet은 집합(Set) 자료 구조
  • Unity에서 HashSet은 일반적으로 C#의 System.Collections.Generic 네임스페이스에 포함되어 있어 사용 가능
    • using System.Collections.Generic;
  • Unity 프로젝트에서 HashSet은 중복을 방지하거나 빠른 조회 속도가 필요한 상황에서 사용
    • 중복 허용 안 함: 동일한 값을 두 번 추가할 수 없음
    • 빠른 검색: 데이터의 해시 값을 기반으로 하기 때문에 삽입, 삭제, 검색 연산이 평균적으로 O(1)의 시간 복잡도를 가짐
    • 순서 없음: 데이터가 추가된 순서를 보장하지 않음
  • HashSet은 데이터를 빠르게 추가하거나 검색해야 하는 경우에 특히 유용하며, 리스트(List)나 배열(Array)보다 유리한 점이 많음

○ 사용법

  1. 네임스페이스 가져오기
using System.Collections.Generic;
  1. HashSet 생성
HashSet<string> myHashSet = new HashSet<string>();
  1. 데이터 추가
myHashSet.Add("Apple");
myHashSet.Add("Banana");
  1. 데이터 존재 여부 확인
if (myHashSet.Contains("Apple")) 
{
    Debug.Log("Apple이 존재합니다.");
}
  1. 데이터 제거
myHashSet.Remove("Banana");
  1. 모든 데이터 삭제
myHashSet.Clear();
  1. 집합연산
  • 교집합: 두 집합에 모두 포함된 요소.
  • 합집합: 두 집합의 모든 요소.
  • 차집합: 첫 번째 집합에만 포함된 요소.
HashSet<int> setA = new HashSet<int>() { 1, 2, 3, 4 };
HashSet<int> setB = new HashSet<int>() { 3, 4, 5, 6 };

// 교집합
setA.IntersectWith(setB);
Debug.Log(string.Join(", ", setA)); // 출력: 3, 4

// 합집합
setA.UnionWith(setB);
Debug.Log(string.Join(", ", setA)); // 출력: 1, 2, 3, 4, 5, 6

// 차집합
setA.ExceptWith(setB);
Debug.Log(string.Join(", ", setA)); // setA에만 포함된 값 출력

○ Unity에서 활용 예

  • 충돌 판정: 게임 오브젝트가 충돌했을 때 고유한 충돌 객체를 저장
    • 게임에서 여러 충돌체를 관리할 때 중복 충돌 객체를 제거하기 위해 HashSet을 사용
HashSet<GameObject> collidedObjects = new HashSet<GameObject>();

void OnCollisionEnter(Collision collision)
{
    collidedObjects.Add(collision.gameObject);
}

void Update()
{
    foreach (var obj in collidedObjects)
    {
        Debug.Log(obj.name + "와 충돌 중");
    }
}
  • 태그 관리: 중복이 없는 고유 태그를 관리
    • 태그를 중복 없이 저장하고 관리할 수 있음
HashSet<string> uniqueTags = new HashSet<string>();

void AddTag(string tag)
{
    if (uniqueTags.Add(tag))
    {
        Debug.Log(tag + "이 추가되었습니다.");
    }
    else
    {
        Debug.Log(tag + "은 이미 존재합니다.");
    }
}
  • 성능 최적화: 탐색 속도가 중요한 데이터 처리
    • 리스트(List)나 배열(Array)는 요소를 검색할 때 O(n)의 시간 복잡도를 가지지만, HashSet은 O(1)로 훨씬 빠름

○ 장단점

  • 장점
    • 중복 방지
    • 빠른 검색 및 삽입 성능
    • 집합 연산 지원
  • 단점
    • 메모리 사용량이 상대적으로 많음 (해시 테이블 사용)
    • 데이터가 순서 없이 저장되므로 특정 순서로 처리해야 할 경우 부적합


■ Resources

○ 개념

  • Unity에서 Resources 폴더는 특정 애셋을 런타임에 동적으로 로드할 수 있도록 설계된 특별한 폴더
  • 이 폴더에 저장된 애셋은 빌드 시 포함되며, Resources.Load API를 통해 메모리에 로드할 수 있음

○ 주요 특징

  1. 동적 로드: 코드에서 애셋을 이름으로 불러옴
Texture2D myTexture = Resources.Load<Texture2D>("Textures/MyTexture");
  1. 배치 관리: 정적 참조가 필요 없는 애셋을 로드하여 메모리 최적화 가능
  2. 유용한 경우 : 특정 조건에 따라 애셋을 로드해야 하는 경우. 메모리를 절약하기 위해 필요한 시점에만 애셋을 로드하려는 경우.
  3. 주의사항: 모든 Resources 애셋은 메모리에 포함되므로, 남용 시 메모리 사용량 증가. 때문에 대규모 프로젝트에서는 효율적으로 관리하지 않으면 성능 저하를 초래할 수 있음
  4. 권장사항: 적은 수의 애셋을 동적으로 로드할 때만 사용. 규모 애셋 관리를 위해서는 Addressables 시스템이 더 적합

○ 사용예시

  • 기본 이미지 로드
    • 목표: Resources 폴더에서 이미지 파일을 로드하여 텍스처로 사용
    • 폴더구조: Assets/Resources/Textures/MyTexture.png
using UnityEngine;

public class Example : MonoBehaviour
{
    void Start()
    {
        // Resources 폴더 내 "Textures/MyTexture"에 위치한 텍스처 로드
        Texture2D myTexture = Resources.Load<Texture2D>("Textures/MyTexture");

        if (myTexture != null)
        {
            Debug.Log("텍스처 로드 성공!");
        }
        else
        {
            Debug.Log("텍스처 로드 실패!");
        }
    }
}
  • 프리팹 로드 및 생성
    • 목표: Resources 폴더에서 프리팹을 로드하여 동적으로 생성
    • 폴더구조: Assets/Resources/Prefabs/MyPrefab.prefab
using UnityEngine;

public class InstantiateExample : MonoBehaviour
{
    void Start()
    {
        // Resources 폴더 내 "Prefabs/MyPrefab"에 위치한 프리팹 로드
        GameObject prefab = Resources.Load<GameObject>("Prefabs/MyPrefab");

        if (prefab != null)
        {
            // 프리팹 인스턴스 생성
            Instantiate(prefab, Vector3.zero, Quaternion.identity);
            Debug.Log("프리팹 생성 성공!");
        }
        else
        {
            Debug.Log("프리팹 로드 실패!");
        }
    }
}
  • 오디오 파일 로드
    • 목표: Resources 폴더에서 오디오 파일을 로드하고 재생
    • 폴더구조: Assets/Resources/Audio/BackgroundMusic.wav
using UnityEngine;

public class AudioExample : MonoBehaviour
{
    private AudioSource audioSource;

    void Start()
    {
        // AudioSource 컴포넌트 추가
        audioSource = gameObject.AddComponent<AudioSource>();

        // Resources 폴더 내 "Audio/BackgroundMusic"에 위치한 오디오 클립 로드
        AudioClip clip = Resources.Load<AudioClip>("Audio/BackgroundMusic");

        if (clip != null)
        {
            audioSource.clip = clip;
            audioSource.Play();
            Debug.Log("오디오 재생 중!");
        }
        else
        {
            Debug.Log("오디오 로드 실패!");
        }
    }
}
  • 전체 애셋 리스트 로드
    • 목표: Resources 폴더 내 특정 타입의 모든 애셋 로드
    • 폴더구조: Assets/Resources/ Textures/ Texture1.png Texture2.png
using UnityEngine;

public class LoadAllExample : MonoBehaviour
{
    void Start()
    {
        // Resources 폴더 내 모든 텍스처 로드
        Texture2D[] textures = Resources.LoadAll<Texture2D>("Textures");

        foreach (Texture2D texture in textures)
        {
            Debug.Log("로드된 텍스처: " + texture.name);
        }
    }
}

○ 주의 사항

  • 경로 주의: Resources.Load 함수는 폴더 이름을 포함한 경로를 문자열로 전달받지만, Resources/ 폴더 자체는 경로에서 제외합니다.
  • 메모리 관리: 동적으로 로드된 애셋은 메모리를 차지하므로 더 이상 필요하지 않을 때 Resources.UnloadUnusedAssets를 호출하여 정리할 수 있습니다.
    큰 프로젝트에서는 Addressables 시스템을 고려하세요.


■ 애셋 번들 (Asset Bundles)

○ 개념

  • 개념
    • Unity에서 제공하는 파일 패키지 형식으로, 필요한 애셋만 런타임에서 다운로드 및 로드할 수 있도록 설계됨
    • 애셋 번들은 네트워크를 통해 다운로드하거나 로컬 저장소에서 로드할 수 있음
  • 특징
    • 빌드 크기를 줄이고 필요한 애셋만 로드 가능
    • 유저가 콘텐츠를 개별적으로 다운로드하도록 할 수 있음 (예: DLC)
    • 복잡한 종속성 관리 필요
  • 사용 시기
    • 대규모 프로젝트에서 런타임에만 특정 애셋이 필요할 때.
    • 콘텐츠를 배포 또는 업데이트하려는 경우.


■ 어드레서블 (Addressables)

○ 개념

  • 개념
    • 애셋 번들을 쉽게 관리할 수 있도록 Unity에서 제공하는 고급 시스템
    • Addressable 애셋으로 등록된 모든 콘텐츠는 런타임에서 이름이나 주소로 로드 가능
  • 특징
    • 애셋 번들의 복잡한 종속성 문제를 자동으로 관리
    • 네트워크나 로컬에서 애셋을 로드
    • 비동기 로드를 기본 지원
    • 프로파일을 통해 플랫폼별 설정 가능
  • 사용시기
    • 대규모 프로젝트에서 효율적인 애셋 관리를 위해.
    • 유연한 로드, 메모리 관리, DLC 배포가 필요한 경우.


■ 차이점

○ 선택기준

  • Resources:
    • 작은 프로젝트나 간단한 애셋 로드가 필요한 경우
    • 초기 학습 및 테스트 프로젝트에 적합
  • 애셋 번들:
    • 런타임에 동적 로드가 필수인 경우
    • 네트워크 배포와 DLC를 사용하려는 경우
  • 어드레서블:
    • 애셋 번들의 유연성과 자동화를 활용하려는 경우
    • 대규모 프로젝트에서 효율적인 관리와 성능이 중요한 경우

  • 참고하기 좋은 에셋번들 사용법 사이트

0개의 댓글