tangent
게임에서
cos sin은 각에 관련된 것이었고
tangent도 마찬가지로 각도와 관련이 있고 기울기가 핵심이다
tan θ는 높이/밑변으로 c/b이다
이는 결국 a가 1이라는 가정하에, sin θ / cos θ를 의미한다
우리가 원하는 건 tan θ가 아닌
tan를 뺀 θ 이기 때문에
arcTan(역삼각함수)을 이용해서 θ 를 구할 수 있다
θ = c/b의 arcTan
유니티의 Atan()
유니티에서는 역삼각함수로 쉽게 바꿀 수 있는 Atan과 Atan2가 있다
Mathf.Atan(parameter)을 이용하면
길이의 비율을 (y / x)을 인자로 작성하면 된다
Mathf.Atan2(parameter 01, parameter 02)을 이용하면
길이의 비율을 (y, x)를 순서대로 인자로 작성하면 된다
Atan() 예시
적용 사례로는
간단하게 포탑과 플레이어가 있다고 한다면
포탑이 플레이어의 위치를 추적해 그 플레이어에 맞는 각도로 움직이는 것이다
위의 사례를 구현하기 위해
먼저 플레이어(빨간 공)가 계속 위아래로 계속 움직이도록
플레이어(빨간 공)에 추가할 sin을 이용한 MoveUpDown 스크립트를 작성하면 아래와 같다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveUpandDown : MonoBehaviour
{
[Range(10, 50)]
public float speed = 10.0f;
[Range(1, 5)]
public float scalar = 1.0f;
public float degree = 0.0f;
float y = 0.0f;
// Start is called before the first frame update
void Start()
{
y = transform.position.y;
}
// Update is called once per frame
void Update()
{
degree += Time.deltaTime * speed;
Vector3 direction = new Vector3(transform.localPosition.x, y + Mathf.Sin(Degree2Rad(degree)) * scalar, 0);
transform.localPosition = direction;
}
float Degree2Rad(float degree)
{
return degree * Mathf.PI / 180;
}
}
그리고 포탑이 플레이어의 위치에 따라
각도를 계산하여 그 방향으로 회전을 하도록(바라보도록) 하는 TargetRotate 스크립트는 아래와 같이 작성할 수 있다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TargetRotate : MonoBehaviour
{
public Transform Target;
public Transform Root;
public Transform Shot;
private float degree;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Target != null)
{
float x = Target.position.x - Root.position.x;
float y = Target.position.y - Root.position.y;
float tan = y / x;
float radianTan = Mathf.Atan(tan);
degree = Rad2Degree(radianTan);
Root.localRotation = Quaternion.Euler(0, 0, degree);
}
}
float Rad2Degree(float rad)
{
return rad * 180 / Mathf.PI;
}
}
이에 따른 결과물은 아래와 같다
이제 포탑에서 총이 발사되도록 구현하려면
기존의 TargetRotate 스크립트를 변형하여 TargetRotateByShot 스크립트 만들면 된다
CreateShot 함수를 호출해 총알을 발사하게끔 아래와 같이 작성 가능하다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TargetRotateByShot : MonoBehaviour
{
public Transform Target;
public Transform Root;
public GameObject Shot;
private float degree;
// Start is called before the first frame update
void Start()
{
InvokeRepeating("CreateShot", 1.0f, 1.0f);
}
// Update is called once per frame
void Update()
{
if (Target != null)
{
float x = Target.position.x - Root.position.x;
float y = Target.position.y - Root.position.y;
float tan = y / x;
float radianTan = Mathf.Atan(tan);
degree = Rad2Degree(radianTan);
Root.localRotation = Quaternion.Euler(0, 0, degree);
}
}
float Rad2Degree(float rad)
{
return rad * 180 / Mathf.PI;
}
private void CreateShot()
{
if(Shot != null)
{
GameObject obj = Instantiate<GameObject>(Shot, Root.position, Quaternion.identity);
ShotMove shotMove = obj.GetComponent<ShotMove>();
if (transform.localPosition.x > 0)
degree += 180;
shotMove.SetDegree(degree);
Destroy(obj, 20.0f);
}
}
}
이처럼
sin의 성질을 활용한 빨간 공과
각도를 찾아낼 수 있는 tangent의 성질을 활용하여
Root를 기준으로 플레이어와의 각도를 알아내서
그 각도로 회전하며 총알이 발사되는 아래와 같은 결과물을 만들 수 있다
'게임 수학 & 물리 > 게임 수학' 카테고리의 다른 글
[게임 수학] 벡터의 기초 (2) (0) | 2023.10.17 |
---|---|
[게임 수학] 벡터의 기초 (1) (0) | 2023.10.17 |
[게임 수학] sin, cos (2) (0) | 2023.10.16 |
[게임 수학] sin, cos (1) (0) | 2023.10.16 |
[게임 수학] 피타고라스의 정리 (0) | 2023.10.15 |