본문 바로가기
다이어리/내일배움 개발일지

게임개발캠프 - 최종프로젝트 4일차

by E.Clone 2024. 3. 12.

과정명 : 내일배움캠프 Unity 게임개발 3기

전체진행도 : 52일차

부분진행도 : ChapterF - 4일차

작성일자 : 2024.03.11(월)

개발일지 목록 : 클릭


1. 진행중인 과정에 대해

탄막게임의 탄막 시스템 열심히 개발 중

2. 오늘 학습에 대해

SO 활용 탄막 사이클

SO 활용 탄막 사이클
PatternSO
PhaseSO

SO 탄막 활용의 테스트를 위한 준비

추후 실사용에서는 tag:Player를 사용하지는 않겠지만, 테스트를 위해서 플레이어 오브젝트를 만들고 플레이어 태그를 통해 위치정보를 알아내도록 세팅하였다.

1차적으로 선형 발사를 위한 PatternSO 변수 준비를 마쳤다.

using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "Patterns", menuName = "DanmakuSO/Pattern", order = 0)]
public class PatternSO : ScriptableObject
{
    public List<DanmakuPatternData> patternDatas;

    // 패턴 이름을 통해 패턴 정보를 찾기 -> 추후 최적화를 위한 수정 필요. 어떻게 쓰일지도 살짝 애매모호한 상태.
    // ▲ 현재 상태 : PhaseSO에서 patternName을 입력하여 저장, Enemy에서 'GetSpawnInfoByPatternName' 이용하여 탄막패턴 사용. 일단 OK
    // TODO.
    // But, 커스텀 고려해서 수정 필요.
    // 그리고 GetSpawnInfoByPatternName 자체에 대해서도 연산 더 낮은 방식으로 바꾸어야 함.
    public DanmakuPatternData GetSpawnInfoByPatternName(string patternName)
    {
        foreach (var patternData in patternDatas)
        {
            if (patternData.patternName == patternName)
            {
                return patternData;
            }
        }
        return null;
    }
}

[System.Serializable]
public class DanmakuPatternData
{
    public string patternName;
    public DanmakuSettings danmakuSettings;
}

[System.Serializable]
public struct DanmakuSettings // 추가 할 게 진짜 많다.. 트리 이미지로 {1.생성-2.이동-3.하층생성-4.반환} 명심하여 작성
{
    // 아래의 내용은 전-부 PhaseSO 작성 시 커스텀이 가능. 다만 선택적 커스텀을 어떻게 해야할지 떠오르지가 않음. 커스텀 값을 기본적으로 모두 null로 둘 수 있을까?

    // 1. 생성 ---------------------------------//------------------------------------------------------------------

    // 1-1. 탄막의 모양
    public GameObject danmakuPrefab;            // 탄막 기본 프리팹

    // 1-2. 생성 시간과 횟수에 관련된 정보
    public float initDelay;                     // 첫 탄막 생성까지의 지연
    public int numOfSet;                        // 총 세트 수
    public float setDelay;                      // 세트 사이의 지연
    public int shotPerSet;                      // 한 세트에서 탄막을 몇 차례 생성할지
    public float shotDelay;                     // 탄막 생성 사이의 지연

    // 1-3. 생성 모양에 관한 정보
    // Memo. 여기서 할게 꽤 많음. 차차 작성. 03월 11일 목표는 여기! SO 정보를 읽어 구 모양으로 발사하기. 필수요소만 준비하여 시연을 해 보자.

    // a. 어느 방향을 기준으로 생성을 시작할 것인지
    public PosDirection posDirection;           // 주체 기준으로 생성될 방향
    public Vector3 customPosDirection;          // > posDirection이 World일 경우 지정
                                                // a-plug. 기준 방향에 랜덤성을 줄 것인지.
                                                // public bool posDirectionHasRandomness;    // 랜덤성 부여
                                                // public PosDirectionRandomType posDirectionRandomType;    // > 랜덤성이 직선인지, 평면인지. 이후에 고려할 사항도 다수
                                                // >a> 랜덤성이 직선일 경우, 그 직선의 형태
                                                // >a> 랜덤성이 직선일 경우, 그 직선의 범위 또는 양 방향 각각의 범위(각도가 될 듯)
                                                // >b> 랜덤성이 평면일 경우, 그 평면의 형태. 능력이 안된다면, 아래의 조건만 보아 콘 형태부터.
                                                // >b> 랜덤성이 평면일 경우, 허용 범위. 즉 기준점으로부터의 허용 각도

