[TIL] 37 3D ๊ฐ•์˜, UI โญโญ

์—…๋ฐ์ดํŠธ:

์นดํ…Œ๊ณ ๋ฆฌ:

ํƒœ๊ทธ: , ,




์œ ๋‹ˆํ‹ฐ ์ˆ™๋ จ์ฃผ์ฐจ 8์ผ์ฐจ

ย ย  [o] ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ - 45
ย ย  [o] ๊ฐ•์˜ ๋“ฃ๊ธฐ - 22๊ฐ•~
ย ย  [o] ๊ฐ•์˜ ๋“ฃ๊ธฐ - UI๊ฐ•์˜~
ย ย  [o] ๊ฐ•์˜ ๋“ฃ๊ธฐ - 2๋ฐ˜๊ฐ•์˜~
ย ย  [X] ๋‹ค๋ฅธ๋ฐ˜ ๊ฐ•์˜ ๋“ฃ๊ธฐ
ย ย  [X] ๋‹ค๋ฅธ๋ฐ˜ ๋ฐœํ‘œ ๋ณด๊ธฐ







1. UI๊ฐ•์˜

ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ๊ฒŒ์ž„์„ ํ•  ๋•Œ ์›ํ™œํ•˜๊ฒŒ ํ”Œ๋ ˆ์ด ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ
๊ฒŒ์ž„UI : ๋ชฐ์ž…์„ฑ , ์ƒํ™ฉ์„ ๋น ๋ฅด๊ฒŒ ์ดํ•ด, ํ™”๋ฉด์ค‘์•™์— ์ง‘์ค‘๋˜๊ฒŒ ์‹ฌํ”Œํ•œ ๋””์ž์ธ

UI ์ฒดํฌ์‚ฌํ•ญ

  • ๊ฒŒ์ž„์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๋””์ž์ธ
  • ์ ์ ˆํ•œ ๋ฐฉ๋ฒ•, ๋ช…ํ™•ํ•œ ์•ˆ๋‚ด
  • ๊ฐ€์ด๋“œ, ํŠœํ† ๋ฆฌ์–ผ ์ดํ•ด์‰ฝ๊ฒŒ, ๊ฑด๋„ˆ๋›ฐ๊ธฐ
  • ์‹œ๊ฐํšจ๊ณผ๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด์ƒ, ์ธ์•ฑ ๊ตฌ๋งค ๋ˆˆ์— ๋„๊ฒŒ
  • UI๋Š” ๋‹จ์ˆœํ•˜๊ฒŒ ๋ณต์žกX
  • ๊ณ„์ธต๊ตฌ์กฐ, ์ค‘์š”๋ถ€๋ถ„ ํ‘œ์‹œ ๋ช…ํ™•ํ•œ ์•ˆ๋‚ด
  • ์‚ฌ์ด๋“œ๋ฐ” ์ œ๊ณต, ๊ณต๊ฐ„ ํ™•์žฅ
  • ๋ฐ˜์‘ํ˜• UI



Mesh

์ž‘๋™์›๋ฆฌ
image

image



DrawCall

๊ณ„์† ๋ณ€ํ•˜๋Š” UI๋Š” ๋งค๋ฒˆ CPU์—์„œ ์—ฐ์‚ฐ ํ›„ GPU๋กœ ๋„˜๊ธฐ๋Š” ๊ตฌ์กฐ
DRAWCALL = ํ™”๋ฉด์— ๊ทธ๋ ค์ค˜~

image

UGUI

  • Grapgics.cs : ๊ทธ๋ž˜ํ”ฝ์  ์š”์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํด๋ž˜์Šค(Image ๋“ฑ) ๊ด€๋ฆฌ
  • Canvas.cpp : ๊ทธ๋ž˜ํ”ฝ์  ์š”์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ํ•˜๋‚˜์˜ ๋ฒ„ํผ๋กœ ๋งŒ๋“ค์–ด์„œ GPU์— ํ• ๋‹น
    Canvas ํ•˜์œ„์— UI์š”์†Œ๊ฐ€ ๊ฐฑ์‹ ๋˜๋ฉด ์ „์ฒด Canvas๋ฅผ ๊ฐฑ์‹ ํ•ด์•ผ ํ•จ




