K-digital traning/Final Project

Gazzlers 개발일지 - Map생성(3)

내꺼블로그 2023. 11. 22. 15:18

 

현재 구현상태에서는 아직 player가 깔아놓은 rail을 따라가지 못하고 있다.

player의 경로 이동을 구현하기 위해 각각의 railPrefab에 경로를 지정한 뒤 그 경로를 player에게 전달하여 player가 이를 따라가는 방식으로 구현해보고자 한다.

 

 

 

 

 

rail 경로 지정

 

 

 

 

 

 

 

 

 

 

 

 

 

Rail.cs를 새로 작성하고 기존 Script 중의 일부를 수정하는 작업을 거쳤다.

 

+수정

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

    public class Rail : MonoBehaviour
    {
        public enum eType
        {
            Left = 0, Middle = 1, Right = 2
        }
        private int value;
        public int Value { get { return value; } }

        public eType type;
        [SerializeField] Transform[] arrRoute;

        void Start ()
        {
            switch (type)
            {
                case eType.Left:
                    value = 4;
                    break;
                case eType.Middle:
                    value = 0;
                    break;
                case eType.Right:
                    value = -4;
                    break;
            }
        }

        public Transform[] GetRoute()
        {
            return this.arrRoute;
        }
    }

 

 

 

 

 

 

 

 

각각의 RailPrefab에 Rail.cs를 부착하였다.

Rail.cs에는 각각의 rail 종류를 알려주는 railType과 그들이 가지고 있는 경로에 대한 정보를 저장하고 있는 routeTrans 배열을 구현하였다.

GetRoute는 CamMove.cs가 player가 지나갈 경로를 얻기 위해 구현한 Method이다.

 

 

 

 

 

Rail.cs에 type을 구현하였기 때문에 RailPoolManager에 구현했던 enum eType을 제거하였다.

 

 

 

 

 

 

 

MapController.cs의 코드 일부 역시 수정되었다.

기존 queueRail의 저장타입을 rail의 type과 gameObject에서 각각의 rail이 가지고 있는 Rail 클래스로 수정하였다.

stack 역시 저장할 타입을 RailPoolManager.eType에서 Rail.eType으로 수정하였다.

 

 

 

player의 경로 갱신을 위해 MapController가 Rail을 설치할 때마다 TestMapMain에게 Rail 정보를 전달한다.

 

 

 

 

 

TestMapMain은 camMove에게 rail에 저장되어있는 route 배열들을 전달한다.

 

 

 

 

player가 경로를 받기 전에는 Move()가 호출되지 않도록 isReady로 관리하도록 구현하였다.

 

 

 

 

 

 

UpdateRoute는 경로를 전달받는 method로 전달받은 경로는 queueRouteTrans에 enqueue되어 관리된다.
Move는 player의 움직임을 관리하는 method로 player는 지정해놓은 경로를 향해 회전하면서 이동한다.

지정해놓은 경로의 position.z값이 player의 position.z값보다 클 경우(player가 경로를 지나칠 경우) queueRouteTrans.Dequeue를 하여 지나간 경로를 제외시킨다.

 

 

 

전체코드

Rail.cs(위 코드 그대로)

 

 

 

