Unity - 2D 종스크롤 슈팅 : 따라다니는 보조 무기 만들기

TXMAY·2023년 10월 12일
0

Unity 튜토리얼

목록 보기
31/33
post-thumbnail

이번 강좌는 따라다니는 보조 무기 만들기에 관한 강좌다.


준비하기

'Follower' 스프라이트를 배치한다.
그리고 'Player Bullet A' 프리펩을 복사하여 'Follower Bullet'으로 만들고 스프라이트와 Collider를 변경한다.

기본 작동 구현

'Follower.cs' 파일을 생성한 후, 다음과 같이 코드를 작성하고 추가한다.

// Follower.cs
using UnityEngine;

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

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

    void Follow()
    {

    }

    void Fire()
    {
        if (!Input.GetButton("Fire1"))
        {
            return;
        }
        if (curShotDelay < maxShotDelay)
        {
            return;
        }

        GameObject bullet = objectManager.MakeObj("BulletFollower");
        bullet.transform.position = transform.position;

        Rigidbody2D rigid = bullet.GetComponent<Rigidbody2D>();
        rigid.AddForce(Vector2.up * 10, ForceMode2D.Impulse);

        curShotDelay = 0;
    }

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

// ObjectManager.cs
...

public GameObject bulletFollowerPrefab;
...

GameObject[] bulletFollower;
...

void Awake()
{
    ...
    
    bulletFollower = new GameObject[100];
	...
    
}

void Generate()
{
    ...

    for (int index = 0; index < bulletFollower.Length; index++)
    {
        bulletFollower[index] = Instantiate(bulletFollowerPrefab);
        bulletFollower[index].SetActive(false);
    }
}

public GameObject MakeObj(string type)
{
    switch (type)
    {
        ...
        
        case "BulletFollower":
            targetPool = bulletFollower;
            break;
    }
    ...
    
}

public GameObject[] GetPool(string type)
{
    switch (type)
    {
        ...
        
        case "BulletFollower":
            targetPool = bulletFollower;
            break;
    }
	...
    
}

실행하면 플레이어처럼 총알을 발사한다.

팔로우 로직

다음과 같이 코드를 추가한다.

using System.Collections.Generic;
...

public class Follower : MonoBehaviour
{
    ...

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

    void Awake()
    {
        parentPos = new Queue<Vector3>();
    }

    void Update()
    {
        Watch();
        ...
        
    }

    void Watch()
    {
        if (!parentPos.Contains(parent.position))
        {
            parentPos.Enqueue(parent.position);
        }

        if (parentPos.Count > followDelay)
        {
            followrPos = parentPos.Dequeue();
        }
        else if (parentPos.Count < followDelay)
        {
            followrPos = parent.position;
        }
    }

    void Follow()
    {
        transform.position = followrPos;
    }
    ...
    
}
  • Enqueue(value) : 큐에 데이터를 저장하는 함수
  • Dequeue() : 큐의 첫 데이터를 빼면서 반환하는 함수
    실행하면 플레이어의 위치를 따라서 이동하게 된다.

파워 적용

'Player.cs'에 다음과 같이 코드를 추가하고 수정한다.

...

public GameObject[] followers;
...

void Fire()
{
    ...

    switch (power)
    {
        case 1:
            ...
            
        case 2:
            ...
            
        default:
            GameObject bulletRR = objectManager.MakeObj("BulletplayerA");
            bulletRR.transform.position = transform.position + Vector3.right * 0.25f;

            GameObject bulletCC = objectManager.MakeObj("BulletplayerB");
            bulletCC.transform.position = transform.position;

            GameObject bulletLL = objectManager.MakeObj("BulletplayerA");
            bulletLL.transform.position = transform.position + Vector3.left * 0.25f;

            Rigidbody2D rigidRR = bulletRR.GetComponent<Rigidbody2D>();
            Rigidbody2D rigidCC = bulletCC.GetComponent<Rigidbody2D>();
            Rigidbody2D rigidLL = bulletLL.GetComponent<Rigidbody2D>();
            rigidRR.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
            rigidCC.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
            rigidLL.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
            break;
    }
	...
    
}
...

void OnTriggerEnter2D(Collider2D collision)
{
    ...
    
    else if (collision.gameObject.tag == "Item")
    {
        ...
        
        switch (item.type)
        {
            ...
            
            case "Power":
                if (power == maxPower)
                {
                    score += 500;
                }
                else
                {
                    power++;
                    AddFollower();
                }
                break;
            ...
            
        }
        ...
        
    }
}
...

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);
    }
}

팔로워 오브젝트를 두 개 더 만든 후 비활성화하고 parent를 팔로워로 지정해 따라오게 만든다.
파워 아이템을 먹고 파워가 4 이상이 되면 팔로워가 생긴다.


뒤따라오는 메커니즘이 궁금했는데 이런 방식으로 구현하는 것을 알아서 좋았다.
버전에 따라 뒤따라오는 간격이 영상과 다를 수 있는데 딜레이를 늘리면 해결된다.

profile
게임 개발 공부하는 고양이

0개의 댓글