티스토리 뷰

반응형

Gamelog 20. 총알피하기 게임 만들기(4)

메인을 만들어본다. 사실 메인도 초보가 하기에 딱 좋다. 오히려 처음에 만들면서 만났던 이상한 에러들을 보여주고 싶은데, 재현을 할 수 있을지는 한 번 해보면서 나오면 따로 써보겠다.

 

Gamelog 20. 총알피하기 게임 만들기(4)

총알

  1. 캐릭터를 향해서 일자로 전진함
  2. 일정시간마다 계속 생성되며 점점 속도가 빨라짐
  3. 캐릭터와 닿으면 멈춤

Gamelog 20_1. 총알 캐릭터를 향하게 하기

기본세팅

유니티 Sorting Layer 설정하기

행성이 날라오는 것을 피하는 것처럼 표현하고자 한다.
따라서 별사탕 같은 이미지를 사용하였으며,
Scale은 캐릭터는 0.3, 0.3 이었으나 별사탕은 0.25, 0.25로 약간 더 작게 설정하였다.
그리고 Sorting LayerCharacters로 설정한다.

 

캐릭터에 향하게 하기

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

public class Direct_TargetObjtect : MonoBehaviour {
    public string targetObjectName; // 목표 오브젝트 이름 : Inspector에 지정
    private float speed = 1;

    GameObject targetObject;
    Rigidbody2D rbody;
    Vector3 dir;

    void Start() {
        targetObject = GameObject.Find(targetObjectName); // 목표 오브젝트를 찾아낸다

        // 중력을 0으로 해서 충돌 시에 회전시키지 않는다
        rbody = GetComponent<Rigidbody2D>();
        rbody.gravityScale = 0;
        rbody.constraints = RigidbodyConstraints2D.FreezeRotation;

        // 방향만 지닌 Vector로 변경한다.
        dir = (targetObject.transform.position - this.transform.position).normalized;
    }

    // 생성시 캐릭터가 있던 방향으로 움직인다.
    void FixedUpdate() {
        rbody.velocity = new Vector2(dir.x * speed, dir.y * speed);
    }
}

Direct\_TargetObject 스크립트를 생성한다.
targetObject는 Inspector에서 설정할 수 있도록 한다.

방향을 찾기 위해서는,
타겟 오브젝트의 위치에서 별사탕의 position을 제거하면 방향만 남게 되게 되는데
이때 normalized를 통해 같은 방향을 유지한 길이가 1.0인 벡터를 반환하게 되는 방식을 활용한다.
이전에 한 방식을 참고하였다. (게시글 바로가기)

유니티 컴포넌트 추가하기

이 스크립트를 별사탕에 컴포넌트로 추가하고, Target Obejct Name을 설정한다.
Rigidbody 2D 컴포넌트도 함께 추가한다.

유니티 캐릭터 방향으로 오브젝트 향하게 하기

캐릭터의 방향으로 움직이는 별사탕이 생성되었다.

 

Gamelog 20_2. 일정시간마다 생성되게 하기

먼저 사방에서 날라올 수 있도록 하기 위해 그 범위를 생성한다.

이 block 이미지를 활용하여 세팅을 해준다.
이 방법 외에도 다른 방법이 있을지 모르지만 이전 게시글에서 배운 방법을 응용해서 구현해보았다.

유니티 블록 패턴 복사하기

Block 오브젝트의 Draw ModeTiled로 설정하고, Sorting Layer를 BackGround로 설정했다.
그리고 메인카메라 밖에서 사방으로 둘러 별사탕을 생성할 것이다.

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

// 범위 내에 랜덤으로 프리팹을 만든다
public class Sometime_RandomCreatePrefab : MonoBehaviour {

    public GameObject newPrefab; // 만드는 프리팹 :Inspector에 지정한다
    public float intervalSec = 1; // 작성 간격(초):Inspector로에 지정한다

    void Start() {
      // 지정 초 수마다 CreatePrefab를 반복 실행하는 예약
        InvokeRepeating("CreatePrefab", intervalSec, intervalSec);
    }

    void CreatePrefab() {
        // 이 오브젝트의 범위 내에 랜덤으로
        Vector3 area = GetComponent<SpriteRenderer>().bounds.size;

        Vector3 newPos = this.transform.position;
        newPos.x += Random.Range(-area.x / 2, area.x / 2);
        newPos.y += Random.Range(-area.y / 2, area.y / 2);
        // 프리팹을 만든다
        GameObject newGameObject = Instantiate(newPrefab) as GameObject;
        newGameObject.transform.position = newPos;
    }
}

유니티 프리팹 설정하기

스크립트를 추가한 뒤 생성할 프리팹을 설정해준다.

프리팹은 Hierachy에서 Bomb를 프로젝트 뷰로 드래그하여 생성할 수 있다.

유니티 프리팹 여러개 생성하기

