C# 게임개발 입문 1주차-팀프로젝트

C014·2023년 12월 1일

Unity

목록 보기
5/9

벽돌깨기 게임
튕기는 공 컨트롤에 대한 코드에 대해 이야기해볼겁니다!

using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BallControl : MonoBehaviour
{
    public float ballSpeed = 8.0f;

    public Vector2 ballDirection; //공의 속도
    public bool isBallReleased = false;      //공이 패들에서 떨어졌는가 (붙어있음)

    //공의 방향
    // Start is called before the first frame update
    void Start()
    {
        ballDirection = Vector2.up.normalized;      //처음 시작할때 공의 방향을 위쪽으로
    }

    // Update is called once per frame
    void Update()
    {
        if (!isBallReleased)
        {
            Vector3 paddlePosition = GameObject.Find("Paddle").transform.position;        ////패들 오브젝트의 위치를 찾아옴

            Vector3 ballPosition = paddlePosition;        ////공의 위치를 패들의 위치로 변경
            ballPosition.y += 0.1f;                       //// 공과 패들사이 간격
            transform.position = ballPosition;            //// 공을 패들에 위치

            if (Input.GetButtonDown("Fire1")) //// 공 발사
            {
                isBallReleased = true;        ////공이 패들에서 떨어짐

                ballDirection = new Vector2(Random.Range(-1f, 1f), 1).normalized;         //// 위쪽 랜덤방향으로 공 발사(직각으로 발사할 경우 random.range를 빼고 좌표룰 설정해준다.
            }
        }
        else
        {
            transform.Translate(ballDirection * ballSpeed * Time.deltaTime);        ////시간에 따른 공의 이동    방향*속도*시간
        }




    }
    private void OnCollisionEnter2D(Collision2D collision) //rigid2D나 coli2D가 다른 rigid2D나 coli2D에 부딪혔을때 실행
    {
        if (collision.gameObject.CompareTag("Wall")|| collision.gameObject.CompareTag("Brick")) // 게임오브젝트 Wall 태그에 충돌
        {
            ballDirection = Vector2.Reflect(ballDirection, collision.contacts[0].normal);   // 벽에 충돌할때 방향 반전
        }
        else if (collision.gameObject.CompareTag("Paddle"))     //패들과 충돌할때 방향설정
        {
            float hitpoint = collision.contacts[0].point.x;     // 충돌 지점의 x좌표를 hitpoint에 저장
            float paddleCenter = collision.transform.position.x;        //패들의 중심 x좌표를 paddlecenter에 저장
            float angle = (hitpoint - paddleCenter) * 2.0f;         // 충돌점과 중심으로 각도 계산
            ballDirection = new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)).normalized; // 각도를 기반으로 방향벡터를 만들고 normalized로 크기1로 만듦 
        }
    }
}


Ball 오브젝트에 rigidbody 2d로 물리엔진을 입혀주고 circle colider 2d로 동그랑 공모양으로 히트박스를
만들어 주었습니다.
여기서 중요한점은 gravity scale을 0으로 바꿔줌으로서

ballDirection = new Vector2(Random.Range(-1f, 1f), 1).normalized;

랜덤방향으로 공을 발사하여 중력없이 공이 튕겨다니게 설정할 수 있습니다.


가장 핵심이 되는 코드는 공이 벽돌, 벽, 패들에 튕겨나갈때 공이 움직이는 각도를 설정하는것이라고 할 수 있겠죠?

private void OnCollisionEnter2D(Collision2D collision) //rigid2D나 coli2D가 다른 rigid2D나 coli2D에 부딪혔을때 실행
    {
        if (collision.gameObject.CompareTag("Wall")|| collision.gameObject.CompareTag("Brick")) // 게임오브젝트 Wall 태그에 충돌
        {
            ballDirection = Vector2.Reflect(ballDirection, collision.contacts[0].normal);   // 벽에 충돌할때 방향 반전
        }
        else if (collision.gameObject.CompareTag("Paddle"))     //패들과 충돌할때 방향설정
        {
            float hitpoint = collision.contacts[0].point.x;     // 충돌 지점의 x좌표를 hitpoint에 저장
            float paddleCenter = collision.transform.position.x;        //패들의 중심 x좌표를 paddlecenter에 저장
            float angle = (hitpoint - paddleCenter) * 2.0f;         // 충돌점과 중심으로 각도 계산
            ballDirection = new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)).normalized; // 각도를 기반으로 방향벡터를 만들고 normalized로 크기1로 만듦 
        }
    }

Wall, Brick, Paddle 오브젝트에 붙어있는 Tag를 이용해 충돌 결과를 실행할수 있습니다!

공이 부딪혀서 날아가는 각도에 대해 고민해본 결과 입사각=반사각을 이용하면 정확한 물리 엔진을 만들 수 있을거라고
생각했습니다.
따라서 충돌지점과 중심과의 차의 2배를하면 반대 사분면에서 올바르게 튕겨저 나올것이라 생각하여 코드를 구현했습니다.

float angle = (hitpoint - paddleCenter) * 2.0f;

(예를들면 2사분면에서 입사각을 가지고 공이 충돌한다면 1사분면에서 반사각을 가지고 반사될것입니다)

 ballDirection = new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)).normalized;

그리고 벡터의 방향을 계산해보면 Sin각도를 반환한값과 Cos각도를 반환한 값으로 공이 튕겨나가는 방향벡터를
만들고 normalized를 통해 크기가 1인 벡터를 정규화 하여 공이 일정한 속도로 반사되는 물리 엔진을 만들어 보았습니다.

profile
doro

0개의 댓글