Machineboy空

BubbleShooter 01 : 공 쏘기 및 predictedLine (변위 벡터, reflective) 본문

Game/개발 일지

BubbleShooter 01 : 공 쏘기 및 predictedLine (변위 벡터, reflective)

안녕도라 2024. 4. 21. 14:59

 

본격 기초다지기 프로젝트. 버블슈터 모작 시작했다.

 

간단하리라 생각했는데 기초 유니티 상식들도 많이 잊어버렸고,

문제풀이용 DFS가 아닌 게임 로직용 DFS를 직접 구현해보려니 재밌기도 했지만 머리가 아팠다.

 

2D 프로젝트도 처음인데 생각보다 다른 점들이 꽤 있어 난항을 겪기도 했다.

5단계 정도까지 구현하려는 중이고, 단계별로 정리해보겠다!

 

01. 기본세팅                                                                                                                                                                               

 

  1. 기본 Scene Setting
    • 1080 * 1920 세로 사이즈 모바일용 resolution 설정
  2. 경계 만들기
    • 배경 크기에 맞춰 Border - Collider2D 생성
    • Border 태그 달아주기
  3. 공 만들기
    • 공 생성 (Sprite2D - Circle)
    • collider2D 및 rigidbody2D component 추가
    • physics Materials 만들어 할당

 

***

collider2D, rigidbody2D 꼭 2D가 붙은 것을 넣어주고 코드에서 활용해야한다.

collision 체크가 안되어서 수십번 고민하던 중에 2D용을 쓰지 않은 것 발견


02. 공 쏘기                                                                                                                                                                        

 

 

startPos와 endPos로 변위 벡터 구해 AddForce를 해주자!

Vector2 startPos,endPos, dir;

    // Update is called once per frame
    void Update()
    {
    	// 버튼 누른 순간 startPos 체크
        if(Input.GetMouseButtonDown(0)){
            startPos = Input.mousePosition;
        }
		
        // 버튼 떼는 순간 endPos 체크
        if(Input.GetMouseButtonUp(0)){
        	
            endPos = Input.mousePosition;
            dir = startPos - endPos;
            transform.GetComponent<Rigidbody2D>().AddForce(dir);
        }
   }

 

**

변위 벡터 구하는 원리

 

벡터란?

물체에 힘을 가할 때, 어느 방향으로 얼마만큼 세게 미는 지를 이야기.

크기와 방향을 동시에 가지는 물리적인 양을 벡터라고 한다.

벡터의 시작과 끝이 주어질 때, 벡터의 크기 구하기

 

벡터의 뺄셈?

 

두 벡터 사이의 변화량을 구할 때 사용된다.

물체가 시간에 따라 이동한다고 할 때, 기준점으로 부터의 물체 초기를 나타내는 벡터 1, 일정 시간이 지난 후 나중 위치를 나타내는 벡터 2가 있을 것이다.

일정 시간 동안 이 물체가 움직인 변위를 구할 때, 벡터의 뺄셈을 사용한다.

A, B의 좌표가 주어질 때, B에서 A로 향하는 벡터의 방향과 크기 구하기

***

이론상 endPos - startPos 를 해줘야 반대방향 벡터가 나오는 듯 한데,

startPos - endPos로 해야 원하는 방향으로 날아간다.. 왜지?

 

***

충돌을 너무 강하게 하는 경우에 border colilider를 뚫어버리는 문제가 발생했다.

collider 설정에서, 좀 더 충돌을 정교하고 많이 계산하도록 설정을 바꿔주면 된다!

 

(참고한 블로그)

https://geukggom.tistory.com/5

 

[Unity] RigidBody : Collider를 만들었는데 벽을 통과할 때

[서문] 벽에 Collider를 넣었음에도 가끔 플레이어가 벽을 통과하는 버그가 발생하곤 합니다. 물체의 가속도가 일정량 이상으로 올라가면 생기는 버그로, 원인과 해결 방법에 대해 알아보겠습니다

geukggom.tistory.com


03. 반사하는 PredictedLine                                                                                                                                                                  

 

trajectoryLine, prejectedLine 등으로 검색하면 된다.

이 용어 찾아내는 것도 한참 걸렸음.

 

Ray를 쏴서 맞은 곳에 점을 찍고, LineRenderer를 그려주고

