멋쟁이사자처럼부트캠프 유니티 게임 개발 5기 25일차 - 몬스터 게임 마무리, 삼각함수

2025. 6. 19. 16:30·강의/멋쟁이 사자처럼 유니티 부트캠프

오늘은 어제까지 클릭커 방식으로 구현했던 몬스터 게임에 캐릭터를 추가하여 키보드 입력 방식으로 바꾸어보았다.

그리고 본격적으로 게임수학 학습에 들어갔는데, 고등학생 때는 막연히 공식으로만 배웠던 내용들이 게임에서 실제로 활용되는 모습을 보니 흥미로웠다. 계산은 엔진 내장 함수로 금방 할 수 있기 때문에 프로그래머는 계산보다는 그 의미를 이해하고 어떻게 활용할 지 고민하는 게 더 중요한 것 같다.

저번에 유니티 공식 유튜브에서도 삼각함수 관련 게임수학 강의를 들었었는데, 다음 프로젝트는 이를 이용해서 탄막 슈팅 게임을 만들어봐야겠다.

 

몬스터 게임

아이템

IItem 인터페이스를 구현한 ItemCoin과 ItemPotion 클래스를 만들었다.

Get 함수는 공통적으로 진행되지만, price나 회복hp 같이 다르게 적용되는 변수들은 따로 작성해주면 된다.

public interface IItem
{
    GameObject Obj { get; set; }
    void Get();
}
public class ItemCoin : MonoBehaviour, IItem
{
    private Inventory inventory;
    
    public enum CoinType { Gold, Green, Blue }
    public CoinType coinType;

    public float price;

    void Start()
    {
        inventory = FindFirstObjectByType<Inventory>();
        Obj = gameObject;
    }
    
    void OnMouseDown()
    {
        Get();
    }

    public GameObject Obj { get; set; }

    public void Get()
    {
        Debug.Log($"{this.name}을 획득했습니다.");

        inventory.AddItem(this);
        
        gameObject.SetActive(false);
    }
}

인벤토리 클래스를 만들어서 아이템 획득 시 인벤토리의 리스트에 추가되도록 하였다.

public class Inventory : MonoBehaviour
{
   public List<GameObject> Items = new List<GameObject>();

   public void AddItem(IItem item)
   {
      Items.Add(item.Obj);
   }
}

캐릭터 공격

Sprite를 끈 Circle을 만들어서 캐릭터 앞에 HitBox로서 배치한다.

Space바 클릭 시 Circle의 콜라이더가 활성화되어 몬스터를 공격하는 방식이다.

void Update()
{
    Move();
    Attack();
}
 
void Attack()
{
    if (Input.GetKeyDown(KeyCode.Space) && !isAttack)
    {
        StartCoroutine(AttackRoutine());
    }
}
    
IEnumerator AttackRoutine()
{
    isAttack = true;
    hitBox.SetActive(true);
    
    yield return new WaitForSeconds(0.25f);
    hitBox.SetActive(false);
    
    yield return new WaitForSeconds(0.25f);
    isAttack = false;
}

좌우 이동할 때 Flip을 사용하게 되면 캐릭터의 Sprite만 반전되기 때문에 이번에는 Scale값을 -1로 바꿔 HitBox도 같이 뒤집힐 수 있도록 한다.

void Move()
{
    h =  Input.GetAxis("Horizontal");
    v = Input.GetAxis("Vertical");

    if (h == 0 && v == 0)
    {
        animator.SetBool("Run", false);
    }
    else
    {
		    // h 값에 따라 좌우 이동
        if (h > 0)
            transform.localScale = new Vector3(1f, 1f, 1f);
        else if (h < 0)
            transform.localScale = new Vector3(-1f, 1f, 1f);
                
        animator.SetBool("Run", true);
        var dir = new Vector3(h, v, 0).normalized;
        transform.position += dir * moveSpeed * Time.deltaTime;
    }
    
}

Player와 Monster의 충돌을 피하기 위해 레이어 처리도 해주었다.

void OnTriggerEnter2D(Collider2D other)
{
    if (other.GetComponent<Monster>() != null)
    {
        Monster monster = other.GetComponent<Monster>();
        StartCoroutine(monster.Hit(1f));
    }
}

OnTrigger 이벤트로 Hitbox에 몬스터가 충돌한다면 몬스터를 공격한다.

아이템 획득

아이템 획득의 경우 OnCollision을 이용해 캐릭터와 충돌하면 인벤토리에 추가할 수 있도록 해주었다.

 void OnCollisionEnter2D(Collision2D other)
{
    if (other.gameObject.GetComponent<IItem>() != null)
    {
        IItem item = other.gameObject.GetComponent<IItem>();
        item.Get();
    }
}

결과

 

삼각함수

역함수

x와 y의 위치를 바꾼 함수

y = sin x → x = sin y → y = asin x

사인 법칙

ASA (Angle-Side-Angle) 또는 AAS(Angle-Angle-Side)

위 그림을 아래 코드처럼 작성할 수 있다.

public float aAngle = 30f;
public float bAngle = 90f;
public float aSide = 1f;

void Start()
{
    float aRad = aAngle * Mathf.Deg2Rad;
    float bRad = bAngle * Mathf.Deg2Rad;

    float bSide = (aSide * Mathf.Sin(bRad)) / Mathf.Sin(aRad);

    Debug.Log(bSide); // 2
}


코사인 법칙

위 그림을 아래 코드처럼 작성할 수 있다.

public float cAngle = 60f;
public float aSide = 1f;
public float bSide = 1f;

