목록프로그래밍/UnityEngine기초 (21)
有希
이동 Directional Light: 태양처럼 한 방향으로만 빛을 쏜다. 위치는 관계없음. 회전각과 빛을 쏘는 방향이 중요함. Point Light: sphere로 된 범위 안에서 빛을 밝혀줌. 횃불 같은 느낌 spot ligth: 무대에서 쓰는 그 스포트라이트 ㅇ light 연산은 연산량이 어마어마함. 한 픽셀당 연산을 해서 빛이 적용된 색을 적용해서 수학식을 통해서 최종 색이 나옴. 빛 연산 모드를 baked를 하면 미리 다 연산해놓고 덮어놓겠다. mixed는 baked랑 realtime 섞. mixed? 좀 이상한게 어디서 어떻게 움직일지 알고 baked를 같이 쓴다는 걸가? 결론은 못한다. 다만 벽 같이 움직이지 않는 녀석에 대해서 미리 계산을 해두는 것임. static이 체크되어 있으면 bak..
레벨별 스탯 수치 같은 데이터, 레벨별 다음 레벨로 넘어가기 위한 경험치 등… 수치와 관련된 것들. 혹은 던전의 패턴이나, 몬스터의 AI 등을 모두 데이터로 관리한다. 왜? 사용하는가? 디자이너나 기획파트에서 hp를 수정하고 싶다거나 그럴 때, 코드로 박아놓으면 그 부분을 모두 바꿔야 함. 혹은 하드코딩된 수치들은 exe파일에 묶여서 들어간다. 만약 밸런스가 너무 안맞아서 긴급 업데이트를 하고 싶다 그러면 배포를 다시 해서 바이너리가 다시 나가서 앱스토어에 다시 배포를 해야하는 문제가 발생한다. 보통 JSON이나 xml파일로 관리하게 됨. 이런 경우엔 패치하게 되면 웹으로 접근해서 xml이나 JSON파일만 수정하면 됨. 데이터의 경우에는 항상 들고있어야 하므로 clear는 하지 않는다. 데이터 요즘에는 ..
연산이 오래 엄청 걸리는 작업을 하나의 함수에서 다 하면 문제가 생길 수 있다. 어떤 함수를 일시정지 시켰다가 모든 값을 복원해서 다시 함수를 시작하는 것. C#에서는 지원하지만 C++에서는 지원하지 않음. :Ienumerable을 붙여줘서 GetEnumerator를 구현해주어야 한다. Return 시에는 yield return을 해줘야 한다. 이 때 int를 넣어서 반환해도 실제 반환은 박싱해서 Integer(object)로 반환한다. 그래서 반환값을 쓸 때에는 (T)로 원하는 타입으로 캐스팅 해줘야 한다. Return을 여러 번 해서 값을 계속 뱉을 수 있다. Yield return null을 하면 일시정지이고(그럼 해당 루프를 빠져나와서 호출한 쪽으로 돌아간다. 그럼 이제 호출한 쪽에서 다시 실행할..
성능최적화 관련 기법. Pooling: 어딘가에 저장되어 있는 리소스를 메모리에 올려놓고, 이것을 인스턴스화 하는 것이 어마어마하게 느리다. 필요할 때 마다 하나씩 긁어와서 배치하는 것은 너무 느려서 이것을 개선해야 한다. 당장 필요없어도 곧 필요할 것이니 계속 어딘가에 상주시켰다가 필요할 때 쓰는 것. 재사용의 개념 정도? 커피 일회용컵 재사용 하는 느낌… 코드 상에서 Load를 해서 GameObject로 저장한 상태에서는 ssd에서 긁어와 메모리에 적재한 상태이고, Object.Instanciate하면 인스턴스화 한 것이다. 풀매니저를 만들고, 모든 풀들의 부모인 _root를 생성한다(게임오브젝트나 트랜스폼으로) 이 녀석은 Dontdetroyonload로. 풀 매니저는 dic으로 여러 개의 풀들을 갖..
//MP3 Player -> AudioSource(소리를 발생), 음원->AudioClip, 듣는사람->AudioListener Player가 음원을 재생하면 듣는사람이 이걸 듣는다(소리가 나온다). 한 씬에 하나만 리스너가 있으면 됨. Audio를 알아서 삭제되게 하고 싶으면, float을 하나 선언한 뒤, 이를 Destroy에 넣어줘 float시간 이후 알아서 삭제되게 한다. 오디오소스 같은 것을 오브젝트가 들고 있는 것이 맞는가? 오브젝트가 파괴되면 사라져버릴텐데. -> 사운드 매니저로 옮긴다. DontDestroyOnLoad를 통해서 씬을 옮겨도 사라지지 않게 한다. (모든 씬에서 재활용) 오디오를 매번 불러올 수 없으니 caching을 해야한다. dictionary를 이용해서 GetOrAdd 함..
전체 씬을 관리하는 매니저. 각각의 오브젝트는 항상 존재한다는 보장이 없다. 그래서 항상 존재하는 Manager를 하나 두어서 해당 씬에서 항상 존재하며 다른 오브젝트들을 관리한다. 약간 GM같은 느낌? Base 클래스를 둬서 virtual로 init, clear 함수 선언 게임, 로비 등의 씬들은 이 Base클래스를 상속받는다. Start()안에 Init을 넣어 시작해준다. 그리고, Init안에 해줘야 할 일들을 넣어준다.(start에서는 init함수 호출만 한다. UI를 보여주는 showUI같은 함수들을 작성해서 Init안에 넣어준다.) EventSystem이 없으면 입력같은게 안되고 크러시가 나니까, EventSystem을 Prefab으로 만들어서 이것을 GameObject.FindObjectTyp..
UI는 팝업. 다만 씬에 고정적으로 박혀있는 UI는 팝업이긴 한데 다르게 봐야한다. 즉, 팝업용 UI, 팝업용이 아닌 UI(씬을 위한 UI같은 것) 사용했던 order를 저장해서 order에 따라 팝업순서를 지정하면 팝업 효과를 줘서 새로 뜬 녀석이 기존에 뜬 녀석을 가리게 할 수 있다. Stack에서 게임 오브젝트 보다는, 컴포넌트 패턴이므로 UI_Popup과 같은 스크립트를 상속받은 녀석들을 관리할 것이므로 UI_Popup이라는 녀석을 Stack으로 관리하는 편이 낫다. 팝업을 열 때에는 스택에 넣기만 하면 된다. 다만, 팝업을 닫을 때에는 stack이라는 점을 염두해서 LIFO에 맞게 닫아주어야 한다. Int형 변수인 order의 경우에는 매니저에서 증가시키기 보다는, UI_Popup 코드를 통해서..
사용할 함수를 똑같이 복사해주고, GameObjecet에는 this를 붙여준다. 내용으로 원본 함수를 사용하는 것을 똑같이 호출해주고 인자로 Extension에 선언한 함수의 인자를 그대로 넘겨준다.
Action OnBeginDragHandler = null; 어떤 이벤트가 발생하는 함수에서 위에처럼 Action으로 등록해둔 녀석을 Invoke 하면서 에 맞는 T를 인자로 넘겨준다. if(OnBeginDragHandler!=null) OnBeginDragHandler.Invoke(eventData);
드래그 드롭으로 오브젝트와 스크립트 등을 연결시키는 방법과, Button코드 산하에 직렬화코드([SerializeField]였나)를 넣어서 수정하는 방법을 초보자때 쓰는데, 이 방법을 지양하고자 한다. 게임 오브젝트는 텍스트나 버튼과 달리 컴포넌트가 아니어서 텍스트나 버튼처럼 FindChild를 통해 찾는 방법은 불가능하다. 다른 함수를 추가로 작성해서 찾아야 한다. enum으로 두고 Bind함수를 만들어 이를 자동으로 Dic에 등록해서 묶고, Get 할 때도 찾고 싶은 타입 T에 맞는 Dic에서 가져온다. 자세한 코드는 다음 강좌 구매 -> https://www.inflearn.com/course/MMORPG-%EC%9C%A0%EB%8B%88%ED%8B%B0/dashboard