Boxing 과 Unboxing
형변환 할때 주로 변환한다.
Boxing 이란 값을 참조 형태로 바꾸는
Unboxig 이란 참조하는 것을값 형태로 바꾸는 기법이라고 하는데,
어떠한 오브젝트를 쓰려고 가져왔는데, 오브젝트 자체를 쓰진 못하니 사용할 수 있게,
강제로 형변환을 해야한다.
자세히 한번 알아봅시다 ! 중요하다고 한다.
Delegate ( 대리자 )
Delegate 라는 것은 함수의 이름을 변경하여 호출하는 형태,
선언형식 : delegae 반환값 함수이름 ( 매개변수 )
함수 포인터 라고 생각하면 된다.
Sum 이란 함수가 있다.
Func 라는 곳에 Sum 의 주소를 담는다면 앞으로
Func( ) 을 호출하면 결국은 Sum 이 호출된다.
※ 괄호 열고 닫고는 호출한다는 의미이고, 괄호가 없는 것은 그냥 주소를 담는다는 뜻이다.
※ GOF : 디자인 패턴 : 예를 들면 싱글턴, 상태패턴 같은 것
※ 상태패턴 : STATE 라는 변수하나르 두고, 여러 상태들 ( 로딩, 로고, 타이틀, 옵션 등등 ) 을 관리이를 원래 Switch 를 통해 관리하여야하지만, Delegate 를 사용한다면 상태가바뀔때마다, Delegate의 대입만 바꿔주면 된다.
※ FSM : 유한상태머신 : 로고 타이틀 왓닸다하는 것 등 제한된 상태에서 왔다갔다하는 것
----------------------------------------------------------------------------------------------------------
Action ( 대리자와 거의 같다. )
Delegate 를 편리하게 호출하기 위해 미리 선언해 노흔 방식
Action : 반환형이 없는 대리자
System.Action 대리자 이름 ;
System.Action<Type> 대리자 이름
----------------------------------------------------------------------------------------------------------
Event ( 대리자와 거의 같다. )
특정 시점에 함수를 연결하여 호출하거나 연결을 해제하여 호출을 중지 시킬 수 있는 메시지 함수.
선언형식 : event 대리자( or Action ) 이벤트이름
구독자 패턴 / 관찰자 패턴 / 옵저버 패턴 이라고도 부름
신문 구독을 생각하자 구독자가 있으면 매번 같은시간 신문주고 구도자 없으면 아무일도 안하면 된다 !
만약 저 MyEvent += Pring 를 10번 반복하고나서 Start 에서 저렇게 호출하면 Print 가 10번 호출된다고 함.
일반적으로 Event 에 1개만 넣어서 사용한다.
----------------------------------------------------------------------------------------------------------
재미있는 예제 // 클래스 포인터에 관하여
Class A {
void Print( ){
cout << "Hello World" ;
}
}
A *pt = NULL ;
pt -> print( ) ;
오류가 일어나지 않고잘 돌아간다. !
Class A {
int a ;
void Print( ){
cout << "Hello World" ;
++a ;
}
}
A *pt = NULL ;
pt -> print( ) ;
Hello World 가 출력된 다음 오류가 일어나다. 왜? a는 존재하지 않는다.
생각해보자 포인터가 NULL 을 가리키고는 있지마 이미 print 라는 함수는 메모리 어딘가에 존재 하는 것이다.
그렇다면 두번째 예제는 왜 오류인가? a 에 접근하려 했지만 a는 메모리 상에 존재하지 않기 때문이다.
----------------------------------------------------------------------------------------------------------
파일 출력 ( 쓰기 )
using Sysem.IO ;
FileStream 변수명(File) = new FileStream( 경로 , FileMode.Create ) ;
파일에 이제 무언가 써내려가고 싶을때
TextWriter 변수명(Writer) = new StreamWriter( 위의 File ) ;
Writer.Write( " 쓰고싶은말 " ) ;
파일을 이제 다을때
파일을 열어서 무언가를 했다면 반드시 반드시 닫아야한다.
Writer.Close( );
※ 만약 파일이 안생길때 using UnityEditor 추가하고 AssetDatabase.Refresh( ) ; 를 마지막 줄에 추가해주면 된다.
----------------------------------------------------------------------------------------------------------
파일 입력 ( 읽기 )
파일을 읽어올때에는 쓰기 부분과 비슷하되 몇군데가 다르다.
주의 해야할 부분은 FileMode.Open 이라는 것과 기존의 TextWriter 였던 것이 TextReader 로 바뀌었다는 것이다.
그리고 이 C# 에서 파일 입출력을 할때에는 앞으로 꼭! 텍스트 파일 첫줄이라던가 매 줄이라던가에 숫자를 통해서 몇줄을 읽어야 하는지 혹으 이 줄이 몇 어절 로 이루어져 있는지 힌트를 주는것이 편하다는 것이다 !!'
만약 텍스트 파일에
3
A
B
C
라고 넣었다면, 읽을 때에는
TextReader txtReader = new StreamReader(fs);
int cnt = int.Parse(txtReader.ReadLine());
string txt = "";
for (int a = 0; a < cnt; ++a)
{
txt += txtReader.ReadLine() + "\n";
}
이런식으로 3줄을 읽어 올수 있다.
그리고 위 사진에서 맨 마지막을 보라 기존 쓰기(입력) 과정에선 TextWriter 만 닫았지만 출력(읽기) 과정에서는
파일을 열었던 fs 자체도 닫아주고 있다. 다른 문제 발생이 생기는 것을 막기위해서 이다.
----------------------------------------------------------------------------------------------------------
연습한 코드
using UnityEngine;
using System.Collections; using System.IO; using UnityEditor;
public class IOstream : MonoBehaviour {
class PlayerInfo { public string name; public string job; public int HP; public int MP; public int STR; public int DEX; public int INT; } // Use this for initialization void Start () { SaveTextFile(); LoadTextFile(); //"C:/Users/User/Documents/VR" }
// Update is called once per frame void Update () { } void SaveTextFile() { string dataPath = Application.dataPath + "/Resources/"; string filename = "myTxt.txt";
// 파일 열기 FileStream fs = new FileStream( dataPath + filename , FileMode.Create); Debug.Log(" 파일 주소 : " + dataPath);
// 파일 출력 TextWriter txtWriter = new StreamWriter(fs); txtWriter.Write("3\nSteve Jobs, Warrior, 650, 50,69,25,17\n" + "Bill Gates, Magician, 350, 450, 27, 19,82\n" + "Lee Gun Hee, Archer, 450,250,35,60,30");
//파일 닫기 txtWriter.Close(); // 파일을 열어서 무언갈 했으면 반드시 닫아줘야 한다. AssetDatabase.Refresh(); // }
void LoadTextFile() { string dataPath = Application.dataPath + "/Resources/"; string filename = "myTxt.txt";
// 파일 열기 FileStream fs = new FileStream(dataPath + filename, FileMode.Open);
// 파일 출력 TextReader txtReader = new StreamReader(fs); int cnt = int.Parse(txtReader.ReadLine()); string txt = ""; string[] result = new string[cnt]; PlayerInfo[] player = new PlayerInfo[cnt];
for (int a = 0; a < cnt; ++a) { txt = txtReader.ReadLine(); string[] sprite = txt.Split(','); player[a] = new PlayerInfo(); player[a].name = sprite[0].Trim(); player[a].job = sprite[1].Trim(); player[a].HP = int.Parse(sprite[2].Trim()); player[a].MP = int.Parse(sprite[3].Trim()); player[a].STR = int.Parse(sprite[4].Trim()); player[a].DEX = int.Parse(sprite[5].Trim()); player[a].INT = int.Parse(sprite[6].Trim()); }
for (int a = 0; a < cnt; ++a) { result[a] += player[a].name + " " + player[a].job + " " + player[a].HP+ " " + player[a].MP+ " " + player[a].STR+ " " + player[a].DEX + " " + player[a].INT + " " ; } Debug.Log(result[0]); Debug.Log(result[1]); Debug.Log(result[2]); //파일 닫기 txtReader.Close(); // 파일을 열어서 무언갈 했으면 반드시 닫아줘야 한다. fs.Close(); // 읽을경우는 이것까지 닫아줘야한다. AssetDatabase.Refresh(); //
} } |
----------------------------------------------------------------------------------------------------------
실제 출시할때 바뀌어야할 코드
왜 ? 어떤 OS에 팔릴지 모르고, OS 마다 접근권한이 다를수있기 때문 바뀐 Load 함수
void LoadTextFile_Finish()
{
// 유니티 상에서
string filename = "myTxt2.txt";
// 파일 열기
TextAsset asset = (TextAsset)Resources.Load(filename, typeof(TextAsset));
TextReader textReader2 = new StringReader(asset.text);
// 파일 출력
int cnt = int.Parse(textReader2.ReadLine());
string txt = "";
string[] result = new string[cnt];
PlayerInfo[] player = new PlayerInfo[cnt];
for (int a = 0; a < cnt; ++a)
{
txt = textReader2.ReadLine();
Debug.Log(txt);
string[] sprite = txt.Split(',');
foreach (string b in sprite)
{
Debug.Log(b);
}
player[a] = new PlayerInfo();
player[a].name = sprite[0].Trim();
player[a].job = sprite[1].Trim();
player[a].HP = int.Parse(sprite[2].Trim());
player[a].MP = int.Parse(sprite[3].Trim());
player[a].STR = int.Parse(sprite[4].Trim());
player[a].DEX = int.Parse(sprite[5].Trim());
player[a].INT = int.Parse(sprite[6].Trim());
}
for (int a = 0; a < cnt; ++a)
{
result[a] += player[a].name + " " + player[a].job +
" " + player[a].HP + " " + player[a].MP + " "
+ player[a].STR + " " + player[a].DEX + " "
+ player[a].INT + " ";
}
Debug.Log(result[0]);
Debug.Log(result[1]);
Debug.Log(result[2]);
//파일 닫기
textReader2.Close(); // 이것만 닫으면 된다 filestream 을 사용안하기때문
AssetDatabase.Refresh(); //
}
※ CSV 파일( comma-separated values ) , ( 컴마 ) 로 구분지어 지는 파일
엑셀에서 열리는 Text 파일이므로 많이 쓰인다고함
내가 위에서 재미로 만들었던 캐릭터 3명의 정보 파일이 확장하는 txt 이지만 사실상 CSV 파일이다.
----------------------------------------------------------------------------------------------------------
Binary 파일
바이너리를 사용해야하는 이유
- 텍스트 파일은 쓸데없는 정보가 너무 많다 !
- 용량이 훨씬 작다.
- 텍스트 파일은 그냥 읽어 올수가 없다.
- 바이너리는 그냥 읽어온다.
- 어느정도의 암호화
자료형 상과없이 Write 를 사용하면된다.
TextWriter -> BinaryWriter
그리고 저장단계에서 확장자가 bytes 혹은 byte 로 해야한다.
바꾼 두 함수 코드
void SaveBinaryFile() // 바이너리 파일로 저장
{
string dataPath = Application.dataPath + "/Resources/";
string filename = "MyBinaryTxt.bytes";
// 파일 열기
FileStream fs = new FileStream(dataPath + filename, FileMode.Create);
Debug.Log(" 파일 주소 : " + dataPath);
// 파일 출력
BinaryWriter txtWriter = new BinaryWriter(fs);
txtWriter.Write(3);
txtWriter.Write("Steve AAA");
txtWriter.Write("Warrior");
txtWriter.Write(650);
txtWriter.Write(50);
txtWriter.Write(69);
txtWriter.Write(25);
txtWriter.Write(17);
txtWriter.Write("Bill BBB");
txtWriter.Write("Magician");
txtWriter.Write(350);
txtWriter.Write(450);
txtWriter.Write(27);
txtWriter.Write(19);
txtWriter.Write(82);
txtWriter.Write("Lee CCC");
txtWriter.Write("Archer");
txtWriter.Write(450);
txtWriter.Write(250);
txtWriter.Write(35);
txtWriter.Write(60);
txtWriter.Write(30);
//파일 닫기
txtWriter.Close(); // 파일을 열어서 무언갈 했으면 반드시 닫아줘야 한다.
}
============================================================
void LoadBinaryFile_Developing() // 바이너리파일 읽어오기
{
string dataPath = Application.dataPath + "/Resources/";
string filename = "MyBinaryTxt.bytes";
// 파일 열기
FileStream fs = new FileStream(dataPath + filename, FileMode.Open);
// 파일 출력
BinaryReader txtReader = new BinaryReader(fs);
int cnt = txtReader.ReadInt32();
string txt = "";
string[] result = new string[cnt];
PlayerInfo[] player = new PlayerInfo[cnt];
for (int a = 0; a < cnt; ++a)
{
player[a] = new PlayerInfo();
player[a].name = txtReader.ReadString();
player[a].job = txtReader.ReadString();
player[a].HP = txtReader.ReadInt32();
player[a].MP = txtReader.ReadInt32();
player[a].STR = txtReader.ReadInt32();
player[a].DEX = txtReader.ReadInt32();
player[a].INT = txtReader.ReadInt32();
}
for (int a = 0; a < cnt; ++a)
{
result[a] += player[a].name + " " + player[a].job +
" " + player[a].HP + " " + player[a].MP + " "
+ player[a].STR + " " + player[a].DEX + " "
+ player[a].INT + " ";
}
Debug.Log(result[0]);
Debug.Log(result[1]);
Debug.Log(result[2]);
//파일 닫기
txtReader.Close(); // 파일을 열어서 무언갈 했으면 반드시 닫아줘야 한다.
fs.Close(); // 읽을경우는 이것까지 닫아줘야한다.
AssetDatabase.Refresh(); //
}