void Start()
{
    float cRad = cAngle * Mathf.Deg2Rad;
    float cSide = Mathf.Sqrt(Mathf.Pow(aSide, 2) + Mathf.Pow(bSide, 2) - 2 * aSide * bSide * Mathf.Cos(cRad));
    
    Debug.Log(cSide); // 1
}

탄젠트 법칙

Sin 법칙과 Cos 법칙으로 해결하기 어려운 경우에 사용한다.

삼각함수 그래프

private float theta;
[SerializeField] private float speed, radius;

void Update()
{
    theta += Time.deltaTime * speed;

    float x = Mathf.Cos(theta);
    float y = Mathf.Sin(theta);
    
    Vector2 pos = new Vector2(x, y) * radius;
    transform.position = pos;
}

Sin과 Cos을 이용하여 원 모양으로 이동할 수 있다.

 

라이트 실습

public class MathLight : MonoBehaviour
{
    private Light light;
    private float theta;

    void Start()
    {
        light = GetComponent<Light>();
    }
    void Update()
    {
        theta += Time.deltaTime;
        light.intensity = Mathf.Sin(theta);
    }
}

이렇게 수학적 공식을 이용한 라이트 조절 같은 기능들이 유니티 안에도 내장되어 있다.

예를 들어 PerlinNoise 같은 경우 꺼질거같은데 안 꺼지는 느낌의 효과로 공포게임에서 음산한 느낌을 조성하기도 한다.

void Update()
{
    theta += Time.deltaTime * speed;
    
    light.intensity = Mathf.PerlinNoise(theta, 0) * power;
}

 

 

터렛 실습

기본 상태 - 주변 돌아보기

Sin함수를 이용하여 자연스러운 움직임을 만들 수 있다.

public class Turret : MonoBehaviour
{
    public Transform turretHead;
    private float theta;
    public float rotSpeed = 1f;
    public float rotRange = 60f;
    void Update()
    {
        theta += Time.deltaTime * rotSpeed;

        float rotY = Mathf.Sin(theta) * rotRange;
        turretHead.localRotation = Quaternion.Euler(0, rotY, 0);
    }
}

타겟팅 - 타겟 상대 바라보기

범위 내에 플레이어가 들어온다면 LookAt을 이용하여 플레이어를 바라보게 만들었다.

void Update()
{
    if (isTarget)
        TurretTarget();
    else
        TurretIdle();

}

void TurretTarget()
{
    if (target != null)
        turretHead.LookAt(target);
}

void OnTriggerEnter(Collider other)
{
    if (other.CompareTag("Player"))
    {
        target = other.transform;
        isTarget = true;
    }
}

void OnTriggerExit(Collider other)
{
    if (other.CompareTag("Player"))
    {
        target = null;
        isTarget = false;
    }
}

결과

 

벡터와 스칼라

Vector3.Distance(x벡터, y벡터) : 두 벡터 사이의 거리 계산

Vector3.Magnitude(x벡터 + y벡터) : 두 벡터를 합친 새로운 벡터 생성 후 크기(길이) 계산

Vector3.SqrMagnitude(x벡터 + y벡터) : 벡터의 길이를 제곱해서 반환 (루트 연산 하지않아서 연산 빠름)

Vector3 vecA = new Vector3(3, 0, 0);
Vector3 vecB = new Vector3(0, 4, 0);

void Start()
{
    float size = Vector3.Magnitude(vecA + vecB);
    Debug.Log($"Magnitude: {size}"); // 5
    
    float distance = Vector3.Distance(vecA, vecB);
    Debug.Log($"Distance: {distance}"); // 5
    
    float size2 = Vector3.SqrMagnitude(vecA + vecB);
    Debug.Log($"SqrMagnitude: {size2}"); // 25
}
'강의/멋쟁이 사자처럼 유니티 부트캠프' 카테고리의 다른 글
  • 멋쟁이사자처럼부트캠프 유니티 게임 개발 5기 27일차 - 조이스틱 이동, 점프, 공격
  • 멋쟁이사자처럼부트캠프 유니티 게임 개발 5기 26일차 - 벡터, 행렬, 플랫포머 게임
  • 멋쟁이사자처럼부트캠프 유니티 게임 개발 5기 24일차 - 몬스터 피격, 죽음, 스폰
  • 멋쟁이사자처럼부트캠프 유니티 게임 개발 5기 23일차 - 캡슐화, 인터페이스, 상속 실습
로또
로또
게임 개발자 연습생의 발전 일지
  • 로또
    게임 개발 발전소
    로또
  • 전체
    오늘
    어제
    • 분류 전체보기 N
      • 개발
        • 코딩테스트
        • JAVA
        • DB
        • Unity
      • 강의 N
        • 패스트캠퍼스 0원 챌린지
        • 멋쟁이 사자처럼 유니티 부트캠프 N
      • 게임
        • 공부
        • 리뷰
  • 블로그 메뉴

    • 홈
    • 방명록
    • 글쓰기
  • 링크

    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    패스트캠퍼스후기
    패캠인강후기
    직장인자기계발
    트리
    코딩테스트
    백트래킹
    패스트캠퍼스
    3D웹인터랙티브
    자료구조
    오공완
    Java
    C4D
    BFS
    그리디알고리즘
    그리디
    패캠챌린지
    백준
    직장인인강
    한번에끝내는프론트엔드개발초격차패키지Online
    dfs
    환급챌린지
    그래프
    C#
    2839
    분리집합
    완전탐색
    수강료0원챌린지
    멋쟁이사자처럼후기
    게임개발
    Unity
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
로또
멋쟁이사자처럼부트캠프 유니티 게임 개발 5기 25일차 - 몬스터 게임 마무리, 삼각함수
상단으로

티스토리툴바