Canvas

ui ์ƒ์„ฑ์‹œ Canvas ์ž๋™์ƒ์„ฑ
Canvas(๋„ํ™”์ง€) 3D์ขŒํ‘œ์ƒ์˜ ์œ„์น˜๊ฐ€ ์•„๋‹Œ ์œ ์ €์—๊ฒŒ ๋ณด์—ฌ์ง€๋Š” ์Šคํฌ๋ฆฐ์— ๋Œ€์‘ํ•˜๋Š”

image


Rect TransForm

TransForm์„ ์ƒ์†๋ฐ›์€(๋ถˆ๋ณ€) (RENDER MODE - WORLD ๋ฉด ์ˆ˜์ •๊ฐ€๋Šฅ)

Anchors

UI Elemnet ์›์ ์„ ์„ธํŒ…ํ•˜๋Š” ๊ธฐ์ค€

image

์•ต์ปค๊ฐ’ ๊ธฐ์ค€์œผ๋กœ pos x ,y ๊ฐ€ ์ •ํ•ด์ง„๋‹ค.
image

์•ต์ปค min,max ๋‹ค๋ฅผ ๋•Œ
image

Pivot

UI Elemnet ๋‚ด๋ถ€ ๊ธฐ์ค€์ ์„ ์„ธํŒ…ํ•˜๋Š” ๊ธฐ์ค€

image
image



CanvasScale

Render Mode

overlay -> ์บ”๋ฒ„์Šค๊ฐ€ ๋ชจ๋“  ์˜ค๋ธŒ์ ํŠธ๋ณด๋‹ค ์•ž์— ๊ทธ๋ ค์ง„๋‹ค Cmara : ์นด๋ฉ”๋ผ ์‹œ์ ์œผ๋กœ ์บ”๋ฒ„์Šค๊ฐ€ ๋ณด์ผ ์ˆ˜ ์žˆ๋‹ค. world : ์˜ค๋ธŒ์ ํŠธ์ฒ˜๋Ÿผ ๋ฐฐ์น˜

Canvas Scaler(๋ฐ˜์‘ํ˜•์œผ๋กœ)

Scale Mode : Scale With Screen Size
Reference Resolution 1920 1080

Screen Math Mode

Match Width Or Height : ํ•ด์ƒ๋„ ๋ณ€ํ™” ์‹œ ๋„“์ด ๋˜๋Š” ๋†’์ด๋ฅผ ๋ณ€๊ฒฝx Expand : Reference Resolution ๋ณด๋‹ค ์ž‘๊ฒŒ ์•ˆ๋งŒ๋“ ๋‹ค.







2. 2๋ฐ˜๊ฐ•์˜

๋ฐ์ดํ„ฐ ์ €์žฅ

image
Serializable ์ง๋ ฌํ™” -> byte ๋ฐฐ์—ด๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ?
Serializable์„ ๋‹ฌ๋ฉด ์ง๋ ฌํ™” ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

[Serializable]
public class MyClass{
	public int a;
	public int b;
}

[Serializable]
public class MyBigClass{
	public MyClass my;
}

public class myCharacterData{
	// Transform ์ง์ ‘ ๋„ฃ๋Š”๊ฑฐ ์•ˆ๋จ
	public Vector3 position;
	public Quaternion rotation;
}



1)Playerprefs

๋ฌธ์ž์—ด ์‹ค์ˆ˜ ์ •์ˆ˜ ๊ฐ’์„ ํ”Œ๋žซํผ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.
์•”ํ˜ธํ™”x ๋ฏผ๊ฐํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š”๋ฐ ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค.

// ์ •๋ณด๋“ค์„ , ๋กœ ๊ตฌ๋ถ„ํ•ด ์ €์žฅ
string userId = "user1234";
string password = "password123";
string name = "ํ™๊ธธ๋™";
int balance = 10000;

string combinedInfo = password + "," + name + "," + balance.ToString();
PlayerPrefs.SetString(userId, combinedInfo);
PlayerPrefs.Save();

