[Unity]삼각함수를 활용한 미사일 슈팅 구현하기

728x90

삼각함수를 사용하여 오브젝트 이동 방법

총알 발사 패턴

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

// 1. Player 이동 2. Player 이동 패턴을 원을 그리며 이동 3. 미사일 발사(순차적) 4. 미사일 발사(한번에)
public enum Pattern { One, Two };
public class PlayerController : MonoBehaviour
{
    public GameObject bulletObject;
    public Transform bulletContainer;

    public Pattern shotPattern; // 패턴을 선택할 수 있게 되어 있음
    public float moveSpeed = 2f;
    public float circleScale = 5f;
    public int angleInterval = 10;
    public int startAngle = 30;
    public int endAngle = 330;

    private int iteration = 0;
    
    private void Start() //총알 발사 관련
    {
        if(shotPattern == Pattern.One)
            StartCoroutine(MakeBullet()); //코루틴 함수
        else if (shotPattern == Pattern.Two)
            StartCoroutine(MakeBullet2());
    }

    private void Update() //플레이어 이동 관련
    {
        //PlayerMove(30);  //30도(Degree) 방향으로 움직인다
        //PlayerCircle();
    }

    void PlayerMove(float _angle)
    {
        if (Input.GetKey(KeyCode.Space))
        {
            Vector2 direction = new Vector2(Mathf.Cos(_angle * Mathf.Deg2Rad), Mathf.Sin(_angle * Mathf.Deg2Rad));
            //Mathf.cons,sin = Radian값(0~2pi), Degree값(0~360)을 Rad값으로 변경
            transform.Translate(moveSpeed * direction * Time.deltaTime); //이동을 시킴
        }
    }

    void PlayerCircle()
    {
        //iteration은 0부터 360까지 값이 커짐. 즉, 각도가 1 씩 증가
        //Deg를 Deg2Rad으로 변환
        //circleScale은 원의 크기를 결정
        Vector2 direction = new Vector2(Mathf.Cos(iteration * Mathf.Deg2Rad), Mathf.Sin(iteration * Mathf.Deg2Rad));
        transform.Translate(direction * (circleScale * Time.deltaTime));
        //곱해진 Time.deltaTime은 매 프레임마다 달라지기 때문에 실행 시 스케일을 조정하면 중심이 이동한다
        iteration++;
        if (iteration > 360) iteration -= 360; //0~360도 사이에 돌게 만들기 위해
    }

    private IEnumerator MakeBullet()
    {
        int fireAngle = 0; //초기값은 0도
        while (true)
        {
            GameObject tempObject = Instantiate(bulletObject, bulletContainer, true);
            //bulletContainer 안에 bulletObject를 생성
            Vector2 direction = new Vector2(Mathf.Cos(fireAngle*Mathf.Deg2Rad),Mathf.Sin(fireAngle*Mathf.Deg2Rad));
            tempObject.transform.right = direction;
            //총알 오브젝트 오른쪽을 direction 방향(날아가는 방향)으로 설정(각도에 따라 이동)
            tempObject.transform.position = transform.position;
            //총알 오브젝트의 위치는 플레이어의 위치로 설정

            yield return new WaitForSeconds(0.1f);
            // 0.1초간 대기
            
            fireAngle += angleInterval;
            //발사한 각도를 설정한 간격값(angleInterval)에 따라 증가
            if (fireAngle > 360) fireAngle -= 360;
            //0~360도
        }
    }
    
    private IEnumerator MakeBullet2()
    {
        while (true)
        {
            //한번에 미사일을 만들어줌
            for (int fireAngle = startAngle; fireAngle < endAngle; fireAngle += angleInterval)
            {
                GameObject tempObject = Instantiate(bulletObject, bulletContainer, true);
                Vector2 direction = new Vector2(Mathf.Cos(fireAngle*Mathf.Deg2Rad),Mathf.Sin(fireAngle*Mathf.Deg2Rad));
               
                tempObject.transform.right = direction;
                tempObject.transform.position = transform.position;
            }

            yield return new WaitForSeconds(4f);
            //4초간 대기
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BulletController : MonoBehaviour
{
    private Rigidbody2D bulletRigidbody2D;
    private float bulletSpeed = 10f;
    void Start()
    {
        bulletRigidbody2D = GetComponent<Rigidbody2D>();
        bulletRigidbody2D.velocity = bulletSpeed * transform.right;
        //transform.right는 bullet의 오른쪽 방향으로 가라는 의미
    }
}

1번 타입

2번 타입

 

화살 발사 패턴

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

public class ArcherController : MonoBehaviour
{
    public GameObject arrowObject;
    public Transform arrowContainer;

    public float shotInterval = 2f;
    
    void Start()
    {
        StartCoroutine(FireArrow());
    }

    IEnumerator FireArrow()
    {
        while (true)
        {
            //화살 발사각도 = 20 + 20i(20, 40, 60)
            for (int i = 0; i < 3; i++)
            {
                GameObject tempObject = Instantiate(arrowObject, arrowContainer);
                Vector3 direction = new Vector2(Mathf.Cos((20+20*i)*Mathf.Deg2Rad), Mathf.Sin((20+20*i)*Mathf.Deg2Rad));

                tempObject.transform.right = direction;
                tempObject.transform.position = transform.position + shotInterval * direction;
                //shotInterval * direction는 화살이 플레이어 앞에서 발사되도록 자연스럽게 만들어주기 위해
                //direction을 곱해 발사 각도에 맞게 발사 위치를 띄움(간격을 더할 때 나아가고자 하는 방향으로 간격 띄움)
            }

            yield return new WaitForSeconds(5f);
        }
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ArrowController : MonoBehaviour
{
    private Rigidbody2D arrowRigidbody2D;
    private float arrowPower = 12f;
    void Start()
    {
        arrowRigidbody2D = GetComponent<Rigidbody2D>();
        arrowRigidbody2D.AddForce(arrowPower*transform.right,ForceMode2D.Impulse);
    }

    private void Update()
    {
        transform.right = arrowRigidbody2D.velocity.normalized; //화살이 부드럽게 날아감
        //내 오른쪽 방향을 내 현재의 속도의 방향 벡터로 설정하겠다
        //normalized -> 방향 벡터를 만드나는 뜻
    }
}

정상적으로 플레이 시,

Update() 함수에서 다음 코드를 주석처리 했을 시,

transform.right = arrowRigidbody2D.velocity.normalized;

 

728x90