Single RPG Project
팀 단위로 제작한 자작 Single RPG
StackUnity, C#
Develop2021.12 ~ 2022.04
Made byTIOGX 이효원, 정은지
Features
1. 로비씬 : 씬 이동
2. 플레이어 이동 및 카메라 이동, 미니맵 구현
3. npc와의 상호작용
4. npc와의 대화 및 퀘스트 시스템, UI
5. 퀘스트 구분 및 현재 진행중인 퀘스트 CHECK
6. 전투 퀘스트 진행 예시 및 몬스터와 플레이어 간의 상호작용(전투)
7. 액션컨트롤러를 통한 아이템 퀘스트 진행 예시 및 아이템의 인벤토리에 저장
8. 퀘스트 보상 및 store ui를 이용한 골드 소비
9. 스킬 구현 및 추가 기능 설명
10. 보스 전투 시스템
- UnityEngine.SceneManagement 라이브러리의 SceneManager.LoadScene() 함수를 사용하여 씬 이동 구현
플레이어 이동
- Input.GetAxis()를 통해 키보드 입력을 벡터값으로 변환하고, moveInput.magnitude를 통해 해당 백터의 크기를 구하여 0 이상의 경우(움직임이 있는 경우) isMove 변수를 true로 변환하여 움직이는 상태를 구분 할 수 있다.
Vector2moveInput=newVector2(Input.GetAxis("Horizontal"),Input.GetAxi("Vertical"));boolisMove=moveInput.magnitude>0;
- 카메라가 바라보는 방향과 키보드 입력 벡터 사이의 연산을 통해 이동하고자 하는 방향 벡터를 구한 후, 플레이어 객체의 position을 해당 방향으로 moveSpeed 계수에 맞는 속도로 이동시킨다.
Vector3lookForward=newVector3(cameraArm.forward.x,0f,cameraArm.forward.z).normalized;Vector3lookright=newVector3(cameraArm.right.x,0f,cameraArm.right.z).normalized;Vector3moveDir=lookForward*moveInput.y+lookright*moveInput.x;characterBody.forward=moveDir;transform.position+=moveDir*Time.deltaTime*moveSpeed;
카메라 방향 전환 및 줌인 줌아웃
- 마우스 입력에 따라 카메라를 돌려준다. 이때 x,y축 방향으로 제한을 두어 특정 각도 이상 카메라가 회전하는 것을 막는다.
mouseX=Input.GetAxis("Mouse X")*camSpeed;// 프로젝트 세팅에 입력 값 매니저를 보면 이름이 Mouse X로 설정되어있음mouseY=Input.GetAxis("Mouse Y")*camSpeed;Vector3camAngle=centralAxis.rotation.eulerAngles;floatx=camAngle.x-mouseY;if(x<180f){x=Mathf.Clamp(x,0f,70f);}else{x=Mathf.Clamp(x,335f,361f);}centralAxis.rotation=Quaternion.Euler(x,camAngle.y+mouseX,camAngle.z);
- 마우스 휠을 활용하여 줌 구현 및 최대, 최소 줌 거리 제한
privatevoidZoom(){wheel+=Input.GetAxis("Mouse ScrollWheel");if(wheel>=-3){wheel=-3;}elseif(wheel<=-7){wheel=-7;}cam.localPosition=newVector3(0,0,wheel);} ```
미니맵
- 미니맵용 카메라 객체 생성하여 미니맵 레이어에 해당하는 미니맵 이미지를 촬영하는 형식으로 구현
- 카메라가 바라보는 방향으로 발생한 Ray가 태그가
Npc이고MainCamera layer에 존재하는 오브젝트와 충돌하게 되면 NPCActionController.NPCInfoAppear()가 실행된다. - 이를 통해 현재 어떤 NPC와 상호작용 할 수 있는지 알려주는 문자가 게임 상단에 나타난다.
- (T)키를 통해 상호작용을 하게 되면, NPCManager.InitUI()와 QuestManager.checkQuest()가 실행된다.
NPCManager.InitUI() 를 통해 충돌체의 QuestData와 NPCData에 접근한다. 만약 해당 NPC의 퀘스트가 진행될 차례가 아니라면 Idle() 상태의 퀘스트를 주지 않는 기본 상태 UI가 생성되고 그 반대라면 퀘스트가 시작된다.
QuestManager.checkQuest()를 통해 충돌체의 Id와 퀘스트 Type를 확인한다. 해당 정보로 퀘스트의 진행도와 클리어 여부를 확인한다.
Type 1 : 사냥 퀘스트
Type 2 : 말걸기
Type 3 : 아이템 획득
- 퀘스트가 시작되면 현재 진행되고 있는 퀘스트의 내용과 진행도가 게임 화면 왼쪽 UI에 표시된다. 또한 현재 퀘스트가 진행되고 있는 대상이 누구인지 NPC위의 마크를 통해 알 수 있다.
- 플레이어의 피격 및 몬스터의 피격 판정 구현
- 플레이어의 피격
- 몬스터의 경우 일정 거리 내에 플레이어가 들어오면 trace를 실시하며, 공격 사거리 안에 플레이어가 존재 할 시 공격을 실시
- 몬스터의 피격
- 플레이어가 공격키를 입력시 공격중인 상태가 되며 이때 무기와 적 사이의 충돌판정을 실시하여 충돌 시 1회에 한하여 플레이어의 공격력에 해당하는 데미지를 몬스터에가 가함
- 플레이어의 피격
- 아이템 획득 퀘스트 진행시, 퀘스트 클리어 조건으로 명시된 아이템을 획득해야 한다.
- Ray가 태그가 Item인 오브젝트와 충돌하게 되면
ActionController.ItemInfoAppear()함수가 실행. 이를 통해 현재 어떤 아이템을 획득할 수 있는지 알려주는 Text가 게임 상단에 나타난다. - (E)키를 눌러 아이템을 획득하면, 해당 아이템이 Inventory에 추가되고,
ItemDataUI.InstantiateItemDataUI()를 통해 어떤 아이템을 획득했는지 UI를 통해 플레이어에게 알려준다.
- 획득한 아이템이 money일 경우, 인벤토리에 저장되지 않고 게임 상단의
playerGoldUI에 명시된다. - 골드를 통해 상점에서 포션을 구매할 수 있다. 만약 충분한 돈을 가지고 있지 않으면
NotEnoughMoney오브젝트가 나타난다. - 구매한 포션은 인벤토리에 저장된다.
각 스킬 prefab ,SkillpoolManager을 통해 스킬 시스템 구현
- SkillpoolManager
key : Keycode, value : skillprefab 형태의 dict 자료구조를 통해 보유 스킬을 관리
현재 등록된 스킬의 키보드 입력이 들어올 경우 KeyDictionary[dic.Key].GetComponent().CanUseSkill()
- 각 스킬 prefab
각 프리팹의 경우 고유한 스킬 이름, 데미지, 쿨타임 및 UseSkill() 메소드 보유
추가 기능
- 게임 좌측 버튼을 통해 여러 UI에 접근할 수 있다.
- 플레이어 정보
플레이어 레벨, Xp, 현재 체력, 공격력, 주문력
- 게임 정보
게임 플레이 시 필요한 키들이 정리되어 있다.
- 플레이어의 현재 체력이 0이 되면 플레이어의 상태가 Die로 변하고
PlayerDieUI가 켜진다.
계속 플레이하게 되면 리스폰 장소로 이동한다. 계속 플레이하지 않으면 로비로 돌아간다.
- BossController.cs
보스는 idle, tracing, die 상태를 가짐
매 업데이트마다 CheckBossState() 함수를 통해 상태를 체크하고, 움직일 수 있는 상태라면 BossMove(), 공격 할 수 있는 상태라면 BossAttack() 함수를 실행한다.
- BossMove()
nav.SetDestination() 함수를 통해 플레이어 객체의 position을 TargetPos로 지정한 후 이동한다.
- BossAttack()
IsAttack() 함수를 통해 보스의 상태 및 공격 주기, 공격 사거리 내에 플레이어가 존재하는지 확인 한 후 공격을 실시
랜덤 난수를 생성하여 패턴을 선택하고 해당 패턴을 사용한다. 이후 코루틴을 통해 공격 쿨타임을 갱신한다.






