그러면 한쪽에서 이렇게 별사탕이 슬라임을 향해 날라오는 것을 구현할 수 있다.

유니티 프리팹 여러개 생성하기

블록도 동일하게 프리팹으로 생성한 후, 전체 메인 화면 주변으로 둘러준다.

 

Gamelog 20_3. 바깥으로 나가면 사라지게 하기

유니티 오브젝트 화면에서 나갈 경우 지우기

현재는 별사탕이 무한으로 생성되고 사라지지 않아 Hierachy에 오브젝트가 엄청나게 쌓이는 것을 볼 수 있다.
이렇게 되면, 게임에 부하가 가기 때문에 별사탕이 바깥으로 나가게 되면 사라지게 하는 것이 필요하다.

using System;
using UnityEngine;

// 바깥으로 나가면 자기 자신을 삭제한디
public class OnEscape_DestroyMe : MonoBehaviour {
    public float size = 9;

    void Update() {
        Vector3 pos = this.transform.position;

        if (Math.Abs(pos.x)>size || Math.Abs(pos.y)>size) {
            Destroy(this.gameObject);
        }
    }
}

현재 화면 바깥쪽 크기가 x축이 -9 ~ 9 사이이며, y축이 -6 ~ 6 사이이다.
따라서 별사탕이 큰 값인 x축을 기준으로 9보다 큰 위치로 나가게 되면 Destory를 통해 삭제를 시켜준다.
해당 위치는 transform 오브젝트의 position 값을 기준으로 하였으므로, 해당 값을 Vector로 가지고 온다.
또한, size = 9로 설정하기 위해 절대값을 사용하여 Math.Abs()를 사용한다.

다 되었다면, 별사탕 오브젝트에 해당 스크립트를 추가한다.

유니티 오브젝트 화면에서 나갈 경우 지우는 방법

그러면 이렇게 스크롤바가 늘었다 줄었다 하는 것을 통해 별똥별이 사라지고 있음을 알 수 있다.

 

Gamelog 20_4. 캐릭터와 닿으면 멈추게 하기

이제 게임답게, 별사탕을 피하게 만들어보자.
별사탕과 슬라임이 닿으면 게임이 중단되도록 구성한다.

유니티 콜라이더 종류

먼저, 별사탕은 동그랗기 때문에 동그란 오브젝트에 사용하는 콜라이더인 Circle Collider 2D를 프리팹에 추가한다.
그리고 바깥영역이 아닌 안쪽 영역으로 Edit Collider를 통해 조정해준다.

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

// 충돌하면 게임을 정지한다
public class OnCollision_StopGame : MonoBehaviour {

    public string targetObjectName; // 목표 오브젝트 이름 : Inspector에 지정

    void OnCollisionEnter2D(Collision2D collision) { 
      // 만약 충돌한 것의 이름이 목표 오브젝트였다면
        if (collision.gameObject.name == targetObjectName) {
            // 시간을 멈춘다
            Time.timeScale = 0;
        }
        if (collision.gameObject.tag == "Bomb") {
            Physics2D.IgnoreCollision(collision.collider, GetComponent<Collider2D>(), true);
        }
    }
}

그리고 스크립트를 추가하여, 충돌하면 게임이 정지하도록 한다.
만약 targetObject와 부딪히면, Time.timeScale=0을 통해 게임을 멈춘다.

유니티 같은 오브젝트끼리 충돌 무시하는 방법

그러나 이 설정만 있으면, 별사탕끼리 서로를 인식하여 엉겨붙어 모이는 현상이 발생한다.
(처음에 이거보고 얼마나 당황스러웠던지..)
따라서 Physics2D.IgnoreCollision()을 통해 충돌을 무시를 하는 방법을 적용하는 것이 필요하다.

Tags & Layers에서 Tags에 Bomb를 추가한다.

그리고 Tag를 Bomb로 설정한다.

if (collision.gameObject.tag == "Bomb") {
    Physics2D.IgnoreCollision(collision.collider, GetComponent<Collider2D>(), true);
}

그러면 이 코드를 통해서 gameObjecttag를 인식하고 충돌을 무시할 수 있게 된다.

유니티 같은 오브젝트끼리 충돌 무시하는 방법

이렇게 별사탕들이 서로 충돌했을 때, 무시하고 잘 지나가게 되었다.
이제 캐릭터와 닿으면 멈추도록 슬라임에 콜라이더를 적용해주자.

유니티 콜라이더 설정하기

슬라임도 동그랗기 때문에 Circle Collider 2D를 적용해주었으며, 사람이 닿았다고 인식하는 범위로 좁혀주었다.

유니티 콜라이더 설정하기

그러면 이렇게 닿았을 때, 게임이 멈추도록 하는 것까지 완료되었다.

 

다음 게시글에서는 기록 측정을 할 수 있도록 타이머를 구현하고 마무리해보자.

반응형
댓글