2D 콘텐츠 제작

팀 프로젝트 골드메탈 슈팅게임 [#1]

송현호 2023. 10. 13. 11:46

↑동료(1명)와 함께 svn을 사용하여 골드메탈님의 슈팅게임을 만들어 보기로 했다.

 

먼저 팀원과 R&D를 해서 어떤 걸 할지 정했다.

그리고 팀원은 애니메이션, 배경 스크롤링 등을 담당하였고 나는 캐릭터/적기의 이동, 총알생성, 충돌반응을 담당하였다.

 

먼저 플레이어의 공격과 이동은 코루틴으로 작성하였고 카메라 메인의 뷰포트 함수를 이용하여 플레이어가 화면밖으로 나가지 않도록 제한했다. 이 부분은 전에 써놓은 코드가 있어서 그렇게 오래 걸리지 않았다.

 

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

namespace Chaosmoney8
{
    public class Player : MonoBehaviour
    {
        [SerializeField]
        private float speed = 0f;
        [SerializeField]
        private GameObject bullet;

        private Rigidbody2D rb;
        private Animator anim;

        private bool attackDelay = false;

        void Start()
        {
            this.rb = GetComponent<Rigidbody2D>();
            this.anim = GetComponent<Animator>();

            StartCoroutine(CoMove());
            StartCoroutine(CoAttack());
        }

        // Update is called once per frame
        void Update()
        {
        }

        private IEnumerator CoMove()
        {
            while (true)
            {
                //카메라뷰로 이동제한
                Vector3 worldPos = Camera.main.WorldToViewportPoint(this.transform.position);
                if (worldPos.x < 0.1f) worldPos.x = 0.1f;
                if (worldPos.x > 0.9f) worldPos.x = 0.9f;
                if (worldPos.y < 0.05f) worldPos.y = 0.05f;
                if (worldPos.y > 0.95f) worldPos.y = 0.95f;
                this.transform.position = Camera.main.ViewportToWorldPoint(worldPos);

                //키보드 화살표로 방향 입력
                var h = Input.GetAxisRaw("Horizontal");
                var v = Input.GetAxisRaw("Vertical");

                //이동 애니메이션
                if (h > 0.1f)
                {
                    this.anim.SetTrigger("Right");
                }
                else if (h < -0.1f)
                {
                    this.anim.SetTrigger("Left");
                }
                else
                {
                    this.anim.SetTrigger("Idle");
                }

                Vector2 moveDir = new Vector2(h, v);
                Vector2 moveSpeed = moveDir.normalized * Time.deltaTime * speed;

                this.rb.velocity = moveSpeed;
                yield return null;
            }
        }

        private IEnumerator CoAttack()
        {
            while (true)
            {
                // 어택 딜레이 false일시 공격 가능
                if (Input.GetKey(KeyCode.Space) && this.attackDelay == false)
                {
                    var pos = this.transform.position + new Vector3(0, 0.5f, 0);
                    GameObject go = Instantiate(bullet, pos, bullet.transform.rotation);

                    this.attackDelay = true; // 공격 비활성화

                    // 0.5초후 어택딜레이 false
                    yield return new WaitForSeconds(0.25f);
                    this.attackDelay = false;
                }
                yield return null;
            }
        }

        private void OnTriggerEnter2D(Collider2D collision)
        {
            if(collision.tag == "Enemy")
            {
                Destroy(collision.gameObject);
            }
        }
    }
}

 

그리고 만들다보니 이걸 어떻게 합쳐야 할지 고민이 되었다. 팀원과 상담을 해서 스크립트 폴더에 각자 이름으로 폴더를 만든 뒤 네임스페이스를 활용해서 서로 스크립트를 작성하고 나중에 합치는 식으로 하기로 했다.

 

그리고 적기 같은 경우엔 마찬가지로 이동은 코루틴으로 작성하였고 랜덤한 위치에서 생성해서 내려오는 식으로 하였다. 그리고 적기의 종류는 A,B,C가 있는데 EnemyA,B,C 에 Enemy스크립트를 상속받아서 사용하였다.

 

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

namespace Chaosmoney8
{
    public class Enemy : MonoBehaviour
    {
        [SerializeField]
        private float speed = 2;
        [SerializeField]
        protected int hp;
        private Animator anim;
        protected virtual void Start()
        {
            this.anim = GetComponent<Animator>();
            this.transform.position = new Vector3(Random.Range(-2.6f, 2.6f), 8, this.transform.position.z);
            StartCoroutine(CoMove());
        }

        private IEnumerator CoMove()
        {
            while (true)
            {
                //Debug.Log("이동");
                var moveDir = speed * Time.deltaTime * Vector2.down;
                this.transform.Translate(moveDir);
                if(this.transform.position.y < -6f)
                {
                    Destroy(this.gameObject);
                }
                yield return null;
            }
            
        }

        private void OnTriggerEnter2D(Collider2D collision)
        {
            if(collision.tag == "Bullet")
            {
                this.anim.SetTrigger("Hit");
                --hp;
                if(hp == 0)
                {
                    // 게임 매니저로 Die 대리자 호출
                    // 게임 매니저에서 적 삭제, 폭발 이펙트 생성
                    Debug.Log("Die");
                }
                Destroy(collision.gameObject);
            }
        }
    }
}

 

만들다 보니 느낀 점은 구현보다는 팀원과 상의하는게 더 신경써야할게 많았던 것 같다. 그래도 문제가 되는 부분은 서로 상의를 많이 하다보니 해결되었고 역할 분담을 잘하는게 중요하다는 걸 깨달았다.