MapController.cs

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

    public class MapController : MonoBehaviour
    {
        [SerializeField] private GameObject floorPrefab;
        [SerializeField] private Transform playerTrans;
        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;

        public void Init()
        {
            this.count = (int)(offset / dis * 2)+1;
            this.InitFloor();
            this.InitRail();
        }

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

        private void UpdateMap()
        {
            while (queueFloor.Count > 0 && queueFloor.Peek().transform.position.z > +playerTrans.position.z + this.offset + this.dis)
            {
                GameObject floorGo = queueFloor.Dequeue();
                this.UnInstallRail();
                Vector3 pos = lastFloorTrans.position + Vector3.forward * -this.dis;
                floorGo.transform.position = pos;
                railPos = pos + Vector3.right * this.CaculateRailOffset();
                //Debug.LogFormat("<color=cyan>railPos: {0}</color>", railPos);
                this.InstallRail();
                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 InitRail()
        {
            RailPoolManager.Instance.Init(this.count);
            for(int i = 0; i < this.count; i++)
            {
                float railOffset = this.CaculateRailOffset();
                railPos = playerTrans.position + Vector3.forward * (offset - i * this.dis) + Vector3.right * railOffset;
                if (i == this.count / 2)
                    this.onInformInitPos(railPos);
                this.InstallRail();
            }
        }
        private float CaculateRailOffset()
        {
            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 < 3)                   //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 < 6)              //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.EnbaleLRail();
            Rail rail = go.GetComponent<Rail>();
            queueRail.Enqueue(rail);
            go.transform.position = this.railPos;
            this.onInformRoute(rail);
            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.EnbaleMRail();
            Rail rail = go.GetComponent<Rail>();
            queueRail.Enqueue(rail);
            go.transform.position = this.railPos;
            this.onInformRoute(rail);
            //Debug.LogFormat("<color=yellow>stack count:{0}</color>", stackRail.Count);
        }

        private void InstallRRail()
        {
            GameObject go = RailPoolManager.Instance.EnbaleRRail();
            Rail rail = go.GetComponent<Rail>();
            queueRail.Enqueue(rail);
            go.transform.position = this.railPos;
            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();
            switch(rail.type)
            {
                case Rail.eType.Left:
                    RailPoolManager.Instance.DisableLRail(rail.gameObject);
                    break;
                case Rail.eType.Middle:
                    RailPoolManager.Instance.DisableMRail(rail.gameObject);
                    break;
                case Rail.eType.Right:
                    RailPoolManager.Instance.DisableRRail(rail.gameObject);
                    break;
            }
        }
    }

 

 

 

 

TestMapMain.cs

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

    public class TestMapMain : MonoBehaviour
    {
        [SerializeField] private MapController mapController;
        [SerializeField] private CamMove camMove;
        // Start is called before the first frame update
        void Start()
        {
            Vector3 camPos = Vector3.zero;
            this.mapController.onInformInitPos = (pos) =>
            {
                camPos = pos;
            };
            this.mapController.onInformRoute = (rail) =>
            {
                this.camMove.UpdateRoute(rail.GetRoute());
            };
            this.mapController.Init();
            this.camMove.Init(camPos);
        }
    }

 

 

 

 

 

CamMove.cs

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

    public class CamMove : MonoBehaviour
    {
        [SerializeField] private GameObject player;
        private Queue<Transform> queueRouteTrans = new Queue<Transform>();
        private Transform curDestTrans;
        private bool isReady;
        public float rotSpeed = 1f;
        public float moveSpeed = 1.5f;
        // Update is called once per frame

        public void Init(Vector3 pos)
        {
            this.player.transform.position = pos;
            isReady = true;
        }

        void Update()
        {
            if (!isReady) return;
            this.Move();
        }

        private void Move()
        {
            Vector3 destPos = this.queueRouteTrans.Peek().position;
            while (destPos.z > this.player.transform.position.z)
            {
                Transform trans = this.queueRouteTrans.Dequeue();
                //Debug.Log(trans.gameObject.name);
                destPos = this.queueRouteTrans.Peek().position;
                curDestTrans = this.queueRouteTrans.Peek();
            }
            //this.player.transform.LookAt(curDestTrans);
            Vector3 dir = curDestTrans.position - this.player.transform.position;
            this.player.transform.rotation = Quaternion.Lerp(this.player.transform.rotation, Quaternion.LookRotation(dir), Time.deltaTime * this.rotSpeed);
            this.player.transform.Translate(Vector3.forward * this.moveSpeed * Time.deltaTime);            
        }

        public void UpdateRoute(Transform[] routes)
        {
            foreach (var route in routes)
            {
                queueRouteTrans.Enqueue(route);
            }
        }
    }

 

 

 

 

 

 

 

 

결과

 

 

심하게 어설프긴 하다만,,,,(ㅠ) 잡아놓은 경로들의 위치를 다시 설정하면 될 것 같다,,,