카테고리 없음

0728 유니티(에디터 내 변경사항 Csv 자동 반영)

버스창문 2025. 7. 28. 17:58
IEnumerator Start () 
{
	Debug.Log("파일 생성중");
	if (System.IO.File.Exists("Assets/Resources/StatData.csv"))
	{
		Debug.Log("이미 있음");
		//기존에 있던 내용은 내용 수정
		//기존에 없던 내용은 내용 추가
		// id 활용해서 판단
		/*List<StatData> statDatas = new List<StatData>();
		var all = GameObject.FindObjectsOfType<Transform>(true);//모든 게임 오브젝트 다
		foreach(var go in all)
		{
			var scripts = go.gameObject.GetComponents<MonoBehaviour>();
			foreach(var script in scripts)
			{
				Type type = script.GetType();
				var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
                //bool hasInt = false;
                foreach (FieldInfo field in fields)
                {
                    if (field.FieldType == typeof(StatData))
                    {
						//StatData내용 받아오기
						
                    }
                }

            }
        }*/


		var targets = GameObject.FindObjectsOfType<CharTest>(true);
		Dictionary<int, StatData> datas = new Dictionary<int, StatData>();
		List<List<string>> modifiedTxt = new List<List<string>>();
		bool isChanged = false;
		foreach (CharTest t in targets)
		{
			datas.Add(t.data.id, t.data);
		}

		using (var csv = new StreamReader("Assets/Resources/StatData.csv"))
		{
			var txt = csv.ReadToEnd(); //내부 내용 다 읽어오는거 확인함
			var txtLine = txt.Split('\n'); // 줄 바꿈 기준으로 나눔
			for(int i = 0; i < 2; i++) //수정 버전에 초반부분 등록
			{
				var line = txtLine[i].Split(',');
                line[line.Length - 1] = line[line.Length - 1].Replace("\r", "");
                modifiedTxt.Add(line.ToList());
				/*for(int j = 0; j < line.Length; j++)
				{
                    modifiedTxt[i][j] = line[j];
                }*/
			}
			for(int i = 2; i < txtLine.Length - 1; i++) // 첫번째건 이름, 두번째건 자료형
			{
				var id = int.Parse(txtLine[i].Split(',')[0]); // 각 줄을 ,로 나눠서 첫번째 내용 -> id를 int로
				if (datas.ContainsKey(id)) // 이미 있었다면
				{
					isChanged = true;
					var data = datas[id];
					List<string> line = new List<string>();
					//txtLine[i] = $"{data.id},{data.Name},{data.Hp},{data.Exp},{data.Str},{data.Dex},{data.Con},{data.Int}";

					line.Add(data.id.ToString());
					line.Add(data.Name.ToString());
					line.Add(data.Level.ToString());
                    line.Add(data.Hp.ToString());
					line.Add(data.Exp.ToString());
					line.Add(data.Str.ToString());
					line.Add(data.Dex.ToString());
					line.Add(data.Con.ToString());
					line.Add(data.Int.ToString());
					
                    modifiedTxt.Add(line);
					datas.Remove(id);
                }
				else
				{
                    var line = txtLine[i].Split(',');
                    line[line.Length - 1] = line[line.Length - 1].Replace("\r", "");
                    modifiedTxt.Add(line.ToList());
                }
			}
		}
		if(datas.Count > 0)
		{
			isChanged = true;
			foreach (var Rdata in datas)
			{
                List<string> line = new List<string>();
				//txtLine[i] = $"{data.id},{data.Name},{data.Hp},{data.Exp},{data.Str},{data.Dex},{data.Con},{data.Int}";
				var data = Rdata.Value;
                line.Add(data.id.ToString());
                line.Add(data.Name.ToString());
                line.Add(data.Level.ToString());
                line.Add(data.Hp.ToString());
                line.Add(data.Exp.ToString());
                line.Add(data.Str.ToString());
                line.Add(data.Dex.ToString());
                line.Add(data.Con.ToString());
                line.Add(data.Int.ToString());

                modifiedTxt.Add(line);
            }
		}
		if (isChanged)
		{
            using (var writer = new CsvFileWriter("Assets/Resources/StatData.csv"))
            {
                //내용 추가하는 공간
                foreach (var txt in modifiedTxt)
                {
                    writer.WriteRow(txt);
                }

            }
        }
		
    }

CsvFileWriter의 WriteRow함수는 변수로 List<string>을 요구해서 저런 기형적인 Add난사가 나오게 됐다

 

 

현재 씬 내에 CharTest타입을 전부 가져와서

그 안에 있는 StatData에 대해서 현재 csv파일과 대조하고, id가 겹치는 값은 변경됐다고 간주해서 값을 변경시키고, 

그 외에는 그냥 그대로 내리거나, 아예 없던값은 추가한다.

 

위에 주석처리된 내용은 StatData를 변수로 가지고있는 스크립트들을 전부 확인해서 그 안에 StatData를 값으로 받아오려했는데,

확인하는것 까진 되는데 값을 받아오는걸 어떻게 해야할지 모르겠다.

 

 

 

 

 

+

수정

IEnumerator Start () 
{
	Debug.Log("파일 생성중");
	if (System.IO.File.Exists("Assets/Resources/StatData.csv"))
	{
		Debug.Log("이미 있음");
        //기존에 있던 내용은 내용 수정
        //기존에 없던 내용은 내용 추가
        // id 활용해서 판단
        Dictionary<int, StatData> statDatas = new Dictionary<int, StatData>();
		var all = GameObject.FindObjectsOfType<Transform>(true);//모든 게임 오브젝트 다
		foreach (var go in all)
		{
			var scripts = go.gameObject.GetComponents<MonoBehaviour>();
			foreach (var script in scripts)
			{
				Type type = script.GetType();
				var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				//bool hasInt = false;
				foreach (FieldInfo field in fields)
				{
					if (field.FieldType == typeof(StatData))
					{
						//StatData내용 받아오기
						StatData data = field.GetValue(script) as StatData;
						//Debug.Log(data.id);
						statDatas.Add(data.id, data);
                    }
				}

			}
		}

		List<List<string>> modifiedTxt = new List<List<string>>();
		bool isChanged = false;

		using (var csv = new StreamReader("Assets/Resources/StatData.csv"))
		{
			var txt = csv.ReadToEnd(); //내부 내용 다 읽어오는거 확인함
			var txtLine = txt.Split('\n'); // 줄 바꿈 기준으로 나눔
			for(int i = 0; i < 2; i++) //수정 버전에 초반부분 등록
			{
				var line = txtLine[i].Split(',');
                line[line.Length - 1] = line[line.Length - 1].Replace("\r", "");
                modifiedTxt.Add(line.ToList());
				/*for(int j = 0; j < line.Length; j++)
				{
                    modifiedTxt[i][j] = line[j];
                }*/
			}
			for(int i = 2; i < txtLine.Length - 1; i++) // 첫번째건 이름, 두번째건 자료형
			{
				var id = int.Parse(txtLine[i].Split(',')[0]); // 각 줄을 ,로 나눠서 첫번째 내용 -> id를 int로
				if (statDatas.ContainsKey(id)) // 이미 있었다면
				{
					isChanged = true;
					var data = statDatas[id];
					List<string> line = new List<string>();
					//txtLine[i] = $"{data.id},{data.Name},{data.Hp},{data.Exp},{data.Str},{data.Dex},{data.Con},{data.Int}";

					line.Add(data.id.ToString());
					line.Add(data.Name.ToString());
					line.Add(data.Level.ToString());
                    line.Add(data.Hp.ToString());
					line.Add(data.Exp.ToString());
					line.Add(data.Str.ToString());
					line.Add(data.Dex.ToString());
					line.Add(data.Con.ToString());
					line.Add(data.Int.ToString());
					
                    modifiedTxt.Add(line);
					statDatas.Remove(id);
                }
				else
				{
                    var line = txtLine[i].Split(',');
                    line[line.Length - 1] = line[line.Length - 1].Replace("\r", "");
                    modifiedTxt.Add(line.ToList());
                }
			}
		}
		if(statDatas.Count > 0)
		{
			isChanged = true;
			foreach (var Rdata in statDatas)
			{
                List<string> line = new List<string>();
				//txtLine[i] = $"{data.id},{data.Name},{data.Hp},{data.Exp},{data.Str},{data.Dex},{data.Con},{data.Int}";
				var data = Rdata.Value;
                line.Add(data.id.ToString());
                line.Add(data.Name.ToString());
                line.Add(data.Level.ToString());
                line.Add(data.Hp.ToString());
                line.Add(data.Exp.ToString());
                line.Add(data.Str.ToString());
                line.Add(data.Dex.ToString());
                line.Add(data.Con.ToString());
                line.Add(data.Int.ToString());

                modifiedTxt.Add(line);
            }
		}
		if (isChanged)
		{
            using (var writer = new CsvFileWriter("Assets/Resources/StatData.csv"))
            {
                //내용 추가하는 공간
                foreach (var txt in modifiedTxt)
                {
                    writer.WriteRow(txt);
                }

            }
        }
		
    }

GetValue(script) as StatData를 하면 안에 다른 내용이 있더라도 정확히 StatData의 내용만 불러와진다.

그렇게 주석처리 되어있던걸 해결했다.

 

 

+

추가

IEnumerator Start () 
{
	Debug.Log("파일 생성중");
	if (System.IO.File.Exists("Assets/Resources/StatData.csv"))
	{
		Debug.Log("이미 있음");
        //기존에 있던 내용은 내용 수정
        //기존에 없던 내용은 내용 추가
        // id 활용해서 판단

        // 1) StatData 타입 검색 (문자열 기반)
        var statDataType = AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(a => a.GetTypes())
            .FirstOrDefault(t => t.Name == "StatData");

        // 2) 타입이 없으면 스킵
        if (statDataType == null)
        {
            Debug.LogWarning("StatData 클래스가 정의되지 않아 처리하지 않습니다.");
            yield break;
        }



        Dictionary<int, dynamic> statDatas = new Dictionary<int, dynamic>();
		var all = GameObject.FindObjectsOfType<Transform>(true);//모든 게임 오브젝트 다
		foreach (var go in all)
		{
			var scripts = go.gameObject.GetComponents<MonoBehaviour>();
			foreach (var script in scripts)
			{
				Type type = script.GetType();
				var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				//bool hasInt = false;
				foreach (FieldInfo field in fields)
				{
					if (field.FieldType == statDataType)
					{
						//StatData내용 받아오기
						var data = field.GetValue(script);
                        var idField = statDataType.GetField("id",
                BindingFlags.Instance | BindingFlags.Public);
						int idValue = (int)idField.GetValue(data);


                        //Debug.Log(data.id);
                        statDatas.Add(idValue, data);
                    }
				}

			}
		}

		List<List<string>> modifiedTxt = new List<List<string>>();
		bool isChanged = false;

		using (var csv = new StreamReader("Assets/Resources/StatData.csv"))
		{
			var txt = csv.ReadToEnd(); //내부 내용 다 읽어오는거 확인함
			var txtLine = txt.Split('\n'); // 줄 바꿈 기준으로 나눔
			for(int i = 0; i < 2; i++) //수정 버전에 초반부분 등록
			{
				var line = txtLine[i].Split(',');
                line[line.Length - 1] = line[line.Length - 1].Replace("\r", "");
                modifiedTxt.Add(line.ToList());
				/*for(int j = 0; j < line.Length; j++)
				{
                    modifiedTxt[i][j] = line[j];
                }*/
			}
			for(int i = 2; i < txtLine.Length - 1; i++) // 첫번째건 이름, 두번째건 자료형
			{
				var id = int.Parse(txtLine[i].Split(',')[0]); // 각 줄을 ,로 나눠서 첫번째 내용 -> id를 int로
				if (statDatas.ContainsKey(id)) // 이미 있었다면
				{
					isChanged = true;
					var data = statDatas[id];
					List<string> line = new List<string>();
					//txtLine[i] = $"{data.id},{data.Name},{data.Hp},{data.Exp},{data.Str},{data.Dex},{data.Con},{data.Int}";

					line.Add(data.id.ToString());
					line.Add(data.Name.ToString());
					line.Add(data.Level.ToString());
                    line.Add(data.Hp.ToString());
					line.Add(data.Exp.ToString());
					line.Add(data.Str.ToString());
					line.Add(data.Dex.ToString());
					line.Add(data.Con.ToString());
					line.Add(data.Int.ToString());
					
                    modifiedTxt.Add(line);
					statDatas.Remove(id);
                }
				else
				{
                    var line = txtLine[i].Split(',');
                    line[line.Length - 1] = line[line.Length - 1].Replace("\r", "");
                    modifiedTxt.Add(line.ToList());
                }
			}
		}
		if(statDatas.Count > 0)
		{
			isChanged = true;
			foreach (var Rdata in statDatas)
			{
                List<string> line = new List<string>();
				//txtLine[i] = $"{data.id},{data.Name},{data.Hp},{data.Exp},{data.Str},{data.Dex},{data.Con},{data.Int}";
				var data = Rdata.Value;
                line.Add(data.id.ToString());
                line.Add(data.Name.ToString());
                line.Add(data.Level.ToString());
                line.Add(data.Hp.ToString());
                line.Add(data.Exp.ToString());
                line.Add(data.Str.ToString());
                line.Add(data.Dex.ToString());
                line.Add(data.Con.ToString());
                line.Add(data.Int.ToString());

                modifiedTxt.Add(line);
            }
		}
		if (isChanged)
		{
            using (var writer = new CsvFileWriter("Assets/Resources/StatData.csv"))
            {
                //내용 추가하는 공간
                foreach (var txt in modifiedTxt)
                {
                    writer.WriteRow(txt);
                }

            }
        }
		
    }

 

StatData로 선언되어있던 내용을

Dynamic과 Reflection을 이용하여 해결했다

Reflection에 대해 아는 내용이 많이 없어 자세하겐 모르겠다.

 

 

1.

var statDataType = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(a => a.GetTypes())
    .FirstOrDefault(t => t.Name == "StatData");

 

SelectMany는 배열 형태라면 쓸 수 있는 함수이다. 매개변수로는 Func를 받는다

이후 내일 정리

 


해당 내용은 그냥 유니티 기본 세팅으로 안되고

 

project Setting -> Player에서 api수준을 바꿔놔야한다