[타워디펜스게임] #3. 타일 생성 & 유닛 배치

치치·2024년 11월 19일
0

타워디펜스게임

목록 보기
3/18
post-thumbnail

📌 Grid 생성

  • 2d sprite square을 씬에 배치한 후 Vertical Layout Group으로 위치 잡고 맞춰줌
  • 반드시 Box Collider2D가 부착되어야 함

  • 생성된 객체들 Grid로 묶어줌
  • 각각의 객체들에게 Tile스크립트 부착

📌 Tile 스크립트 전체보기

  • 타일에 유닛이 들어왔는지 아닌지 체크하는 bool변수
public class Tile : MonoBehaviour
{
    public bool hasUnits;
}

📌 유닛목록창 & 유닛창


  • Units 게임오브젝트에는 Horizontal Layout Group으로 가로 정렬
  • Canvas창의 Canvas Scaler의 크기를 화면 사이즈와 동일하게 맞춰주면 해상도가 바뀌어도 UI크기 일정하게 유지

📌 UnitSlot 스크립트 전체보기

  • Unit오브젝트에 부착될 스크립트
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;


public class UnitSlot : MonoBehaviour
{
    public Sprite unitSprite; // 유닛 이미지

    public GameObject unitObject; // 유닛 객체

    public int cost;

    public Image icon; // 유닛 이미지

    public TextMeshProUGUI costText;

    // GameManager 스크립트
    private GameManager gameManager;

    private void Start()
    {
        gameManager =
            GameObject.Find("GameManager").GetComponent<GameManager>();
        
            GetComponent<Button>().onClick.AddListener(BuyUnit);
    }

    private void BuyUnit()
    {
        gameManager.BuyUnit(unitObject, unitSprite);
    }

    public void OnValidate()
    {
        if(unitSprite) // Sprite가 있다면
        {
            icon.enabled = true;
            icon.sprite = unitSprite;
            costText.text = cost.ToString();
        }
        else
        {
            icon.enabled = false;
        }
    }


}

🔒 UnitSlot 스크립트 부분으로 보기

  • unitSlot안에 보일 유닛 이미지 & 실제 배치 될 객체 -> unitSprite , unitObject
public Sprite unitSprite; // 유닛 이미지

public GameObject unitObject; // 유닛 객체

public int cost;

public Image icon; // 유닛 이미지

public TextMeshProUGUI costText;
  • 유닛을 타일에 배치하는 데 관여하는 GameManager 스크립트 가져오기
// GameManager 스크립트
private GameManager gameManager;
  • Start함수에서 GameObject.Find를 사용해 GameManager라는 이름을 가진 게임오브젝트에 부착된 스크립트 가져오기

  • ✅ 유닛 구입 버튼기능

private void Start()
{
    gameManager =
        GameObject.Find("GameManager").GetComponent<GameManager>();
    
        GetComponent<Button>().onClick.AddListener(BuyUnit);
}
  • gameManager스크립트의 BuyUnit함수 가져와서 사용
private void BuyUnit()
{
    gameManager.BuyUnit(unitObject, unitSprite);
}
  • ✅ Sprite가 있다면 Unit의 icon 프로퍼티 활성화
public void OnValidate()
{
    if(unitSprite) // Sprite가 있다면
    {
        icon.enabled = true;
        icon.sprite = unitSprite;
        costText.text = cost.ToString();
    }
    else
    {
        icon.enabled = false;
    }
}

📌 GameManager 스크립트 전체보기

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

public class GameManager : MonoBehaviour
{
    public GameObject currentUnit;

    public Sprite currentUnitSprite;

    public Transform tiles;

    public LayerMask tileMask;

    public void BuyUnit(GameObject unit, Sprite sprite)
    {
        currentUnit = unit;
        currentUnitSprite = sprite;
    }

