파일 경로
- 상대적 파일 경로 지정
string filePath = "yammySnack.txt";
- 절대적 파일 경로 지정
/(슬래시), \\(백슬래시), @\ 를 이용한다
string filePath = "C:/yammySnack.txt";
string filePath = "C:\\yammySnack.txt";
string filePath = @"C:\yammySnack.txt";
파일 쓰기
배열을 이용하여 파일에 쓸 문자열 저장하고,
File.WriteAllLines 를 이용하여 작성한 배열을 파일에 작성한다.
// 파일 생성 경로 정의
string filePath = "yammySnack.txt";
// 파일에 쓰여질 문자열 배열 정의
string[] lines = { "First line", "Second line", "Third line" };
// 문자열 배열을 "yammySnack.txt"라는 새 파일에 씀.
// 파일이 이미 존재하는 경우 덮어씀
File.WriteAllLines(filePath, lines);
Console.WriteLine("File written successfully.");
파일 읽기
1) ReadAllLines 사용
File.Exists() 로 파일의 유무를 판단한다.
File.ReadAllLines() 로 문자열 모두 읽는다.
string filePath = "yammySnack.txt";
// 파일이 있는지 확인
if (File.Exists(filePath))
{
// 파일의 모든 줄을 문자열 배열로 읽어들임
string[] lines = File.ReadAllLines(filePath);
// 배열의 각 줄을 순회하며 콘솔에 출력
foreach (string line in lines)
{
// 읽어 온 파일 출력
Console.WriteLine(line);
}
}
else
{
Console.WriteLine("File not Found");
}
2) StreamReader 클래스 사용
using을 이용하여 StreamReader를 인스턴스화 하고
StreamReader의 함수 ReadLine()를 이용하여 한 줄씩 읽어온다.
● using: 괄호 내에서만 사용할 수 있겠끔 하는 키워드. 일회성으로 사용할 때 쓰인다.
● StreamReader: 파일을 읽는데 최적화 된 클래스
string filePath = "yummySnack.txt";
// 파일이 있는지 확인
if (File.Exists(filePath))
{
// 파일 한 줄씩 Read
using (StreamReader streamReader = new StreamReader(filePath))
{
// 파일 한 줄을 읽어옴
string line = streamReader.ReadLine();
while (line != null)
{
// 읽어 온 파일 출력
Console.WriteLine(line);
// 그 다음 라인 읽어옴
line = streamReader.ReadLine();
}
}
}
else
{
Console.WriteLine();
}
파일 추가 쓰기
1) 단일 텍스트 추가
AppendAllText(파일, 추가할 글) 함수를 사용하여 텍스트를 추가한다.
string filePath = "yammySnack.txt";
string newLine = "Fourth line";
// filePath에다가 newLine 데이터를 넣어라.
File.AppendAllText(filePath, newLine);
Console.WriteLine("Success sppend Line");
2) 여러 문자열 추가
AppendAllLines(파일, 추가할 글) 함수를 사용하여 문자열을 추가한다.
string filePath = "example.txt";
string[] newLine = { "Fourth line", "5", "6" };
// filePath에다가 newLine 데이터를 넣어라.
File.AppendAllLines(filePath, newLine);
Console.WriteLine("Success sppend Line");
++변수 와 변수++ 의 차이
● 변수++ : 함수의 argument에 넣은 후 1만큼 증가시키겠다.
● ++변수 : 1만큼 증가시킨 다음에 함수의 argument에 전달하겠다.
int idx1 = 0, idx2 = 0;
Console.WriteLine(idx1);
Console.WriteLine(idx2);
Console.WriteLine(idx1++); // 0
Console.WriteLine(++idx2); // 1
int idx1Result = 0, idx2Result = 0;
idx1Result = idx1++;
idx2Result = ++idx2;
Console.WriteLine(idx1Result.ToString() + " " + idx1.ToString()); // 1 2
Console.WriteLine(idx2Result.ToString() + " " + idx2.ToString()); // 2 2
위와 같이 ++이 뒤에 있는 경우, 원래의 변수와 같은 값을 가지고
++이 앞에 있는 경우, 원래의 변수에 1이 커진 값을 가진다.
보석 먹기 게임 구현
① 에셋 스토어에서 마음에 드는 보석, 오디오, 이펙트 에셋을 다운받는다.
② 보석의 프리팹을 복사하여 Hierarchy에 드래그 앤 드롭 한다.
③ 보석 오브젝트에 Sphere Collider를 추가 후 Is Trigger를 체크한다.