만약 경계라면 반사되는 방향을 구해, 또 그곳에서 ray를 쏘는 방식으로 구현!

 

  1. prejectedLine 만들기
    • Ball에 LineRenderer 붙이기 위한 empty object 하나 child로 달아주기
   Vector2 startPos, dragPos, endPos, dir;
   int reflections = 2;

    void Start()
    {
        // lineRender가 collider안에서 시작할 때, 해당 collider 무시하고 그리도록 설정
        Physics2D.queriesStartInColliders = false;
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0)){
            startPos = Input.mousePosition;
        }

        if(Input.GetMouseButton(0)){
        	// 버튼 누르는 동안만 선 활성화
            LineOfSight.enabled = true;
            
            // 버튼에서 손 떼기 1프레임 전까지 dragPos 갱신 중
            dragPos = Input.mousePosition;
            dir = startPos - dragPos;

            showLaser();
        }

        if(Input.GetMouseButtonUp(0)){
        	// 버튼에서 뗐을 때 선 비활성화하고, AddForce
            LineOfSight.enabled = false;
            
            endPos = Input.mousePosition;
            transform.GetComponent<Rigidbody2D>().AddForce(dir);
        }
    
      
}
    void showLaser(){

        // positionCount: lineRender를 이루는 점의 개수
        LineOfSight.positionCount = 1;
        
        // 시작점 설정: 나로부터
        LineOfSight.SetPosition(0, transform.position);

		// Ray 쏘기
        RaycastHit2D hitInfo = Physics2D.Raycast(transform.position, dir, MaxRayDistance, LayerDetaction);
        Ray2D ray = new Ray2D(transform.position, dir);

        bool isBorder = false;

		// 경계에 닿은 곳 체크용
        Vector2 borderHitPoint = Vector2.zero;
        Vector2 borderHitNormal = Vector2.zero;

        for(int i = 0; i < reflections ; i++){

            LineOfSight.positionCount += 1;
        	
            // 어딘가에 부딪혔다면
            if(hitInfo.collider != null){
				
                // 다음 점을 맞은 곳에 찍는다!
                LineOfSight.SetPosition(LineOfSight.positionCount -1, hitInfo.point);
                isBorder = false;

				// 만약 부딪힌 곳이 border면, reflect방향으로 ray를 또 쏜다
                if(hitInfo.collider.CompareTag("Border")){
                    borderHitPoint = (Vector2)hitInfo.point;
                    borderHitNormal = (Vector2)hitInfo.normal;

                    hitInfo = Physics2D.Raycast((Vector2)hitInfo.point, Vector2.Reflect(hitInfo.point, hitInfo.normal), MaxRayDistance, LayerDetaction);
                    isBorder = true; 
                }
                // 부딪힌 곳이 border가 아니라면 반복 종료 : 즉 꺾이지 않은 직선으로 그려짐
                else{
                    break;
                }
           }else{	// 부딪히지 않았다면
					// forward로 그려라!
                   	LineOfSight.SetPosition(LineOfSight.positionCount - 1, transform.position + transform.forward * MaxRayDistance);
                    break;
            }
        }
    }

 

***

+ 라인 렌더러 기본

점과 점을 이어 직선을 그린다는 개념으로 이어짐!

 

***

+ Vector2.Reflect 와 NormalVector

 

법선 벡터(normal Vector): 한 평면에 대하여 수직을 이루는 벡터

hitInfo.normal을 하면 맞은 곳의 수직 방향 벡터가 나온다.

 

Vector2.Reflect(벡터, 반사시킬 기준 벡터)

 

 

***

보이는 Line과 실제 나아가는 방향 및 운동이 일치하지 않는 문제 발생

값 계속 테스트하며 세부값 조절해줄 필요가 있다.

 

(참고한 영상)

https://www.youtube.com/watch?v=vTnsYnlnMsw

 


+ dash Line, dotted Line 만들기

 

레이저 선이 점선으로 나오게 하고 싶어서 서칭을 많이 했으나,

단순하게 따라할 수 있는 방법은 모두 URP 세팅이 필요했다.

URP 파이프라인을 적용하니 구동 속도가 너무 느려져서 일단 빼두고 마지막에 적용할 예정

 

(참고 영상)

https://youtu.be/Y8MBgR53D10?si=7p2KrRlVzUQu3-ZI