    private void Update()
    {
        RaycastHit2D hit =
        Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), 
        Vector2.zero, Mathf.Infinity, tileMask);

        // 반복문으로 타일 가져오고 비활성화
        foreach(Transform tile in tiles)
        {
            tile.GetComponent<SpriteRenderer>().enabled = false;
        }

        // 콜라이더와 유닛이 충돌한다면
        if(hit.collider && currentUnit)
        {

            // Sprite가져오고 컴포넌트 활성화
            hit.collider.GetComponent<SpriteRenderer>().sprite = currentUnitSprite;
            hit.collider.GetComponent<SpriteRenderer>().enabled = true;
            
            if (Input.GetMouseButtonDown(0) && !hit.collider.GetComponent<Tile>().hasUnits)
            {
                Instantiate(currentUnit,
                    hit.collider.transform.position, Quaternion.identity);

                hit.collider.GetComponent<Tile>().hasUnits = true;
                
                currentUnit = null;
                currentUnitSprite = null;
            
            }
        }

    }
}

📌 GameManager 스크립트 부분으로 보기

  • 현재 유닛의 게임오브젝트 & 현재유닛의 Sprite
  • 타일의 위치값
  • LayerMask 사용 -> 처리하고 싶은 객체의 레이어 지정

public GameObject currentUnit;

public Sprite currentUnitSprite;

public Transform tiles;

public LayerMask tileMask;
  • 유닛을 구입하기 위한 함수
  • 현재 유닛의 게임오브젝트와 현재유닛의 Sprite에 매개변수 넣어주기
public void BuyUnit(GameObject unit, Sprite sprite)
{
    currentUnit = unit;
    currentUnitSprite = sprite;
}

GameManager에 선언한 함수가 public이기 때문에 다른 클래스에서 사용 가능

  • [UnitSlot] 클래스의 스크립트

private void Update함수부분

  • RaycastHit2D를 사용하여 드래그 방식을 구현
  • 레이케스트에 의해 충돌된 객체와 관련된 정보를 담고 있음
  • Ray(광선)과 부딪힌 오브젝트(객체)가 있는지 체크

    Physics2D.Raycast(시작좌표, Ray방향 & 크기, LayerMask);

    ✅ 여기서 Ray 란?
    -> 특정좌표에서 방향과 길이를 가진 광선

private void Update()
{
    RaycastHit2D hit =
    Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), 
    Vector2.zero, Mathf.Infinity, tileMask);
  • foreach -> tile 모두를 다 가져온 뒤 프로퍼티 비활성화
// 반복문으로 타일 가져오고 비활성화
foreach(Transform tile in tiles)
{
    tile.GetComponent<SpriteRenderer>().enabled = false;
}
  • hit의 콜라이더와 현재유닛이 충돌한다면 -> 스프라이트 활성화 & 프로퍼티 활성화

  • 마우스를 클릭하고 타일의 hasUnits함수가 False라면 -> 현재유닛 생성**

  • 현재 유닛을 생성한 뒤 hasUnits를 True로 하여 그 타일에는 유닛이 배치되어있음을 나타냄

  • 현재유닛 & 현재유닛 스프라이트 초기화

// 콜라이더와 유닛이 충돌한다면
if(hit.collider && currentUnit)
{

    // Sprite가져오고 컴포넌트 활성화
    hit.collider.GetComponent<SpriteRenderer>().sprite = currentUnitSprite;
    hit.collider.GetComponent<SpriteRenderer>().enabled = true;
    
    if (Input.GetMouseButtonDown(0) && !hit.collider.GetComponent<Tile>().hasUnits)
    {
        Instantiate(currentUnit,
            hit.collider.transform.position, Quaternion.identity);

        hit.collider.GetComponent<Tile>().hasUnits = true;
        
        currentUnit = null;
        currentUnitSprite = null;
    
    }
}

게임 실행결과

  • 유닛을 클릭하면 유닛의 스프라이트가 활성화되고 타일에 배치하게 되면 실제 오브젝트와 이미지가 배치

https://youtu.be/8Ms2ws6iRy4


2024.11.13.수요일

profile
뉴비 개발자

0개의 댓글