K-digital traning/Final Project

Gazzlers 개발일지 - Zeppelin 생성

내꺼블로그 2024. 1. 2. 18:32

구현할 부분

 

 

아이템 열기구(?) 게임씬에 붙이기.

 

 

 

https://lj9369.tistory.com/129

 

Gazzlers R&D - 아이템 비행체 구현

▼ 구현할 부분 ▼ 구현할 것 - 비행체를 레이로 조준하여 3번 맞추기 --> 비행체 사라지고 아이템 생성 - 생성된 아이템이 player쪽으로 이동 - 스코어 UI에 닿으면 아이템이 사라지고 스코어 점수

lj9369.tistory.com

 

이 부분에 관해서 R&D를 진행해주신 고마운 팀원님❤의 포스팅을 참고하여 제작해보겠습니댯ㅎ

 

 

 

 

 

 

(1) GameScene에 Zeppelin 생성

오브젝트 풀링 사용

 

ZeppelinPoolManager

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

    public class ZeppelinPoolManager : MonoBehaviour
    {
        [SerializeField] private GameObject zeppelinPrefab;
        private List<GameObject> listZeppelin = new List<GameObject>();

        public static ZeppelinPoolManager instance;
        private void Awake()
        {
            instance = this;
        }

        public void Init()
        {
            for(int i = 0; i < 10; i++)
            {
                GameObject go = this.GenerateZeppelin();
                go.SetActive(false);
            }
        }

        private GameObject GenerateZeppelin()
        {
            GameObject go = Instantiate(zeppelinPrefab, this.transform);
            this.listZeppelin.Add(go);
            return go;
        }

        public GameObject GetZeppelin()
        {
            GameObject result = null;
            for(int i=0;i<this.listZeppelin.Count;i++)
            {
                GameObject go = listZeppelin[i];
                if (go.activeSelf == false)
                {
                    go.transform.SetParent(null);
                    go.SetActive(true);
                    result = go;
                    break;
                }
            }
            if(result == null)
            {
                result = this.GenerateZeppelin();
                result.transform.SetParent(null);
            }
            return result;
        }

        public void ReturnZeppelin(GameObject go)
        {
            go.transform.SetParent(this.transform);
            go.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
            go.SetActive(false);
        }
    }

 

 

 

 

 

MapController에서 Zeppelin을 설치하도록 구현

 

 

 

ZeppelinPoolManager가 Zeppelin을 생성하도록 구현.

 

updatemap

MapController의 UpdateMap 함수 수정 부분.

3번(mod)에 한 번씩 zeppelin이 제거 및 설치되도록 구현.

 

 

 

InitRail함수를 InitRailAndZeppelin으로 수정

Rail을 설치할 때 Rail 근처로 Zeppelin이 설치되도록 구현.

이것도 역시 3번(mod)에 한번 꼴.

 

InstallZeppelin은 Zeppelin을 설치하는 함수.

Zeppelin의 생성 위치를 담당할 pos는 방금 설치된 Rail의 근처로 할당된다.

생성된 Zeppelin을 관리할 queueZeppelin에 생성된 zeppelinGo를 enqueue.

UninstallZeppelin은 설치한 zeppelin을 제거하는 함수.

 

결과

 

 

 

 

 

