본문 바로가기
오르막길/Unity

[유니티3D] 플레이어 위치로 원거리 공격하는 적

by 우씌 2023. 4. 11.
반응형
총알 코드
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullet : MonoBehaviour
{
    // Start is called before the first frame update
    public float speed = 5.5f;
    private Rigidbody bulletRigidbody;

    void Start()
    {
        bulletRigidbody = GetComponent<Rigidbody>();
        bulletRigidbody.velocity = transform.forward * speed;

        Destroy(gameObject, 5f);
    }

    void OnTriggerEnter(Collider other)
    {
        if(other.tag == "Player")
        {
            PlayerController playerController = other.GetComponent<PlayerController>();

            if(playerController != null)
            {
                playerController.Die();
            }
        }
    }
    // Update is called once per frame
    void Update()
    {
        
    }
}
설명

총알의 속도는 변수 speed로 조절한다.

 

게임 오브젝트에서 Rigidbody 컴포넌트를 찾아 bulletRigidbody에 할당한다.

 

속도 = 앞쪽 방향 * speed

 

5초 뒤에 총알 삭제

 

OnTriggerEnter로 총알과 플레이어가 충돌한 것을 판단했다.

 

게임 오브젝트와 컴포넌트는 충돌 종류에 따라 OnTriggerEnter 혹은 OnCollisionEnter 가 있다.

 

OnCollision 은 일반 충돌일 경우에 사용되며 충돌한 두 콜라이더가 서로 통과하지 않고 밀어낸다.

 

OnTrigger 은 충돌한 두 게임 오브젝트의 콜라이더 중 최소 하나가 트리거 콜라이더일 경우 자동으로 실행되는 것이다. 이 경우 두 게임 오브젝트가 충돌했을 때 서로 그대로 통과한다.

 

트리거 충돌에는 상세한 충돌 정보가 필요 없기 때문에 충돌한 상대방 게임 오브젝트의 콜라이더 컴포넌트가 Collider타입으로 들어온다.

 

트리거 콜라이더는 충돌이 감지됐을 때 어떤 기능을 실행하는 방아쇠로 많이 사용한다.

 

플레이어가 특정 영역으로 진입했는지 검사할 때 트리거 콜라이더를 자주 사용한다.

 

 

Bullet은 Is Trigger인 트리거 콜라이더이기 때문에 OnTriggerEnter()를 사용했다.

 

OnTriggerEnter()의 입력으로 들어오는 other는 충돌한 상대방 게임 오브젝트의 콜라이더 컴포넌트이다.

 

other의 태그가 Player일 경우 플레이어가 죽게 만든다.

 

 

총알은 프리팹이므로 프리팹과 연동된 게임 오브젝트에서 Overrides에 Apply All를 누르면 해당 게임 오브젝트의 변경 사항이 프리팹에 반영된다. 

 

총알을 던지는 적
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BulletSpawner : MonoBehaviour
{
    // Start is called before the first frame update
    public GameObject bulletPrefab;
    public float spawnRateMin = 0.5f;
    public float spawnRateMax = 3f;

    private Transform target;
    private float spawnRate;
    private float timeAfterSpawn;


    void Start()
    {
        timeAfterSpawn = 0f;
        spawnRate = Random.Range(spawnRateMin, spawnRateMax);
        target = FindObjectOfType<PlayerController>().transform;
    }

    // Update is called once per frame
    void Update()
    {
        timeAfterSpawn += Time.deltaTime;
        if(timeAfterSpawn >= spawnRate)
        {
            timeAfterSpawn = 0;
            GameObject bullet = Instantiate(bulletPrefab, transform.position, transform.rotation);
            bullet.transform.LookAt(target);
            spawnRate = Random.Range(spawnRateMin, spawnRateMax);
        }
    }
}
설명

bulletPrefab이란 생성할 탄알의 원본 프리팹이다. 프리팹이란 뭘까?

 

적은 총알을 복제 생성해서 던질 것이다. 프리팹은 언제든지 재사용할 수 있는 게임 오브젝트 에셋(파일)이다. 프리팹으로 만들면 나중에 게임 오브젝트와 똑같은 게임 오브젝트를 프리팹에서 복제 생성할 수 있다. 

 

프리팹으로 만드는 법은 단순하다. 게임 오브젝트를 하이어라키 창에서 프로젝트 창으로 드래기 하고 드롭하면 끝이다. 하이어라키 창에 있던 게임 오브젝트는 하이어라키 창에서 이름이 파란색으로 표시된다.

 

FindObjectOfType()메서드는 <>에 어떤 타입을 명시하면 씬에 있는 모든 오브젝트를 검색해서 해당 타입의 오브젝트를 가져온다. 이것을 통해 플레이어의 컴포넌트를 target에 transform으로 접근하여 할당해준다. 

 

참고로 FindObjectOfType는 처리 비용이 크기 때문에 Start() 메서드처럼 초기에 한두 번 실행되는 메서드에서만 사용해야 한다.

 

일정주기로 총알을 생성한다. timeAfterSpawn은 0에서 시작하고 Time.deltaTime을 계속 더해서 시간이 흘러가게 한다.

 

초당 프레임은 컴퓨터 성능마다 다르기 때문에 Update 실행 시간 간격이 고정되어 있지 않다.

 

Update()실행 사이의 시간 간격을 알기 위해 Time.deltaTime를 사용한다.

 

Time.deltaTime에는 이전 프레임과 현재 프레임 사이의 시간 간격이 자동으로 할당된다.

 

예를 들어서 1초에 240프레임 속도로 화면을 갱신하는 컴퓨터에서 Time.deltaTime의 값은 1/240이 되는 것이다.

 

탄알 복제 생성할 때 Instantiate() 메서드를 사용했다.

 

Instantaite(원본, 위치, 회전);

 

LookAt()으로 총알이 타겟을 바라보게 했다. 위에서 .forward를 사용했기 때문에 이걸로 바라보는 방향을 골라주는 것이다.

 

Random.Range()를 통해서 랜덤하게 시점을 뽑는다.

반응형

댓글