//๋ถˆ๋Ÿฌ์˜ค๊ธฐ
if(PlayerPrefs.HasKey(userId){ // ID ์žˆ์Œ
	string savedInfo = PlayerPrefs.GetString(userId);
	string[] infoParts = savedInfo.Split(',');
	
	string loadedPassword = infoParts[0];
	string loadedName = infoParts[1];
	int loadedBalance = int.Parse(infoParts[2]);
	
	Debug.Log("๋น„๋ฐ€๋ฒˆํ˜ธ: " + loadedPassword);
	Debug.Log("์ด๋ฆ„: " + loadedName);
	Debug.Log("์ž”์•ก: " + loadedBalance);
}
else {
		// ID ์—†์Œ
}



2)CSV

CSV(Comma-Separated Values) ๊ฐ์ค„์ด ํ•˜๋‚˜์˜ ๋ฐ์ดํ„ฐ ๋ ˆ์ฝ”๋“œ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

์˜ˆ์ œ
ํ•„์š” ์ •๋ณด๋ฅผ ,๋ฅผ ๊ตฌ๋ถ„ํ•˜์—ฌ ๋ฌถ๊ณ  ๋ถˆ๋Ÿฌ์˜ฌ๋•Œ ๊ฐ™์ด ๋ถˆ๋Ÿฌ ์˜ค๋Š” ๋ฐฉ๋ฒ•

[System.Serializable]
public class Item
{
    public int id;
    public string name;
    public int price;
    public string type;

    public Item(int id, string name, int price, string type)
    {
        this.id = id;
        this.name = name;
        this.price = price;
        this.type = type;
    }
}

using System.Collections.Generic;
using UnityEngine;

public class CSVReader : MonoBehaviour
{
    public TextAsset csvFile; // Unity Editor์—์„œ ํ• ๋‹น

    void Start()
    {
				csvFile = Resources.Load<TextAsset>("/File/myFile");

        List<Item> items = ReadCsv(csvFile.text);
        // ์ฝ์€ ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ ์˜ˆ
        foreach (Item item in items)
        {
            Debug.Log($"์•„์ดํ…œ: {item.name}, ๊ฐ€๊ฒฉ: {item.price}, ํƒ€์ž…: {item.type}");
        }
    }

    List<Item> ReadCsv(string csvData)
    {
        List<Item> items = new List<Item>();

        string[] lines = csvData.Split('\n');
        for (int i = 1; i < lines.Length; i++) // ํ—ค๋”์ค„ ์ œ์™ธ!
        {
            if (lines[i].Trim() == "") continue;

            string[] fields = lines[i].Split(',');
            int id = int.Parse(fields[0]);
            string name = fields[1];
            int price = int.Parse(fields[2]);
            string type = fields[3];

            items.Add(new Item(id, name, price, type));
        }

        return items;
    }
}



3)JSON

JSON(JavaScript Object Notation) ๊ฒฝ๋Ÿ‰ ๋ฐ์ดํ„ฐ ๊ตํ™˜ ํ˜•์‹.
json์—๋Š” csv์™€ ๋‹ฌ๋ฆฌ ํ•˜๋‚˜์˜ ์†์„ฑ์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ๊ฐ’์ด ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.
์‚ฌ๋žŒ ๊ธฐ๊ณ„ ๋ชจ๋‘์—๊ฒŒ ์ฝ๊ธฐ ์‰ฝ๊ณ  ์“ฐ๊ธฐ ์‰ฌ์šด ํ˜•์‹

using UnityEngine;
using System.IO;

public class JsonDataManager : MonoBehaviour
{
    private string filePath;

    private void Awake()
    {
        filePath = Application.persistentDataPath + "/data.json";
    }

    public void SaveData(PlayerData data)
    {
        string jsonData = JsonUtility.ToJson(data, true);
        File.WriteAllText(filePath, jsonData);
    }

    public PlayerData LoadData()
    {
        if (File.Exists(filePath))
        {
            string jsonData = File.ReadAllText(filePath);
            return JsonUtility.FromJson<PlayerData>(jsonData);
        }
        else
        {
            Debug.LogError("Save file not found.");
            return null;
        }
    }
}
//์˜ˆ์ œ2
using UnityEngine;