MapController

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


    public class MapController : MonoBehaviour
    {
        [SerializeField] private GameObject floorPrefab;
        [SerializeField] private Transform playerTrans;
        [SerializeField] private StructureManager structureManager;
        private Queue<GameObject> queueFloor = new Queue<GameObject>();
        private Queue<Rail> queueRail = new Queue<Rail>();
        private Stack<Rail.eType> stackRail = new Stack<Rail.eType>();
        private int maxStackSize = 3;
        public float offset = 112f;
        public float dis = 16f;
        private int count;
        private Transform lastFloorTrans;
        private Vector3 railPos;
        public System.Action<Vector3> onInformInitPos;
        public System.Action<Rail> onInformRoute;

        //------------------------------------------------------Zeppelin--------------------------------------------------
        private Queue<GameObject> queueZeppelin = new Queue<GameObject>();
        private int installZeppelin;
        private int mod = 3;
        //----------------------------------------------------------------------------------------------------------------


        public void Init()
        {
            //-----------------------------------------------Zeppelin----------------------------------------------------
            ZeppelinPoolManager.instance.Init();
            //-----------------------------------------------------------------------------------------------------------
            StructurePoolManager.Instance.InitStructure();
            this.count = (int)(offset / dis * 2) + 1;
            this.InitFloor();
            this.InitRailAndZeppelin();
        }

        void Update()
        {
            this.UpdateMap();
        }

        private void UpdateMap()
        {
            while (queueFloor.Count > 0 && queueFloor.Peek().transform.position.z > +playerTrans.position.z + this.offset)
            {
                GameObject floorGo = queueFloor.Dequeue();
                this.UnInstallRail();
                Vector3 pos = lastFloorTrans.position + Vector3.forward * -this.dis;
                floorGo.transform.position = pos;
                railPos = pos + Vector3.right * this.CalculateRailOffset();
                //Debug.LogFormat("<color=cyan>railPos: {0}</color>", railPos);
                this.InstallRail();
                //---------------------------------------------------------Zeppelin------------------------------------------
                if ((this.installZeppelin++ % mod) == 0)
                {
                    this.UnstallZeppellin();
                    this.InstallZeppelin();
                }
                //-----------------------------------------------------------------------------------------------------------
                queueFloor.Enqueue(floorGo);
                lastFloorTrans = floorGo.transform;
            }
        }

        private void InitFloor()
        {
            for (int i = 0; i < count; i++)
            {
                GameObject floorGo = Instantiate(floorPrefab);
                floorGo.transform.position = playerTrans.position + Vector3.forward * (offset - i * this.dis);
                queueFloor.Enqueue(floorGo);
                if (i == count - 1)
                    lastFloorTrans = floorGo.transform;
            }
        }

        private void InitRailAndZeppelin()
        {
            RailPoolManager.Instance.Init(this.count);
            for (int i = 0; i < this.count; i++)
            {
                float railOffset = this.CalculateRailOffset();
                railPos = playerTrans.position + Vector3.forward * (offset - i * this.dis) + Vector3.right * railOffset;
                if (railPos.z == 0)
                    this.onInformInitPos(railPos);
                if (railPos.z >= 0)
                {
                    this.InstallMRail();
                }
                else
                    this.InstallRail();
                //---------------------------------------Zeppelin-----------------------------------------------
                if ((this.installZeppelin++ % mod) == 0)
                    this.InstallZeppelin();
                //----------------------------------------------------------------------------------------------
            }
        }
        private float CalculateRailOffset()
        {
            float railOffset = stackRail.Count;
            if (railOffset > 0)
            {
                if (stackRail.Peek() == Rail.eType.Left)
                {
                    railOffset *= 4;
                }
                else
                {
                    railOffset *= -4;
                }
            }
            return railOffset;
        }

        private void InstallRail()
        {
            int rand = Random.Range(0, 10);
            if (rand < 2)                   //LRail
            {
                if (this.stackRail.Count == this.maxStackSize && this.stackRail.Peek() == Rail.eType.Left)
                {
                    //Debug.Log(stackRail.Peek());
                    this.InstallRRail();
                }
                else
                    this.InstallLRail();
            }
            else if (rand < 4)              //RRail
            {
                if (this.stackRail.Count == this.maxStackSize && this.stackRail.Peek() == Rail.eType.Right)
                    this.InstallLRail();
                else
                    this.InstallRRail();
            }
            else                            //MRail
            {
                this.InstallMRail();
            }
        }

        private void InstallLRail()
        {
            GameObject go = RailPoolManager.Instance.EnableRail((int)Rail.eType.Left);
            Rail rail = go.GetComponent<Rail>();
            queueRail.Enqueue(rail);
            go.transform.position = this.railPos;
            //structure 생성
            structureManager.InstallStructure(rail);

            //루트 알려주기
            this.onInformRoute(rail);

            //stack에 저장
            if (this.stackRail.Count == 0 || this.stackRail.Peek() == Rail.eType.Left)
            {
                stackRail.Push(Rail.eType.Left);
            }
            else if (this.stackRail.Peek() == Rail.eType.Right)
            {
                stackRail.Pop();
            }
            //Debug.LogFormat("<color=yellow>stack count:{0}</color>", stackRail.Count);
        }

        private void InstallMRail()
        {
            GameObject go = RailPoolManager.Instance.EnableRail((int)Rail.eType.Middle);
            Rail rail = go.GetComponent<Rail>();
            queueRail.Enqueue(rail);
            go.transform.position = this.railPos;

            structureManager.InstallStructure(rail);

            this.onInformRoute(rail);
            //Debug.LogFormat("<color=yellow>stack count:{0}</color>", stackRail.Count);
        }

        private void InstallRRail()
        {
            GameObject go = RailPoolManager.Instance.EnableRail((int)Rail.eType.Right);
            Rail rail = go.GetComponent<Rail>();
            queueRail.Enqueue(rail);
            go.transform.position = this.railPos;

            structureManager.InstallStructure(rail);

            this.onInformRoute(rail);
            if (this.stackRail.Count == 0 || this.stackRail.Peek() == Rail.eType.Right)
            {
                stackRail.Push(Rail.eType.Right);
            }
            else if (this.stackRail.Peek() == Rail.eType.Left)
            {
                stackRail.Pop();
            }
            //Debug.LogFormat("<color=yellow>stack count:{0}</color>", stackRail.Count);
        }

        private void UnInstallRail()
        {
            Rail rail = queueRail.Dequeue();
            RailPoolManager.Instance.DisableRail(rail.gameObject);
            structureManager.UninstallStructure();
        }

        //--------------------------------------------------------Zeppelin----------------------------------------------------
        private void InstallZeppelin()
        {
            GameObject zeppelinGo = ZeppelinPoolManager.instance.GetZeppelin();
            Vector3 pos = this.railPos + Vector3.right * Random.Range(-10f, 10f) + Vector3.up * 10f+Vector3.forward*Random.Range(-12f, -3f);
            zeppelinGo.transform.position = pos;
            this.queueZeppelin.Enqueue(zeppelinGo);
        }

        private void UnstallZeppellin()
        {
            GameObject zeppelinGo = this.queueZeppelin.Dequeue();
            ZeppelinPoolManager.instance.ReturnZeppelin(zeppelinGo);
        }
        //--------------------------------------------------------------------------------------------------------------------
    }

 

 

 

 

 

