유니티 공부를 위해 자체적으로 게임을 만들며 기능을 하나씩 구현해가던 중(공격, 차징공격 까지) 플레이어 스크립트가 너무 복잡하다는 것을 깨달았다. 개발자 친구와의 대화중에 기능별로 세분화해서 스크립트를 분리하는 것이 좋다는 말에 무작정 다음날 플레이어의 상호작용, 공격을 무작정 분리하기 시작했다.
명확한 계획없이 진행하다보니 근거리공격, 원거리공격을 나누어서 진행하려다 막상 나누고보니 스크립트의 길이가 길지 않아 다시 합친다거나 하는 불필요한 행위들이 있었으나 그건 그다지 큰 일은 아니었다.
이전 백엔드를 공부할 때 다른 class 파일의 변수나 함수에 접근하는 방법은 크게 어렵지 않았다. (물론 교육을 듣고 있었던지라 모르는게 있으면 강사님께 여쭤봤지만)
하지만 지금은 오로지 구글링만 있을 뿐.
맨처음 검색했을 때 대부분의 사람들은 싱글톤, 빈오브젝트에 스크립트를 넣어 GetComponent<>()를 사용하는 법, find를 사용하는법을 추천했다.
백엔드에서 DB에서 검색 혹은 데이터를 받아오거나 할때 싱글톤이라는걸 썼는데 정확히 어떻게 활용하는지 알지 못해서 일단 알려주는대로 코드를 작성했다.
지금 생각하면 무식하기 짝이없지만...
public static Player_Interaction playerInter;
private void Awake() {
Debug.Log("This is pInteraction Awake");
if(Player_Interaction.playerInter == null){
Debug.Log("pInter instance start");
Player_Interaction.playerInter = this;
Debug.Log("pInter instance end");
}
}
1. 먼저 해당 스크립트를 정적(static)으로 인스턴스화 한다.
2. 스크립트가 시작된 후(Awake) playerInter가 비어있다면(null) 이 스크립트를 대입하라
...고 코드를 썼다. 이렇게만 하면 되는 줄 알았다. 싱글톤이라는 것이 정확히 무엇인지는 파악하지 않은 채 다른 스크립트의 변수와 함수를 사용하기 위해서...
처음에는 잘 작동 했다. 공격(Weapon_Attack) 스크립트만 싱글톤으로 구현했기 때문에 문제는 없었다.
이후 상호작용(interaction)까지 싱글톤을 위해 인스턴스화하고 플레이어스크립트의 변수를 조작할 필요가 있어 플레이어 스크립트와 게임매니저마저 인스턴스화한 뒤 게임을 시작하기 전까지는...
아무튼 모든 스크립트를 싱글톤으로 구현하려고 코드를 작성하고 게임을 시작했다. 공격 스크립트는 변함없이 잘 작동했다.
그런데 공격을 맞은 몬스터가 체력이 다 되어 파괴되어야 할텐데 계속 살아있으면서 null point exception오류가 발생했다.
몬스터가 파괴되는 조건은 아래와 같이 설계했다.
1. 플레이어가 공격
2. 공격에 몬스터가 닿으면 공격은 파괴(Destroy)되고
닿은 몬스터의 정보와 공격력을
GameManger의 AtkToEnemy함수에 인자로 넘기며 호출
3. GameManager는 넘겨받은 몬스터의 정보를 받아
해당 개체에 공격력을 인자로 Damaged함수를 호출
4. Damaged는 현재 체력에서 넘겨받은 공격력을 감소시킨다.
이 때 남은 체력보다 공격력이 더 클경우 본 개체를 파괴(Destroy)한다.
원인을 찾기 위해 각각의 함수에 Debug.Log를 달아 확인해보니 2번이 실행되지 않았다.
이때부터 뭔가 잘못됨을 느끼고 더 찾아보았다.
[Unity] 유니티 싱글톤 오브젝트의 활용 - singleton
프로그래밍을 설계 또는 디자인할 때 사용되는 디자인 패턴 중 하나인 싱글톤은 게임 개발 시 많이 사용되는 설계 방법입니다. 싱글톤은 프로젝트 안에서 유일하게 1개의 인스턴스로 존재하여
codeposting.tistory.com
뭔가 이상해 각 스크립트의 Awake()안의 if문(스크립트가 비었는지)에 Debug.Log를 달아서 확인해보니 발생한 Debug문구는 공격 스크립트 단 하나...
즉 공격 스크립트만이 인스턴스 할당되고 나머지는 아예 인스턴스화조차 되지 않았던 것이다.
그리고 유니티에서 싱글톤패턴은 플레이어나 몬스터와 같은 오브젝트에는 효과적이지 않다는 것 또한 이 일 이후로 알게되어 여태 씨름했던 싱글톤기법을 사용한 변수 접근은 그만두기로 했다.
그렇다면 내가 알고 있는 방법 중 find와 게임오브젝트참조 중 더 나은 방법을 선택해야 했는데 find는 탐색을 통해 스크립트를 찾아야하므로 속도면에서 불리할 것 같아 후자방법을 선택하려 했다.
다만 그러면 불빌요한 오브젝트가 플레이어 하위에 많이 생길 것 같아 생각을 해보던 중 하나의 오브젝트에 스크립트를 여러개 넣을 수 있다는 걸 이제 알았다...
그럼 이제 선택지가 또 늘었다.
1. 오브젝트를 생성하여 각각 스크립트를 넣고 참조를 시키느냐
2. 위처럼 오브젝트 하나에 스크립트를 여러개 넣고 사용하느냐
아무래도 전자보다는 후자가 덜 번거로울 것 같아 후자로 진행하기로 했다.
전자는 오브젝트마다 스크립트에 GameObject 변수를 만들고 Inspector창에서 참조할 수 있도록 일일이 지정해야하는 반면 후자는 GetComponent<>()만 이용해서 접근할 수 있기때문이었다.
결과는 본래 내가 의도했던대로 잘 작동했다. 스스로의 무지함에 며칠간 복잡해서 책상앞에 앉기조차도 싫어지던 시간들이 이렇게 간단하게 해결되니 살짝 허탈해지지만 공부의 필요성이 더 절실해짐에 의미를 두어야겠다.
싱글톤패턴에 대해 객체의 인스턴스화 및 GameManager의 싱글톤 구현등 좀 더 자세히 알아야하는 부분이 생겼다.
'개?발 > Unity 혼공' 카테고리의 다른 글
유니티 3D Tilemap 위에서 플레이어 한 칸씩 움직이기 (0) | 2024.08.13 |
---|---|
유니티 Tilemap 좌표 값 및 중앙 위치 구하기 (0) | 2024.08.12 |
절벽감지 및 경사로 예외상황 (0) | 2023.11.07 |
지면 점프(위 지형으로 점프하기) (0) | 2023.11.07 |
공격(HitBox)좌우 반전(position, localPosition) (0) | 2023.11.07 |