Trigger란?
: 콜라이더와 콜라이더끼리 부딪혔을 때 물리작용은 일어나지 않지만, 상호작용은 하는 충돌체를 말한다.
④ 앞 시간에 했던 것처럼 Tag에 Jewelry 태그를 추가한 후 보석 오브젝트에 등록한다.
⑤ PlayerController 스크립트에서 OnTriggerEnter() 함수를 선언한 후,
"Jewlry" 태그를 가진 오브젝트와 충돌할 시 로그를 띄우게 한다.
// 충돌체가 본인 콜라이더에 들어왔을 때
private void OnTriggerEnter(Collider other)
{
// 충돌체가 "Jewelry" 태그를 가지고 있으면
if (other.gameObject.CompareTag("Jewelry"))
{
Debug.Log("보석 먹음");
}
}
=> 플레이어가 보석에 닿을 경우, 로그가 나타난다.
⑥ 사용할 이펙트 프리팹에 Audio Source 컴포넌트를 추가하고, AudioClip에 원하는 오디오 소스를 드래그 앤 드롭한다.

⑦ 이펙트 스크립트를 만들어 보석 오브젝트에 컴포넌트로 추가한다.
⑧ 이펙트 스크립트에서 GameObject 타입의 변수 'HitEffect'를 public으로 선언한다.
⑨ 함수를 선언하여 보석 오브젝트의 위치에 이펙트가 나타나게 하기 위해 'HitEffect'를 인스턴스화하고,
Destroy() 함수로 현재 본인의 오브젝트를 삭제한다.
// 내 오브젝트가 사라질 때 나타날 효과
public GameObject HitEffect;
public void OnHit()
{
// 내 오브젝트가 있는 곳에 HitEffect 게임 오브젝트를 스폰
GameObject.Instantiate(HitEffect, this.transform.position, Quaternion.identity);
// 내 오브젝트 삭제
GameObject.Destroy(this.gameObject);
}
Instantiate란?
: 유니티식 메모리 할당. 프리팹을 복제할 때 주로 쓰인다.
⑩ 유니티 창에서 주얼리의 이펙트 스크립트 컴포넌트의 "Hit Effect"에 해당 이펙트 프리팹을 드래그 앤 드롭한다.
결과