(2)Zeppelin 폭파 시 아이템 생성 및 이동

 

 

RightHandController

팀장님의 스크립트에 추가한 부분.(CoCheckImpact)

Zeppelin을 맞혔을 경우 ZeppelinController의 Hit을 호출.

 

 

 

ZeppelinController

 

zeppelin hp 할당.

 

Zeppelin 수명을 다하면 Disable.

 

 

 

ZeppelinPoolManager

 

queue에 존재하지 않는 disable 상태의 zeppelin을 get.

 

 

 

MapController

zeppelin이 폭발할 때 생성될 itemPrefab들을 저장할 배열 선언.

 

 

queue에 들어있는 zeppelin이 멀어질 경우 queue에서 삭제하는 방향으로 변경.

 

 

zeppelin이 죽을 경우 호출되는 die.

아이템 생성하는 코루틴 호출.

zeppelin.Init으로 초기화.

 

아이템 생성하는 함수

 

 

 

Item

 

 

기존 팀원님이 작성해주신 코드.

 

 

 

 

player의 position이 갱신되지 못하여 실패

 

 

 

 

 

업데이트 부분으로 이동

 

 

 

요상한 모양새,,,,,

=> Update에서 호출한 DOMove가 사라지지 않고 계속 남아있기 때문.

이에 시도한 방법 : ChangeEndValue

아래의 포스팅을 참고하여 제작.

 

 

https://blog.naver.com/dooya-log/221757539272

 

[Asset] Unity3D 'DOTween' 4 : 유동적인 목표값에는 ChangeEndValue - 재사용되는 트윈 최적화

※1편 : 기본 기능과 팁 ※ 2편 : Sequence와 팁 ※ 3편 : 트윈 옵션 값 설정 이번 포스팅에서는 여태까지...

blog.naver.com

 

 

 

 

 

Tweener 선언

 

 

Start에서 tweener 할당

 

 

 

Update에서 ChangeEndValue 사용

첫번째 인자값 : 목표지점(end value)

두번째 인자값 : 목표지점까지 가는데 걸리는 시간

세번째 인자값 : 현재 위치를 기점으로 시작할 것인지의 여부.

Restart : 다시 시작

duration을 계속 같은 값으로 두었을 경우 Item의 속도가 느려질 수 있으므로 duration-=Time.deltaTime으로 시간 줄이기.

Mathf.Clamp 사용하여 duration이 음수가 되는 것을 방지.(duration이 음수일 경우 duration값을 변화시키지 않겠다는 의미가 됨.)

 

 

 

 

player에 닿으면 destroy.

 

 

 

 

 

(3)Score 획득

 

 

 

 

 

point(팀원분의 스크립트)

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

public class point : MonoBehaviour
{
    public System.Action itemTrigger;

    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Item"))
        {
            Debug.LogFormat("<color=green>itemTrigger</color>");
            this.itemTrigger();
        }
    }
}

 

 

 

 

 

 

 

GameMain

 

 

itemTrigger가 발동하면(아이템을 획득하면) currScore가 증가.

 

 

Item

 

pointTrigger를 향해 아이템이 날아오는 것으로 변경.

 

 

 

결과