    // b. 기준방향을 중심으로 어떤 형태의 방사를 사용할지. 거리와 방향을 포함.
    // 간단한 선형 단일 발사부터, 정육면체 모양으로 속도를 달리 한 발사, 특별한 모양으로 생성되어 각각이 랜덤한 타이밍에 발사 등 다양한 형태.
    // b-1. 형태에 관해. 기본적인 프리셋을 제공하되, 유저가 Vector3를 직접 작성하여 입력할 수 있도록도 하자.
    public DanmakuShape danmakuShape;           // 탄막 모양의 타입
    // b-2. 거의 모든 모양에서 사용할 변수들
    public float initDistance;                  // 모든 탄막에 대한 생성거리의 기준
                                                // 기준 거리에 대한 랜덤성 부여. 여유가 되면 작성.
                                                // 이 랜덤성을, 모든 탄막에 동일부여할지, 각 탄막에 따로 부여할지의 여부.
    public int numPerShot;                      // 한번 발사에 사용되는 탄막 갯수. 
    // 참고: 일부 Shape들()에 대해서는 numPerShot으로 해결이 되기 때문에 이러한 형태들은 b-3항목 불필요.
    // b-3. 탄막 모양에 따라 선택적 변수들(이후, 조건부로 Inspector에 보여주는 것이 과제)
    public float shotVerticalDistance;          // Circle: 원의 면과 보스의 수직거리
    public int shotVerticalNum;                 // Sphere: 구의 '단' 갯수
                                                // Cone: 허용각도. 얘는 자료형을 뭘로 해야할지 모르겠음.
                                                // 전체 모양의 회전을 틀어버릴 요소(정해진 값)
                                                // 전체 모양의 회전을 틀어버릴 값의 랜덤 여부. true라면 위 값을 범위로 사용. // 이 두 랜덤변수는 a-plug에서 커버 가능한 부분으로 보임. 삭제 예정

    // b-99. 유저 커스텀 입력
    // 유저입력1. 원하는 범위에 a.N개를 균일배치(어려울듯), b.N개를 랜덤배치
    //            원하는 범위는... 일단 x, y, z의 범위? 이것만으로는 마음엔 들진 않을 듯.(이 방식으론 직육면체 밖에 불가능)
    //            그래프의 형태로 입력받아 활용할 수 있을 것 같지만 난이도가 있을 듯 하다.
    // 유저입력2. 완전한 위치들의 리스트를 전달받기




    // 탄막의 방향 : 일단 주체기준으로 밖으로 퍼지도록 Outer로 설정하여 테스트
    public DanmakuToDirection danmakuToDirection;

    // 2. 이동 ---------------------------------//------------------------------------------------------------------
    // 탄막 자체의 세팅
    public float initSpeed;                     // 시작속도. 일단은 정속으로 테스트, 추후 수정.
    public Vector3 initDirection;               // 시작방향. 일단 보는방향으로 테스트, 추후 수정.
                                                // 변속정보.
                                                // 변향정보. 플레이어에 유도 등 여러가지 요인으로 변수 추가 가능성 높음.
                                                // 변속정보(불연속) 리스트
                                                // 변향정보(불연속) 리스트
                                                // 나중에 필요하면 이어서 추가

    // 3. 클론 ---------------------------------//------------------------------------------------------------------
    public NextPatternMethod nextPatternMethod; // 하위 탄막을 생성의 조건.
                                                // 타이머일 경우, 그 시간
                                                // UserTrigger일 경우, 이벤트 구독
                                                // 마찬가지로 테스트 이후 필요한만큼 추가

    // 4. 반환 ---------------------------------//------------------------------------------------------------------
    public ReleaseMethod releaseMethod;         // Pool 반환의 조건.
    public float releaseTimer;                  // 방법1. 반환까지의 타이머. 일단 이거로 테스트.
                                                // 방법2. 충돌체크. Ground를 만날 시 반환 여부. 이벤트 감지 로직은 각 탄막에서보다 Ground에서 작성하는 것이 자원을 아낄 수 있을 것으로 보임.
                                                // 방법3. 하위 탄막의 모든 세트 생성을 끝마친 경우
                                                // 방법4. 주체의 트리거(구독)