[System.Serializable]
public class PlayerData
{
    public string playerName;
    public int playerLevel;
    public float playerHealth;
}

public class Player : MonoBehaviour
{
    public PlayerData playerData;

    private void Start()
    {
        playerData = new PlayerData();
        playerData.playerName = "John";
        playerData.playerLevel = 10;
        playerData.playerHealth = 100.0f;

        SavePlayerData();
        LoadPlayerData();
    }

    private void SavePlayerData()
    {
        string jsonData = JsonUtility.ToJson(playerData);
        PlayerPrefs.SetString("PlayerData", jsonData);
        PlayerPrefs.Save();
    }

    private void LoadPlayerData()
    {
        if (PlayerPrefs.HasKey("PlayerData"))
        {
            string jsonData = PlayerPrefs.GetString("PlayerData");
            playerData = JsonUtility.FromJson<PlayerData>(jsonData);

            Debug.Log("Player Name: " + playerData.playerName);
            Debug.Log("Player Level: " + playerData.playerLevel);
            Debug.Log("Player Health: " + playerData.playerHealth);
        }
    }
}



4)ScriptableObject

์œ ๋‹ˆํ‹ฐ ์—”์ง„์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ฐ์ดํ„ฐ ์ปจํ…Œ์ด๋„ˆ.
๊ฒŒ์ž„ ์˜ค๋ธŒ์ ํŠธ๋‚˜ ์”ฌ์— ์ข…์†๋˜์ง€ ์•Š๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅ, ๊ณต์œ  ๊ฐ€๋Šฅ.
๋ฆฌ์†Œ์Šค, ์„ค์ •, ์ƒํƒœ ๋“ฑ์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ
์œ ๋‹ˆํ‹ฐ์— ์‚ฌ์šฉํ•˜๋Š” ์š”์†Œ(sprite, prefabs)๋“ฑ ์„ ์ €์žฅ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์‚ฌ์šฉ ์‹œ ์ฃผ์˜์ 
์—๋””ํ„ฐ ์‚ฌ์šฉ ์‹œ so ์— ์ €์žฅํ•˜๋Š” ์ž‘์—…๋Š” ํŽธ์ง‘, ๋Ÿฐํƒ€์ž„์— ๊ฐ€๋Šฅ
๋ฒ ํฌ๋œ ๋นŒ๋“œ์—์„œ๋Š” so๋ฅผ ์‚ฌ์šฉํ•ด ์ €์žฅx, ๊ฐœ๋ฐœ ์‹œ ์„ค์ •ํ•œ so ์—์…‹์˜ ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉo
-> ์ˆ˜์ •์€ ์—๋””ํ„ฐ์—์„œ๋งŒ ๊ฐ€๋Šฅ -> ํ”Œ๋ ˆ์ด ์ค‘ ์ˆ˜์ •๋˜๋Š” ์ •๋ณด๋Š” so๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋œ๋‹ค.

using UnityEngine;

[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/SpawnManagerScriptableObject", order = 1)]
public class SpawnManagerScriptableObject : ScriptableObject
{
    public string prefabName;

    public int numberOfPrefabsToCreate;
    public Vector3[] spawnPoints;
}

using UnityEngine;

public class Spawner : MonoBehaviour
{
    // The GameObject to instantiate.
    public GameObject entityToSpawn;

    // An instance of the ScriptableObject defined above.
    public SpawnManagerScriptableObject spawnManagerValues;

    // This will be appended to the name of the created entities and increment when each is created.
    int instanceNumber = 1;

    void Start()
    {
        SpawnEntities();
    }

    void SpawnEntities()
    {
        int currentSpawnPointIndex = 0;

        for (int i = 0; i < spawnManagerValues.numberOfPrefabsToCreate; i++)
        {
            // Creates an instance of the prefab at the current spawn point.
            GameObject currentEntity = Instantiate(entityToSpawn, spawnManagerValues.spawnPoints[currentSpawnPointIndex], Quaternion.identity);

            // Sets the name of the instantiated entity to be the string defined in the ScriptableObject and then appends it with a unique number. 
            currentEntity.name = spawnManagerValues.prefabName + instanceNumber;

            // Moves to the next spawn point index. If it goes out of range, it wraps back to the start.
            currentSpawnPointIndex = (currentSpawnPointIndex + 1) % spawnManagerValues.spawnPoints.Length;

            instanceNumber++;
        }
    }
}



5)Binary Formatter

๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌ ๊ณต์œ 
๋ฐ์ดํ„ฐ์˜ ๊ตฌ์กฐ์ˆ˜์ • x ex) ๋Šฅ๋ ฅ์น˜ ์ถ”๊ฐ€x

using UnityEngine;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[System.Serializable]
public class PlayerData
{
    public string playerName;
    public int playerLevel;
    public float playerHealth;
}

public class SaveLoadManager : MonoBehaviour
{
    public PlayerData playerData;

    private string saveFilePath;

    private void Awake()
    {
        saveFilePath = Application.persistentDataPath + "/playerData.dat";
    }

    public void SavePlayerData()
    {
        BinaryFormatter binaryFormatter = new BinaryFormatter();
        FileStream fileStream = File.Create(saveFilePath);

        binaryFormatter.Serialize(fileStream, playerData);
        fileStream.Close();
    }

    public void LoadPlayerData()
    {
        if (File.Exists(saveFilePath))
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            FileStream fileStream = File.Open(saveFilePath, FileMode.Open);

            playerData = (PlayerData)binaryFormatter.Deserialize(fileStream);
            fileStream.Close();
        }
        else
        {
            Debug.Log("Save file not found.");
        }
    }
}



๋ฉ”์†Œ๋“œ/ ํ”„๋กœํผํ‹ฐ

๋ฐ์ดํ„ฐ ์ €์žฅ์— ๋งŽ์ด ์“ฐ์ด๋Š” ๋ฉ”์†Œ๋“œ/ํ”„๋กœํผํ‹ฐ
Application.persistentDataPath
File.Exists
File.ReadAllTEXT
File.WriteAllTEXT

๊ฐ๊ฐ์˜ ์šฉ๋„ so - ๊ฐ’์„ ์ฝ๊ธฐ๋งŒํ•˜๋Š” ๋ฐ์ดํ„ฐ๋“ค
csv, son - ์ฝ๊ณ  ์“ฐ๊ธฐ ๊ฐ€๋Šฅ ํ•œ ๋ฐ์ดํ„ฐ๋“ค
Binary Formatter - ์„ฑ๋Šฅ์ด ๊ฐ€์žฅ์ข‹๋‹ค. but ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์ˆ˜์ •x

๋กœ์ปฌ(๋””๋ฐ”์ด์Šค) ์— ์ €์žฅํ•˜๋Š” ๋ฐฉ์‹
๊ฐœ์ธ์ด ์ˆ˜์ •์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค. -> ๋ฒ„๊ทธํŒ์ด ๋‚˜์˜จ๋‹ค.
์„œ๋ฒ„์— ์ €์žฅํ•˜๋Š”๊ฒƒ์ด ์ •๋‹ต.







์žก๋‹ด,์ •๋ฆฌ

ui์— ๊ด€ํ•˜์—ฌ.
so - ๊ฐ’์„ ์ฝ๊ธฐ๋งŒํ•˜๋Š” ๋ฐ์ดํ„ฐ๋“ค ๋นŒ๋“œ ํ›„ ๊ณ ๋ ค
csv, son - ์ฝ๊ณ  ์“ฐ๊ธฐ ๊ฐ€๋Šฅ ํ•œ ๋ฐ์ดํ„ฐ๋“ค
Binary Formatter - ์„ฑ๋Šฅ์ด ๊ฐ€์žฅ์ข‹๋‹ค. but ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์ˆ˜์ •x





์ฐธ๊ณ  : ์œ ๋‹ˆํ‹ฐ TOP


๐Ÿ“”

๋Œ“๊ธ€๋‚จ๊ธฐ๊ธฐ