게임 개발 일지/유니티 엔진 공부

33. 유니티 2D 종스크롤 슈팅 - 따라다니는 보조무기 만들기

인텔리킴 2024. 6. 9. 19:20

초기 세팅

팔로워 스프라이트 및 총알 프리팹 생성

 

스크립트 작성

using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using UnityEngine;

public class Follower : MonoBehaviour
{
    public GameObject bullet;
    public float curShotDelay;
    public float maxShotDelay;
    public ObjectManager objectManager;

    void Update()
    {
        Follow();
        Fire();
        Reload();
    }

    void Follow()
    {
        
    }

    void Fire()
    {
        if (!Input.GetButton("Fire1"))
            return;
        //maxShotDelay 만큼 총알이 장전되지 않았다면 발사 X
        if (curShotDelay < maxShotDelay)
            return;
        GameObject bullet = objectManager.MakeObject("BulletFollower");
        bullet.transform.position = transform.position;
        Rigidbody2D rigid = bullet.GetComponent<Rigidbody2D>();
        rigid.AddForce(new Vector2(0, 10.0f), ForceMode2D.Impulse);
               
        //발사하고 나선 curShotDelay 초기화
        curShotDelay = 0;
    }

    void Reload()
    {
        curShotDelay += Time.deltaTime;
    }
}

대부분의 코드는 Player 스크립트 참조

보조무기는 플레이어를 따라다니기 때문에 Move함수가 아닌 Follow 함수를 이용해서 작성

ObjectManager에 타겟풀 작성

 

    public Vector3 followPos;
    public int followDelay;
    public Transform parent;
    public Queue<Vector3> parentPos;

퍼블릭 변수로 벡터, 딜레이, 부모의 위치, 큐를 삽입함

void Watch()
{
    followPos = parent.position;
}
void Follow()
{
    transform.position = followPos;
}

유저를 따라오게 함

 

플레이어 따라옴

플레이어 따라오지만 너무 가까움

 

void Watch()
{
    //Enqueue() 큐에 데이터 저장
    //DeQueue() 큐에서 첫 데이터 삭제하는 동시에 반환
    parentPos.Enqueue(parent.position);
    //Queue : FIFO 방식
    //queue.Count : 큐 갯수 세기
    if(parentPos.Count > followDelay )
    {
        followPos = parentPos.Dequeue();
    }
}
void Follow()
{
    transform.position = followPos;
}

위 코드를 사용하면 큐에 들어간 플레이어의 위치를 followDelay만큼의 딜레이 후에 

플레이어를 따라감

 

팔로우

하지만 이 경우에도 플레이어의 위치로 바로 따라온다는 문제가 있음

 

void Watch()
{
    //부모의 위치가 가만히 있으면 저장하지 않도록 조건 추가
    //이미 부모의 위치가 큐안에 있으면 실행 X 없으면 실행
    if(!parentPos.Contains(parent.position))
        //Enqueue() 큐에 데이터 저장
        //DeQueue() 큐에서 첫 데이터 삭제하는 동시에 반환
        parentPos.Enqueue(parent.position);
    //Queue : FIFO 방식
    //queue.Count : 큐 갯수 세기
    if(parentPos.Count > followDelay )
    {
        followPos = parentPos.Dequeue();
    }
    //큐가 모두 채워지기 전까지는 부모의 위치를 적용
    else if(parentPos.Count < followDelay)
    {
        followPos = parent.position;
    }
}

부모가 가만히 있다면 더이상 움직이지 않도록하고 

큐를 모두 채우기 전까지는 부모의 위치를 그대로 적용시킴

 

적용 결과

적당한 딜레이 후 부모의 위치를 따라옴

 

플레이어 파워 적용

플레이어의 파워가 일정량 이상 넘어가면 보조무기가 나오도록 변경

void AddFollower()
{
    if (power == 4) 
        followers[0].SetActive(true);
    else if(power == 5)
            followers[1].SetActive(true);
    else if (power == 6)
        followers[2].SetActive(true);
}

 

파워가 강해질 떄마다 팔로워가 더 생기게 변경

팔로워 1의 부모
팔로워 2의 부모

줄줄이 따라오도록 부모 오브젝트를 설정

 

default:
    GameObject bullet3R = objectManager.MakeObject("BulletPlayerA");
    bullet3R.transform.position = transform.position + new Vector3(0.2f, 0);
    GameObject bullet3L = objectManager.MakeObject("BulletPlayerA");
    bullet3L.transform.position = transform.position + new Vector3(-0.2f, 0);
    GameObject bullet3Middle = objectManager.MakeObject("BulletPlayerB");
    bullet3Middle.transform.position = transform.position + new Vector3(0f, 0.05f);
    Rigidbody2D rigid3R = bullet3R.GetComponent<Rigidbody2D>();
    Rigidbody2D rigid3L = bullet3L.GetComponent<Rigidbody2D>();
    Rigidbody2D rigid3Middle = bullet3Middle.GetComponent<Rigidbody2D>();
    rigid3R.AddForce(new Vector2(0, 10.0f), ForceMode2D.Impulse);
    rigid3L.AddForce(new Vector2(0, 10.0f), ForceMode2D.Impulse);
    rigid3Middle.AddForce(new Vector2(0, 10.0f), ForceMode2D.Impulse);
    break;

스위치 문의 case 3의 경우를 default 상태로 변경

* default : 위쪽 케이스에 모두 해당하지 않을 경우 적용되는 case

 

플레이어를 쫓아오며 발사