    // 그리고 이 모든것을 하나의 뭉치로하여, 하위 탄막에 전해주거나 할 것으로 일단 보임.
    // 하위 탄막에 전해줄 내용 : 뭉탱이.
    // 하위 탄막이 뭉탱이를 언패킹하여, 위의 내용을 모두 적용, 하위 뭉탱이가 있으면 이를 반복.
}

public enum PosDirection
{
    World,              // 주체 또는 플레이어의 방향과 무관계한
    Look,               // 주체가 바라보는
    LookPlayer,         // 주체가 플레이어를 바라볼 경우
    CompletelyRandom,   // 완전히 랜덤한 방향으로
}

public enum PosDirectionRandomType
{
    Line,               // 직선 범위에서 랜덤
    Plane               // 평면 범위에서 랜덤
}

public enum DanmakuToDirection
{
    World,              // 탄막의 방향과 무관계한
    Outer,              // 주체와 반대방향
    LookPlayer,         // 탄막이 플레이어를 바라보도록
    CompletelyRandom,   // 완전히 랜덤한 방향으로
}
public enum NextPatternMethod
{
    Timer,              // 특정 시간 뒤 터뜨리기
    WithRelease,        // 반환과 함께 터뜨리기(삭제예정)
    UserTrigger,        // Manager에서 트리거 관리. 트리거 작동 시, 구독한 탄막들 터뜨리기.
}
public enum ReleaseMethod
{
    Timer,              // 특정 시간 뒤 터뜨리기
    WithRelease,        // 반환과 함께 터뜨리기(삭제예정)
    UserTrigger,        // Manager에서 트리거 관리. 트리거 작동 시, 구독한 탄막들 터뜨리기.
}
public enum DanmakuShape
{
    Linear,             // 가장 단순한 선형 사출
    Circle,             // 원형 (참고: 플레이어를 본 방향으로 원형으로 만들어 Enemy->Player 벡터로 방향을 주거나, 무작위 방향으로 원형 바깥방향으로 사출하면 자연스러울 듯.)
    Sphere,             // 구형
    Cube,               // 큐브형태. (참고: 레퍼런스 있음)
    Custom,             // 유저 입력을 받아 모양을 커스텀. Vector3리스트의 깡 입력으로 여러가지 모양을 만들 수도 있도록.
}

해당 SO 정보를 읽어, Enemy가 SO세팅에 맞춘 공격을 할 수 있도록 해야겠다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "Phases", menuName = "DanmakuSO/Phase", order = 1)]
public class PhaseSO : ScriptableObject
{
    [System.Serializable]
    public class PatternHierarchy
    {
        public PatternSO patternSO;                         // 참조할 PatternSO
        public string patternName;                          // 실행할 패턴의 이름. PatternSO 에서 
        public float startTime;                             // 사이클 중 패턴이 시작할 시간
        public float cycleTime;                             // 하위 패턴들을 굴릴 사이클의 전체 시간
        public List<PatternHierarchy> subPatterns;          // 하위 패턴 목록
    }

    public float cycleTime;                                 // 하위 패턴들을 굴릴 사이클의 전체 시간
    public List<PatternHierarchy> hierarchicalPatterns;     // 계층 구조

    // Todo.
    // 여기 구조 다시 한 번 생각 해 봐야함. PatternSO를 참조하기보다 긁어와서 커스텀 할 수 있어야 할 것.
    // PatternSO는 프리셋 모음이라는 것을 다시 한 번 상기하기
}

PhaseSO에서 PatternSO의 요소를 재귀적으로 아이템을 가질 수 있도록 구성하였다.

현재까지의 진행상황에 더불어, 파라미터를 제대로 전달하기 위한 장치를 구현해야한다.

Pool에 등록된 탄막의 DanmakuController.cs에서 OnEnable사용에 인해 예견된 문제 발생

아직 관련된 파라미터도 갖고있지 않으면서, 게임시작 시 한 차례 실행을 시도하여 오류가 발생한다.
추후 작업을 통해 해결을 해야 할 듯 하다.

반응형