캐릭터가 보석을 먹으면 이펙트와 함께 소리가 나는 것을 확인할 수 있다.
LINQ(링큐)
Language Integrated Query
: C#에서 데이터를 쿼리하고 조작할 수 있게 해주는 문법
한 마디로, 데이터를 정리하는 기능이다.
중요 메서드
● From : 원하는 데이터에서 요소 추출
● Where : 조건을 만족하는 요소 필터링
● Select : 컬렉션의 각 요소를 특정 형식으로 변환
● OrderBy, OrderByDescending : 컬렉션 정렬
● GroupBy : 컬렉션의 요소를 그룹화
● Sum, Max, Min, Average : 집계 함수
등등이 있다.
예시
짝수를 골라내는 코드
● 일반적인 방식
// 데이터 모음집
List<int> nums = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var oddNumbers = new List<int>();
foreach (var num in oddNumbers)
{
if (num % 2 != 0)
{
Console.WriteLine(num);
}
}
● 링큐 적용 방식
foreach문보다 직관적이다.
데이터 생성이 많아서 foreach문보다 조금 느리다.
// 데이터 모음집
List<int> nums = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var oddNumbers = new List<int>();
// 짝수만 골라내고 싶을 때
var evenNumbers = from num in nums // nums에서 요소들 뽑아와
where num % 2 == 0 // 짝수인 애들
select num; // 반환해
Console.WriteLine("Even numbers : ");
foreach (var num in evenNumbers) Console.WriteLine(num);
● 링큐 함수 적용 방식
일반 링큐와 기능상의 차이는 없다.
가독성의 차이
// 데이터 모음집
List<int> nums = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var evenNumbers = nums.Where(e => e % 2 == 0).Select(e => e);
// 기능상 같음. 가독성의 차이
Console.WriteLine("Even numbers : ");
foreach (var num in evenNumbers) Console.WriteLine(num);
● GroupBy
1) group by 쿼리 구문
List<Student> students = new List<Student>();
// List에 키 넣음
students.Add(new Student { Id = 1, Name = "Sumi", Age = 23 });
students.Add(new Student { Id = 1, Name = "Suman", Age = 23 });
students.Add(new Student { Id = 2, Name = "Sumi2", Age = 18 });
students.Add(new Student { Id = 2, Name = "Suman2", Age = 18 });
students.Add(new Student { Id = 3, Name = "Sumi3", Age = 50 });
// 'group by' 쿼리 구문
var result = from student in students
// student.Id 를 기준으로 students 컬렉션 그룹화
group student by student.Id;
foreach (var item in result)
{
Console.Write(item.Key);
foreach (var item1 in item)
{
// \t 탭 문자
Console.WriteLine("\t {0}", item1.Name);
}
}
2) GroupBy 함수 구문
List<Student> students = new List<Student>();
// List에 키 넣음
students.Add(new Student { Id = 1, Name = "Sumi", Age = 23 });
students.Add(new Student { Id = 1, Name = "Suman", Age = 23 });
students.Add(new Student { Id = 2, Name = "Sumi2", Age = 18 });
students.Add(new Student { Id = 2, Name = "Suman2", Age = 18 });
students.Add(new Student { Id = 3, Name = "Sumi3", Age = 50 });
var groups = students.GroupBy(e => e.Id);
foreach (var group in groups)
{
Console.WriteLine(group.Key);
foreach (var item in group)
{
// \t : 탭 문자
Console.WriteLine("\t {0}", item.Name);
}
}
Collection(컬렉션)
데이터를 그룹으로 관리한 것
Array(배열)
- 추가 삽입 삭제 불가능
- 수정 콜렉션 중 제일 빠름
- '수정하면 안되는 그룹' 이라고 명시할 때 쓰임
int[] arr = { 1, 2, 3 };
// 수정 가능
arr[1] = 5;
// 추가 삽입 삭제 불가능
// arr.Append(5); (X)
Console.WriteLine(arr);
List(리스트)
- 배열의 확장판
- 추가 삽입 삭제 가능
List<int> nums = new List<int> { 1, 2, 3 };
// 삭제 가능
nums.RemoveAt(2);
foreach (var num in nums) Console.WriteLine();
// 추가 가능
nums.Add(4);
foreach (var num in nums) Console.WriteLine();
ArrayList
- 고정되지 않음
- 추가 삭제 가능
- 여러 타입의 데이터 저장 가능
- 다른 언어끼리 메모리 교환할 때 나타나는 박싱, 언박싱 발생 => 메모리에 부담 많이 준다
Dictionary(딕셔너리)
- 인덱스 번호를 대신해 사용하는 Key와 키가 가지는 값 Value를 세트로 다루는 배열
Dictionary<string, int> dic = new Dictionary<string, int>();
// 키와 키에 대한 밸류를 가짐
dic["단검"] = 1;
dic["장검"] = 2;
dic["도끼"] = 3;
dic["채찍"] = 4;
foreach (var item in dic) Console.WriteLine(item);
// 원하는 값을 찾을 수 있는 key 값을 이용하여
// 순차적으로 탐색하지 않고 원하는 value값을 바로 찾을 수 있음.
string keyToFind = "단검";
// TryGetValue 사용
if (dic.TryGetValue(keyToFind, out int value))
Console.WriteLine($"키 {keyToFind}에 해당하는 값 : {value}");
else
Console.WriteLine($"키 {keyToFind}가 딕셔너리에 없음.");
// 키 직접 접근
if (dic.ContainsKey(keyToFind))
{
int valueDirect = dic[keyToFind];
Console.WriteLine($"키 {keyToFind}에 해당하는 값 : {valueDirect}");
}
else
Console.WriteLine($"키 {keyToFind}가 딕셔너리에 없음.");
=> 강사님은 List와 Dictionary 를 추천하셨다!
아이템에 이펙트는 처음 붙여보았는데, 이펙트 내에 소리를 넣고
아이템에 이펙트 스크립트를 넣어 본인을 Distroy 한다는 것이 새로웠다.
이 방식을 익혀놓아야겠다.
링큐를 접하면서 개발자들이 상당히 많이 쓰는 문법이라는 것을 알았다.
아직 익숙지 않고 어렵지만, 반복해서 나의 것으로 만들어야겠다.
'부트캠프' 카테고리의 다른 글
[멋쟁이사자처럼 유니티 TIL] 대리자(delegate)와 이벤트 실습, 공격 모션 구현 (+ (Ctrl + H), 리타겟팅) (1) | 2024.06.12 |
---|---|
[멋쟁이사자처럼 유니티 TIL] node.js을 통한 비동기 서버 구축 구현 (+ 서버 구축 관련 용어 정리, 벡터와 라디안으로 회전 구현, 비동기 프로그래밍) (0) | 2024.06.08 |
[멋쟁이사자처럼 유니티 TIL] 에셋을 통한 애니메이션 구현과 비동기 프로그래밍(코루틴, async, await) (1) | 2024.06.05 |
[멋쟁이사자처럼 유니티 TIL] 회전 및 점프 구현(+FixedUpdate와 Update의 차이) (0) | 2024.06.03 |
[c#] 별 찍기 + 피라미드, 역피라미드, 왼쪽/오른쪽 화살표 (0) | 2024.05.29 |