ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스파르타 최종프로젝트 2일차
    스파르타 게임 개발 2024. 6. 28. 23:57

    1. 지형생성

    지형 생성 하는 부분에 있어서 처음 계획은 캐릭터의 자동이동을 지형 정보에 따라서 하려고 했기에 지형을 배열로써 생성을 하려고 했다. 

     

    1,1,1,1,1

    0,0,0,0,1

    1,1,1,1,1

    1,0,0,0,0

     

    1은 부숴지는 땅, 0은 안 부숴지는 땅, 이런 식으로 만들어서 리스트를 쫙 돌려서 가까운 1을 찾아 유닛을 이동 시키게 하려고 했다. 

     

    그런데 아직 내 수준에서 하기엔 어려운 레벨이라고 느꼈고, 튜터님이 유닛 자동이동에 대해서 더 쉬운 방법을 추천 해주셔서 맵 지형을 바꾸기로 했다. 

     

    이 방법이 더 좋은 방법이라면 어려워도 했겠지만, 맵이 길어질수록 성능이 안 좋아지기 때문에 방법을 바꾸기로 했다.(리스트가 계속 늘어나니까)계산이 늘어난다.

     

    그런데 나중에 게임을 다시 로드 할 때 파괴 됐던 땅을 저장을 시켜야 했기에 이 방법으로 만드려고 했으나, 굳이 그럴 필요 없이 길건너친구들 제작 했을 때처럼 특정 맵구역 자체를 자동생성 하게 하고, 그 생성한 지형들을 리스트로 저장을 해서 그 리스트를 저장을 하면 되겠다 싶었다. 

     

    그래서 특정 지형을 만들고 그 특정 지형을 FloorManager가 갖고 있다가 계속 소환을 하게 하는 방식으로 구현 하기로 했다. 특정 지형은 지형안에 있는 블록들을 다 갖고 있는다..!

    이 모양의 지형을 계속해서 생성 할 것임

     

    이 때 맵 만들면서 블록들을 프리펩으로 만들지 않고 바로 오브젝트 복사 하는 참사를 저질러버려서 나중에 굉장히 번거로워졌다... 꼭 프리펩 만들고 작업 하자.. 이런 거 만들 때

    이미지들의 컬러값을 변경을 해서 파지는 땅을 구분했다.
    이미지의 컬러값을 변경해서 판 곳을 구별 할 수 있게 했다.

     

    이렇게 맵을 만들어주고 스크립트를 작성 해줬다. 

     

    Block들은 체력을 갖고 있고 image등 여러 정보들을 갖고 있는다. Unit과 충돌을 하면 유닛이 땅을 파고 체력이 닳는다. 이 때 유닛도 체력이 닳아야 하는데 이게 두 개의 체력을 동시에 닳게 해야 하니까 생각보다 번거로웠다. 나중에 유닛부분에서 작성 하도록 하겠다. 

     

    이 블록의 여러 정보들을 이 Block들을 담고 있는 BlockController가 층수가 오를수록 이미지나, 체력들을 올라가게 했다. 

     

    그리고 이 Block들 사이에 닿으면 맵 생성하게 하는 Block도 숨겨놨다. 

    중간에 큰 컬라이더가 있는 것이 보인다. 저기에 닿으면 다음 맵 생성.

     

    내가 심화주차 개인과제를 길건너친구들을 한 건 운명이였던걸까? 이번 과제를 하면서 전에 했던 것을 하니 비교적 쉬웠다.

     

    그리고 블록들이 파여지기 시작하면 블록의 체력도 나와야 하는데 후.. 블록을 프리펩으로 안 만들어서 굉장히 번거로웠다.

    지금 생각 해보니 Text도 달아둬야 한다..ㅋㅋㅋㅋ 

    블록들의 체력도 닳아줬다.

     

    그리고 이번 프로젝트 굉장히 노가다 한게 GetComponent 자체가 안 좋은 거라고 해서 이번 프로젝트는 컴포넌트들을 거의 다 손으로 집어넣었다. // 프리펩으로 만들기만 했어도.. 1시간은 아꼈다.

    ////// 튜터님이 자기 거 Awake에서 가져오는 건 성능에 1도 상관 없다고 한다......., ㅎㅎ... 내 시간

     

    그리고 블록들의 컬라이더를 땅이 부숴지지 않는 것은 한 줄로 하려고 했고, 이것도 자동으로 컬라이더 영역 잡히게 하고 싶었는데, 잘 안 됐다. 아쉽..

    컬라이더를 한줄로 설정 해보았다. 의미가 있을까

     

    아무튼 지형은 이렇게 해서 끝났다. Block들은 부숴지고 체력 닳고, 체력바 나오고, 자막 나오고 이 Block들을 갖고 있는 BlcokController가 이 Block들의 이미지와 체력 등 여러 스텟들을 변경 하고, FloorManager가 이 BlockController를 계속 해서 생성 하게 했다. 생성 하면 생성한 횟수를 저장 해서 현재 층수를 남기게 한 것으로 지형을 마무리 했다. 

    지형자동생성 완료

     

    정말 생각보다 오래 걸렸다. 첫단추를 잘 못 꿰서 방황을 너무 오래 했다. 

     

     

     

     

    2. 유닛자동이동

    유닛을 자동 이동 하는 것에 대해서도 굉장히 오래 걸렸다. 처음에 일단 1,0,0,0 이거 하려고 시간 엄청 많이 쓰고 12시까지 튜터님께 프로토타입 완성하기로 약속 했는데 시간은 얼마 안 남았고 뇌정지 오고 허둥지둥 하느라 안 헷갈려야 하는 것들도 막 헷갈리고 그랬다. 

     

    1,0,0,0 이런 시긍로 움직이게 하려다가 튜터님께서 추천 해주신 오른 쪽으로 갔다가 방향만 바꾸게 하는 것으로 바꾸기로 했다. 

     

    rigidbody로 처음에 구현 했는데 이것을 이용해서 Block들과 Collider로 로직들을 처리하려고 했으나, 역시 Box Collider와 Exit는 쉽지가 않다. 생각을 좀 많이 해야 했고, 튜터님들께서 그냥 Transform으로 움직임을 구현하라고 해주셨다. 

     

    사실 이거 전에 하던 방법이 하나가 더 있었는데, 그것은 튜터님께서 추천 해주신 방법인데, 지금과 같은 구조는 패턴이 있다고 한다. 블록들이 겹쳐 있으니까 그래서 거리를 지정해두고 한 번에 그 거리만큼 움직이고 Ray를 쏴서 현재 위치를 파악해서 로직을 수행. 그리고 이동중에 전방으로 쏴서 앞에 벽이 있는지 확인. 그리고 로직 수행 등에 방법을 시도 하고 있었다가 튜터님이 트랜스폼 사용 하라고 해주셨다.

     

    나는 Transform으로 이동을 하면 순간이동처럼 되는 것이라 안 좋다고 생각을 했는데 경력 많으신 분들은 그런 걸 못 느끼시고 상관 없다고 하졌다. 그리고 보정을 해주면 괜찮다고 해주셔서 Tranform을 이용해서 이동을 하게 했다. 

     

    스파르타 완전 처음 했을 때의 방법으로 ..ㅋ ㅋ 맘에 안든ㄷ다.... 급해서 어쩔 수 업서.., 나에겐 시간이 없다. 일단 돌아가면 Ok로 가야 하는 .. 거겠지?,, 그럴거면 gpt도 막 쓰던가. 

     

    그리고 유닛의 주요 로직 중 Block과 충돌이 되면 Block의 데미지를 받게 하는 함수를 호출 해야 하는데, 이 때 유닛도 같이 체력이 닳아야 했다. 

     

    근데 컬라이더로 이 두 개를 동시에 닳게 하려니 생각보다 매우 복잡했다. 

     

    우선 충돌한 블록을 가져와서 충돌한 블록에 함수를 사용 해야 하는데 거기에 플레이어 체력도 닳게 해야 했다. 

    이거야 충돌이 됐을 때의 플레이어 체력 빼게 하는 코드도 추가 했으면 됐지만 문제는 플레이어는 공격의 쿨타임이 적용이 돼야 했다. 

     

    그래서 코루틴을 써야 했는데, 이게 어떻게 해야 코루틴 안에 이 오브젝트 두 개의 함수를 넣을 수 있을가가 생각이 좀 오래 갔다. 

     

    한 개는 컬라이더가 돼야 코루틴 안에 넣을 수 있기 때문이였다. 

     

    이 방법은 Block 형식의 변수를 미리 선언만 해두는 것으로 해결했다. 

    이렇게 변수를 선언 해두면 함수 안에 넣을 수 있다!

     

    이걸 생각을 못 해서 꽤 오래 걸렸다. 

    완성 한 코루틴

     

    블록과 충돌을 하면 curBlock이 충돌 한 오브젝트로 초기화 되고 코루틴이 실행 된다. 이 방법으로 오브젝트 2개가 동시에 체력이 닳게 했다. 

     

    처음엔 이걸 어떻게 해야 두 오브젝트가 닳게 할까 하다가 막 매개변수로 함수 넣고, 함수 실행하고 이렇게 할려고 했었다. 그냥 변수 하나 생성으로 비교적 간단하게 구현 했다. 

    // 추가로 collider 될 때마다 공격을 하면 문제가 많아서 한 번 닿으면 둘 중 하나가 뒤질 때까지 연결 된 오브젝트 패게 했다.

     

     

    3. 유닛 생성

    계획은 UI가 유닛의 데이터를 갖고 있고 오브젝트풀을 소환 할 때 갖고 있는 데이터로 초기화 하는 것이다.

    이전 프로젝트에서는 SO를 사용해서 SO를 갖고 있다가 그걸로 초기화를 했었다. 

     

    그런데 SO 같은 경우 게임이 커지면 중간에 데이터가 변경이 돼야 할 때가 있는데 SO는 에디터로만 변경이 가능하다고 데이터가 많아지면 좋은 방법이 아니라는 말이 있어서 이번에는 Class로 데이터를 저장 시켰다. 

     

    진짜 매우 어려웠다. 오늘 오후시간 다 썻다. SO는 쉽다 그냥

     

    그렇게 어려웠던 건 아니지만 생각을 떠올리지 못해서 매우 복잡했다. 일단 SO처럼 한 개의 자료형에 여러가지를 넣으려면 상속을 받아야 했고 자식 클래스로 만들어야 했다. 

     

    지금 생각해보면 그렇게 어렵진 않고, 처음 생각대로 했으면 금방 끝났을 텐데 중간중간 헷갈려서 바꿔가지고 더 오래 걸린 것 같다. 

     

    Unit이라는 부모 클래스가 여러 능력치들이 있고 Druid라는 Class가 상속을 받아서 Druid의 능력치로 Unit의 능력치들을 초기화 하는 함수를 작동 시켜야 했다. 

     

    어우 쉽지 않았다. 방법은 일단 오브젝트 풀로 Unit이라는 객체들을 생성을 하고 그 다음에 그 객체들을 갖고 오면 Druid가 갖고 있는 함수를 사용을 해야 했는데, 일단 복잡한 이유가 SO같은 경우 그냥 갖고 와서 거기에 있는 SO는 이 슬롯의 몇 번째 SO다! 라는 느낌으로 바로 그냥 초기화 했으면 됐는데, 이건 아니다. 

     

    Unit 객체를 넣은 거라서 거기서 GetComponent가 아닌 Druid가 아닌 연결을 해야 하는 등등 한 번 해봐라 

     

    아무튼 나는 Unit형식의 자료형을 만들고 거기에 그걸 상속 받은 Druid를 넣으면 된다라는 생각만 가지고 계속 해서 떠올려냈다. 쉽지 않았지만 일단 함수의 매개변수를 Unit으로 만들고 Druid를 넣으면 된다라는 것을 깨달았다. 어떻게 보면 당연한건데 왜 떠올리지 못 했을까. 인터페이스 추상클래스 등등 엄청 많이 시도 해봤다. 

     

    처음엔 Unit의 함수를 인터페이스나 추상클래스로 만들고 거기에 함수를 상속 받게 해서 자식클래스에 정의 된 것으로 실행이 되게 해가지고 데이터를 변경 하게 하려고 했는데 일단 연결이 안 되고 그럴려면 오브젝트 풀을 자식클래스로 생성을 해야 하고 등등 그랬지만, 이런 방법이 아닌 함수 매개변수에 Unit을 넣으면 된다라는 것을 깨닫고 그 방법으로 나아갔다. 

     

    virtual 함수를 사용 한 게 있었다. 왜냐하면 일단 Unit 자료형을 사용하려면 Unit에 있는 함수여야 하니까, 

    그래서 이 함수에 매개변수로 Unit을 넣어서 자식클래스를 매개변수로 넣으면 이 자식클래스의 함수가 실행이 되는 것으로 데이터를 바꾸게 했다. 

     

    많은 시행착오로 나는 Class 하나만 추가를 하면 자동으로 슬롯이 추가 되고 objPool을 이용한 자동생성을 할 수 있게 만들었다. 

    그런데 나중에 작업량이 많아지면서 추가 할 게 훨씬 더 많아질 것 같긴 하다. 

    그림설명

     

    대충 구조는 UnitController에서(이 유닛 컨트롤러가 각 유닛들을 갖고 있을 UI오브젝트다. 각 버튼들) 미리 Unit을 상속 받은 자식Class들을 집어 넣어놓는다. 

    그리고 버튼이 눌리거나 생성을 하게 되면 Obj를 꺼내와서 Unit 겟컴포넌트 한 다음에 Unit에 만들어둔 함수를 호출한다.

     

    이 때 함수 매개변수에 이 값을 넣어둔 Druid 넣어서 실행을 함으로써 생성을 완성 했다. (이 함수는 매개변수로 넣은 Druid의 스텟들로 obj로 소환 한 오브젝트에 데이터들을 초기화 하는 함수다.)

     

    주의 할 점은 Unit에 있는 함수를 사용 해야 해서 Druid 자체에서도 부모클래스에 있는 스텟들을 변경 하게 하는 함수를 만들어야 하고, 그 변경 된 스텟으로 objPool로 소환 된 객체의 스텟이 바뀌게 함수를 만들고, virtual 함수를 사용해서 그 함수를 호출 하게 해야 한다. 

     

    abstract는 객체 생성을 하지 못 해서 virtual을 사용 해야 한다. 

     

    이렇게 유닛 생성까지 하고 프로토타입을 끝낼 수 있게 되었다.

    나중에 슬롯(현재버튼)도 Manager 계열에 Unit Class를 배열로 집어 넣고 Length 만큼 생성 할 것이다.

     

    원래는 오늘 오전중으로 끝낼 생각이였고, 그럴 줄 알았는데 첫단추 잘 못 꿰서 나비효과로 그냥 나머지도 되게 복잡하게 생각 하고 있었다. 그래서 생각보다 너무 오래 걸렸고 튜터님 실망 하셨을 것 같다. 

     

    아무튼 이거 다 하고 튜터님께서 봐주셨다. 몇 가지 추천들을 해주셨고 그것들로 바꿔야 하고, 그리고 이제 게임구조를 생각 해오라고 말씀 해주셨다. 

     

    최대한 하고 싶은 기능이나 만들어야 하는 것들을 최대한 많이 뽑아오라고 하셨다. 튜터님이 거기서 짤라주신다고, 그래서 오늘 2일차는 여기서 마무리 하고 내일 목표는 게임 기획 완성이다. 

     

Designed by Tistory.