[TIL] 37 3D ๊ฐ์, UI โญโญ
์นดํ ๊ณ ๋ฆฌ: Til
์ ๋ํฐ ์๋ จ์ฃผ์ฐจ 8์ผ์ฐจ
ย ย [o] ์๊ณ ๋ฆฌ์ฆ ๋ฌธ์ - 45
ย ย [o] ๊ฐ์ ๋ฃ๊ธฐ - 22๊ฐ~
ย ย [o] ๊ฐ์ ๋ฃ๊ธฐ - UI๊ฐ์~
ย ย [o] ๊ฐ์ ๋ฃ๊ธฐ - 2๋ฐ๊ฐ์~
ย ย [X] ๋ค๋ฅธ๋ฐ ๊ฐ์ ๋ฃ๊ธฐ
ย ย [X] ๋ค๋ฅธ๋ฐ ๋ฐํ ๋ณด๊ธฐ
1. UI๊ฐ์
ํ๋ ์ด์ด๊ฐ ๊ฒ์์ ํ ๋ ์ํํ๊ฒ ํ๋ ์ด ํ ์ ์๋๋ก ์ค๊ณํ๋ ๊ฒ
๊ฒ์UI : ๋ชฐ์
์ฑ , ์ํฉ์ ๋น ๋ฅด๊ฒ ์ดํด, ํ๋ฉด์ค์์ ์ง์ค๋๊ฒ ์ฌํํ ๋์์ธ
UI ์ฒดํฌ์ฌํญ
- ๊ฒ์์ ์ดํดํ ์ ์๋๋ก ๋์์ธ
- ์ ์ ํ ๋ฐฉ๋ฒ, ๋ช ํํ ์๋ด
- ๊ฐ์ด๋, ํํ ๋ฆฌ์ผ ์ดํด์ฝ๊ฒ, ๊ฑด๋๋ฐ๊ธฐ
- ์๊ฐํจ๊ณผ๋ฅผ ์ฌ์ฉํด ๋ณด์, ์ธ์ฑ ๊ตฌ๋งค ๋์ ๋๊ฒ
- UI๋ ๋จ์ํ๊ฒ ๋ณต์กX
- ๊ณ์ธต๊ตฌ์กฐ, ์ค์๋ถ๋ถ ํ์ ๋ช ํํ ์๋ด
- ์ฌ์ด๋๋ฐ ์ ๊ณต, ๊ณต๊ฐ ํ์ฅ
- ๋ฐ์ํ UI
Mesh
์๋์๋ฆฌ
DrawCall
๊ณ์ ๋ณํ๋ UI๋ ๋งค๋ฒ CPU์์ ์ฐ์ฐ ํ GPU๋ก ๋๊ธฐ๋ ๊ตฌ์กฐ
DRAWCALL = ํ๋ฉด์ ๊ทธ๋ ค์ค~
UGUI
- Grapgics.cs : ๊ทธ๋ํฝ์ ์์๋ฅผ ๊ฐ์ง๊ณ ์๋ ํด๋์ค(Image ๋ฑ) ๊ด๋ฆฌ
- Canvas.cpp : ๊ทธ๋ํฝ์ ์์๋ฅผ ๊ฐ์ง๊ณ ์๋ ๊ฒ์ ํ๋์ ๋ฒํผ๋ก ๋ง๋ค์ด์ GPU์ ํ ๋น
Canvas ํ์์ UI์์๊ฐ ๊ฐฑ์ ๋๋ฉด ์ ์ฒด Canvas๋ฅผ ๊ฐฑ์ ํด์ผ ํจ
Canvas
ui ์์ฑ์ Canvas ์๋์์ฑ
Canvas(๋ํ์ง) 3D์ขํ์์ ์์น๊ฐ ์๋ ์ ์ ์๊ฒ ๋ณด์ฌ์ง๋ ์คํฌ๋ฆฐ์ ๋์ํ๋
Rect TransForm
TransForm์ ์์๋ฐ์(๋ถ๋ณ) (RENDER MODE - WORLD ๋ฉด ์์ ๊ฐ๋ฅ)
Anchors
UI Elemnet ์์ ์ ์ธํ ํ๋ ๊ธฐ์ค
์ต์ปค๊ฐ ๊ธฐ์ค์ผ๋ก pos x ,y ๊ฐ ์ ํด์ง๋ค.
์ต์ปค min,max ๋ค๋ฅผ ๋
Pivot
UI Elemnet ๋ด๋ถ ๊ธฐ์ค์ ์ ์ธํ ํ๋ ๊ธฐ์ค
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๋ฐ๊ฐ์
๋ฐ์ดํฐ ์ ์ฅ
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
๋๊ธ๋จ๊ธฐ๊ธฐ