Ad Block 한번만 꺼주시면 안될까요..?
수학

수학) 어느 각도의 포물선이 가장 멀리 날아가는가? (실험)

UniCoti(유니코티) 2023. 6. 4.

나는 중학교 3학년 때 체육 수행평가로 공 멀리 던지기를

한 적이 있었고, 친구들 입에서 포물선이라는 단어가 오갔다.

 

당시 중학교 내신체계는 예체능의 점수까지 반영되었고

나는 필사적으로 공을 던졌지만 2등급 정도의 거리였다.

나는 그때부터 검색해보진 않았지만 어느 각도의 포물선이

가장 먼 거리를 나아가는지에 대한 의문을 가지기 시작했다.

 

이런 의문을 가졌다가, 사라지는 일상이 지속되고,

오늘 드디어 그런 의문이 증폭되어 실험을 진행했다.

내 특기인 게임엔진 유니티를 통해서 실험을 진행했다.

 

https://alpaca-code.tistory.com/217 (수학적 증면편 새로 씀)

 

수학) 어느 각도의 포물선이 가장 멀리 날아가는가? (증명)

https://alpaca-code.tistory.com/182 수학) 어느 각도의 포물선이 가장 멀리 날아가는가? (실험) 나는 중학교 3학년 때 체육 수행평가로 공 멀리 던지기를 한 적이 있었고, 친구들 입에서 포물선이라는 단

alpaca-code.tistory.com


1. 구의 운동 표현하기

먼저, 구의 운동을 잘 보이게 하기 위해 Trail Renderer를 추가해 준다.

이건 유니티 관련글이 아니라 설명은 자세히 하지 않지만,

그래프가 시간에 따른 크기의 변화이고,

Trail Renderer 자체는 움직임에 따른 선을 표시해 준다.

 


2. 물리 현상 구현

뭐 거창하게 써놨지만 사실 물리 계산은 유니티에서 제공해 준다.

내가 직접 코딩할 것도 없고 그냥 추가해 주면 된다.

 

참고로 저기 보이는 Mass는 무게인데, (kg단위)

1kg로 설정해서 적당한 무게를 맞췄다.


3. 각도를 이용해 방향벡터 구하기

가장 난관이었던 부분이다. 인터넷의 여러 글을 참고하며,

또한 내 글 중 반대되는 격의 글인

벡터로 각도 구하기 글도 참고해서 구현했다.

 

https://alpaca-code.tistory.com/80

 

벡터의 각도 구하기(라디안, 도, 역탄젠트)

원래는 유니티 블로그지만 수학에도 관심이 많아 새로운 주제로 글을 써본다. 이 주제를 알게 된 건 굉장히 옛날부터이고 다양한 시도를 해보았지만 구할 수 없었는데 프로그래밍을 하다 벡터

alpaca-code.tistory.com

가상의 직각삼각형을 그리고, 각도는 알고 있고,

빗변은 방향벡터(크기가 1)이므로 1로 해주고,

남은 두 변의 길이를 각각 x, y라고 정의하면,

로 정리돼서

로 바꿀 수 있게 된다.

 

그리고 sin과 cos은 컴퓨터에서 쉽게 계산 가능하기에

이로서 방향벡터를 만들 수 있게 되는 게 내 이론이었지만

 

현실은 내 생각과 달랐다. 코드에 넣어봤을 때

사인은 정상적으로 나왔지만 코사인은 이상했고,

나는 30분 정도 찾아본 뒤 해결할 수 있었다.

 

앞서 말한 벡터의 각도 구하는 글에서도 등장했었던

라디안이 문제를 일으킨 것이다. C#(코딩)에서 제공하는

Mathf.Sin / Cos함수는 라디안 값을 넣어야 작동된다.

 

따라서 나는 각도 -> 라디안 변환식인 

을 곱해줌으로써 이 문제를 해결했다.

Vector3 Direction = new Vector3(0, Mathf.Cos(rota), Mathf.Sin(rota))

이런 난관을 거쳐 만들어낸 코드는 위와 같다.


4. 발사하기

사실 코딩/수학을 잘 모르는 사람이 이 글을 본다면

발사하기를 가장 큰 절차로 생각했을 것이라 생각한다.

나는 5도씩 변화하는 구를 만들기 위해

반복문인 for문을 사용해 주었다.

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

public class Launcher : MonoBehaviour
{
    public GameObject BulletPrefab;
    public float Force;

    // Start is called before the first frame update
    void Start()
    {
        for(int i = 0; i < 91; i += 5) {
            StartCoroutine(Shoot(i * (Mathf.PI/180)));
        }
    }

    IEnumerator Shoot(float rota) {
        Vector3 Direction = new Vector3(0, Mathf.Cos(rota), Mathf.Sin(rota)) * Force;
        GameObject BulletClone = Instantiate(BulletPrefab);
        BulletClone.transform.position = Vector3.zero + new Vector3(0, 1f, 0);
        BulletClone.GetComponent<Rigidbody>().AddForce(Direction, ForceMode.Impulse);
        yield return new WaitForSeconds(0.5f);
    }
}

코딩하는 사람이 아니라면 안 보아도 상관없다.

 

그래도 설명해 보자면 5도 각도로 90도까지 발사,

위에서 말한 수학지식으로 방향 구하기,

클론 하고, 위치 리셋, 발사하기로 구성된 코드이다.

 

아무튼 여기까지 해주면 실험환경이 완성된다.


5. 실행

이제 실행만 하면 모든 과정이 완료된다.

끌 것 없이 바로 실행을 시켜보면,

이러한 모습으로 공이 나가는 걸 볼 수 있다.

다 떨어지면 이런 모습이다. (3차원처럼 보이지만 선들은 2차원입니다.)

 

아무튼 이를 통해서 가장 바깥 구를 조사해 보면, (유니티에서 가능)

45도로 온 구임을 확인할 수 있게 됨으로써,

가장 멀리 가는 각도는 45도라는 결과가 도출된다.


여기까지 오랜만에 코딩이라는 걸 해보았다.

요즘 학업 때문에 시험기간에는 코딩을 못하고

시험이 끝나면 코딩 책을 쓰느라 코딩을 못해서

좀 답답했는데 오랜만에 이렇게 코딩을 해서 기분이 좋다.

 

이런 문제 해결의 과정의 연속이 코딩이라 생각하는데,

이번에는 수학적 지식이 가미돼서 더 재밌었던 것 같다.

나는 게임수학 책을 사서 볼 만큼 게임수학에 관심이 많다.

(물론 내 실력으로는 어림도 없었다)

 

평소 궁금했던 걸 내가 좋아하는 코딩, 수학을 동시에

충족하며 블로그에 글까지 쓰니 기분이 좋다.


이상으로 도움이 되었길 바라며,

 

끝.

댓글

💲 추천 글