유니티 22

일정 영역을 넘어가면 돌아가는 적 AI

적이 플레이어를 따라가다가 정해진 범위를 벗어나면 다시 원래의 자리로 돌아가는 AI를 구현해보았다. 구현 과정에 필요한 기능은 크게 2가지였다. 1. NavMesh를 원하는 모양대로 설정하기 NavMeshSurface 컴포넌트를 사용해서 NavMesh를 생성했지만 해당 오브젝트의 모든 영역을 사용하는 것이 아니라 일부분은 다른 Area로 사용하고자 했다. 이 때 여러가지 시행착오를 겪었는데 Built-in 되어있는 Area인 NotWalkable은 NavMeshModifier 컴포넌트로 Walkable로 덮어쓸 수 없었다. NotWalkable 영역은 NavMesh의 하나의 영역이라기 보다 해당 영역에는 아예 NavMesh데이터를 생성하지 않는 것처럼 보였다. 그래서 선택한 방법은 새로운 MonsterZ..

부트캠프 2023.10.27

적 AI구현

이번 최종 프로젝트에서 사용될 적 AI를 구현하고 있다. 이번 프로젝트는 스테이지나 씬 등으로 나눠져있지 않고 하나의 큰 맵을 사용한다. 적은 이 맵에 골고루 분포되어 있을 예정인데 모든 적이 매 프레임마다 플레이어와의 거리를 체크하게 된다면 꽤나 큰 부하가 걸릴 것이라는 예상이 되었다. 그래서 적 AI는 일정 시간의 딜레이를 두고 플레이어와의 거리를 체크한 후 적정 거리 이내로 플레이어가 진입했을 때 활성화되고 멀어지면 비활성화 되어서 업데이트를 중단하도록 코드를 작성했다. 또 활성화 된 상태라면 플레이어가 가까이 있다는 뜻이므로 거리체크를 매 프레임 실행하도록 했다. 해당 기능을 수행하는 메소드는 다음과 같다. private void CheckTargetDistance() { if (Time.time..

부트캠프 2023.10.26

최종 프로젝트 기획

https://www.figma.com/file/3dMxFQD9VgzJr2cKp5gaHv/15%EC%A1%B0-%EC%B5%9C%EC%A2%85-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8?type=design&node-id=0-1&mode=design&t=dci7870DuqYh2iyy-0 Figma Created with Figma www.figma.com 오늘은 팀원들과 함께 게임의 뼈대가 될 기획을 같이 작성했다. UI요소의 배치, 게임 내에 필요한 시스템 등을 여러 게임을 참고해서 적절한 형태로 변환시켰고 게임의 장르는 어드벤처 쪽으로 많이 기울어졌다. 서바이벌만으로는 적절한 동기를 부여하기 힘들고 구현할만한 기능이 많지 않았고 너무 캐주얼하지는 않되 무겁지 않은 게임성을 추..

부트캠프 2023.10.24

최종 프로젝트 시작

오늘 약 2달 가량의 시간을 가지고 진행하는 최종 프로젝트를 시작했다. 팀원은 5명으로 팀장을 맡았으며 최종 프로젝트 게임의 장르는 3D RPG로 서바이벌 요소를 첨가하기로 하였다. 적절한 게임성과 여러 게임 기능들을 구현하면서도 개발 기간에 맞춰 만들어 낼 수 있는 게임을 고려했을 때 가장 적절한 장르였다. Figma를 통해서 게임의 컨셉을 정하고 팀원들과 같이 사용할 애셋을 점검하는 데에 많은 시간을 할애했다. 아트를 담당할 인원이 따로 없기 때문에 게임 내의 모든 리소르를 자체 제작 혹은 애셋에 의존해야 하는데 자체 제작은 시간도 너무 오래 걸릴 뿐더러 적당한 컨셉과 퀄리티를 가지기 힘들기 때문에 애셋을 고르는데 많은 투자를 하기로 했다. 그럼에도 불구하고 적당한 애셋들을 찾는 것이 어려워서 완벽하..

부트캠프 2023.10.23

원을 따라 움직이는 적 구현

적 캐릭터를 원을 중심으로 테두리를 따라 움직이도록 구현해 보았다. 핵심이 되는 코드는 다음과 같다. private void CircleMove() { bool onCircle = isOnCircle(); if (!onCircle) { destination = Center.position; if (agent.destination != destination) agent.SetDestination(destination); isMovingToCircle = true; return; } else { if (isMovingToCircle) { isMovingToCircle = false; agent.SetPath(new NavMeshPath()); CalculateOnCircleAngle(); } } float ..

부트캠프 2023.10.20

NavMeshAgent와 CharacterController를 이용한 점프

네브메쉬 에이전트와 캐릭터 컨트롤러를 사용해 적의 움직임을 구현하려고 했다. 생각지 못한 버그들이 많이 발생했는데 알아둬야할 사항들이 몇 가지 있다. 먼저 NavMeshAgent가 enabled 되어 있는 상태에서는 CharacterController의 Move를 사용해도 제대로 동작하지 않는다. 점프등의 행동을 구현하기 위해서는 그 순간 Agent를 꺼주어야 한다. 또 Agent를 끄면 생기는 문제점으로 Agent가 꺼지고 다시 켜지면 기존의 목적지 정보를 상실함과 더불어 velocity가 다시 0부터 시작한다. 해당 정보를 미리 캐싱해놨다가 집어 넣어주어야 한다. CharacterController로 점프를 구현할 때 생각해야 할 점은 RigidBody를 사용하지 않는다면 직접 중력을 적용시켜 주어야..

부트캠프 2023.10.18

델리게이트를 이용해서 UI를 구성하기

UI화면을 띄워야 할 때 같은 UI를 사용하지만 안의 내용이 달라져야 하는 경우가 있다. 위와 같은 UI를 사용한다고 했을 때 해당 팝업은 여러 용도로 쓰일 수 있다. 하지만 같은 UI더라도 안에서 동작하는 스크립트는 달라져야 한다. 이럴 때 가장 쉽게 떠올릴 수 있는 방법은 필요한 용도마다 새로운 스크립트를 짜는 것이다. 예를 들면 StoreUI, InventoryUI, QuestUI 등 그때 그때 필요한 기능을 구현한 스크립트를 추가하고 새로운 UI를 만들어 사용하는 것이다. 구조에 관해 고민할 필요가 없고 구현에만 집중하면 되기 때문에 UI의 개수가 그렇게 많지 않다면 그렇게 나쁜 방법은 아닌 것 같다. 하지만 만약에 UI가 점점 많아져서 해당 팝업이 5군데, 10군데, 20군데 이렇게 끝도 없이 ..

부트캠프 2023.10.12

ToggleGroup

UI를 다루다보면 하나의 옵션만 활성하 하고 싶을 때가 있다. 그럴 때 사용하는 컴포넌트가 토글 그룹이다. ● 토글 그룹이란? 토글 그룹은 토글할 수 있는 UI 요소를 하나의 그룹으로 묶어서 해당 그룹 중의 하나만 선택될 수 있도록 강제한다. ● 어떻게 사용하나? 1. 게임 오브젝트에 토글 그룹 컴포넌트를 추가한다.(이 오브젝트는 꼭 캔버스의 자식이 아니어도 된다) 2. 토글 컴포넌트를 가지고 있는 객체들 중 하나의 그룹으로 묶을 객체들을 다중선택한다.(하나씩 넣어줘도 된다) 3. 토글 컴포넌트 안에 있는 그룹 속성에 토글 그룹 컴포넌트를 가지고 있는 오브젝트를 드래그 앤 드랍으로 넣어준다. ● 토글 그룹의 속성 Allow Switch Off 해당 속성이 활성화되어 있으면 토글 중에 하나도 켜져 있지 않..

부트캠프 2023.09.26

Find계열 함수를 지양하자.

유니티에서 필요한 오브젝트를 찾을 때가 있다. 가장 좋은 것은 상위 오브젝트나 매니저, 혹은 인스턴스화를 할 때 참조할 주소를 가지고 있게끔 설계하거나 인스펙터창을 통해서 참조를 가지고 있게 하는 것이 좋다. 그게 안된다면 GetComponent류 메소드를 통해서 찾는 것이 좋다. 왜 Find라는 편한 함수를 사용하면 안되는가? ● Find 함수는 모든 오브젝트를 검색하기 때문이다. 위와 같은 오브젝트가 있다고 하자. 여기서 Parent의 transform.Find를 사용하면 밑의 Child 1~6을 하나씩 탐색한다. 당연히 자식이 많아질수록 탐색 비용이 커지게 된다. 그래도 transform.Find까지는 자식이 많지 않다면 쓸 수 있다. 그런데 확실하게 쓰지 말아야 할 Find 함수가 하나 있으니 바..

부트캠프 2023.09.19

오브젝트 풀 만들기

● 오브젝트 풀이란 ? 게임 내에서 자주 생성되고 삭제되어야 하는 객체들이 있다. 대표적으로 총알과 같은 투사체가 그러한 객체들이다. 하지만 유니티에서 게임 오브젝트를 만들고 지우는데는 꽤나 큰 비용이 발생한다. 그런 비용을 줄이기 위해 쓰는 것이 오브젝트 풀이다. 미리 오브젝트를 생성해놓고 필요할 때 꺼내서 쓴 다음 파괴되어야 하는 상황에서 파괴하는 것이 아니라 오브젝트 풀로 다시 가져온 뒤 비활성화한 상태로 보관해놓고 있다가 다음 필요할 때에 다시 꺼내쓰는 방식이다. ● 구현 방법 구현하는 방법이 복잡한 것은 아니다. 게임 오브젝트를 저장하고 있을 큐 하나, 그리고 큐에서 게임 오브젝트를 꺼내거나 넣을 기능정도만 있어도 충분하다. 필요하다면 여기에 태그라던가 부가적인 정보를 넣어서 딕셔너리 등으로 구..

부트캠프 2023.09.18