Unity

[Unity] 3차 Study : MovingBlock Script

mooni_ 2024. 3. 12. 12:22

[MovingBlock]

변수 선언부

public float moveX = 0.0f;    //X축 이동 거리
public float moveY = 0.0f;    //Y축 이동 거리
public float times = 0.0f;    //출발점부터 도착점까지 이동 시간
public float weight = 0.0f;    //편도 후 정지 시간
public bool isMoveWhenOn = false;    //플레이어 접촉 여부에 따라 이동할 것인가?
public bool isCanMove = true;    //이동이 가능한가?
float perDX;    //1프레임당 X축 이동 값
float perDY;    //1프레임당 Y축 이동 값
Vector3 defPos;    //초기 위치
bool isReverse = false;    //반전 여부

isMoveWhenOn : 이동 조건을 플레이어와의 접촉으로 할 것인가

isCanMove : 이동이 가능한가

 

 


Start()

void Start()
{
    defPos = transform.position;    //moving block 초기 위치
    float timestep = Time.fixedDeltaTime;    //호출 간격?
    perDX = moveX * timestep / times;    //식1)
    perDY = moveY / (1.0f / timestep * times);    //식2)

    if (isMoveWhenOn)
    {
        isCanMove = false;    //플레이어 접촉 시 이동이 가능하다면 시작 시 블록 이동 금지
    }
}
Update 함수와 deltaTime
Update() : 매 프레임 마다 호출, 간격이 일정하지 않음
FixedUpdate() : 일정한 간격을 보장함, 물리적 충돌 등을 여기서 다룸
deltaTime → Update()에서 사용
fixedDeltaTime → FixedUpdate()에서 사용

+) perDX, perDY 구하는 식이 이해가 너무 안돼서 스터디원과 머리를 싸맴,,,
교재는 식2를 사용하였고 과정을 이해하다 도출해낸 식1도 문제 없이 실행되는 듯 이후 이슈가 발견되면 수정

* 위의 경우는 Start()에서 fixedDeltaTime을 사용했는데 이건 뭘까,,, FixedUpdate()에서 다루는 변수인건가?

 

 


FixedUpdate()

private void FixedUpdate()
{
    if(isCanMove)    //이동 가능한 경우에만 FixedUpdate()내용 실행
    {
        float x = transform.position.x;    //초기 위치값을 받음
        float y = transform.position.y;
        bool endX = false;    //끝지점인가 여부
        bool endY = false;
            
        if(isReverse)    //역방향일 경우에
        {
            //초기 위치값과 현재 위치값이 동일한 경우 == 시작지점 도착
            //endX = true
            if((perDX >= 0.0f && x <= defPos.x) || (perDX < 0.0f && x >= defPos.x))
            {
                endX = true;
            }
            if((perDY >= 0.0f && y <= defPos.y) || (perDY < 0.0f && y >= defPos.y))
            {
                endY = true;
            }
            //블록 역방향 이동
            transform.Translate(new Vector3(-perDX, -perDY, defPos.z));
        }
        else    //정방향일 경우에
        {
            //초기 위치값 + 이동거리와 현재 위치값이 동일한 경우 == 끝지점 도착
            if((perDX >= 0.0f && x >= defPos.x + moveX) || (perDX < 0.0f && x <= defPos.x + moveX))
            {
                endX = true;
            }
            if((perDY >= 0.0f && y >= defPos.y + moveY) || (perDY < 0.0f && y <= defPos.y + moveY))
            {
                endY = true;
            }
            //블록 정방향 이동
            Vector3 v = new Vector3(perDX, perDY, defPos.z);
            transform.Translate(v);
        }

        if(endX && endY)    //시작지점 | 끝지점에서
        {
            if(isReverse)    //역방향이면
            {
                transform.position = defPos;    //현재 포지션은 초기값
            }
            isReverse = !isReverse;    //역방향 해제
            isCanMove = false;    //블록 멈추기
            if(isMoveWhenOn == false)    //플레이어와 접촉 상호작용을 받지 않으면 1초 후에 다시 움직임
            {
                Invoke("Move", weight);
            }
        }
    }
}

시작지점, 끝지점을 체크해서 블록을 이동시킴

 


Move() Stop() OnCollisionEnter2D(Collision2D collision) OnCollisionExit2D(Collision2D collision)

public void Move()
{
    isCanMove = true;    //이동 가능
}

public void Stop()
{
    isCanMove = false;    //이동 불가
}

private void OnCollisionEnter2D(Collision2D collision)    //충돌 발생
{
    if(collision.gameObject.tag == "Player")    //대상이 Player라면
    {
        collision.transform.SetParent(transform);    //Player를 이동블럭의 자식으로 만들기
        if(isMoveWhenOn)
        {
            isCanMove = true;
        }
    }
}

private void OnCollisionExit2D(Collision2D collision)    //충돌 해제
{
    if(collision.gameObject.tag == "Player")    //대상이 Player라면
    {
        collision.transform.SetParent(null);    //Player를 이동블럭의 자식에서 해제
    }
}

Move(), Stop()은 스위치 연동 블록을 만들 때 사용함

충돌 함수는 블록을 플레이어의 부모로 설정하여 이동 중일 때 플레이어가 제자리에서 떨어지지 않도록 함

 

 

 

*교재 : 누구나 할 수 있는 유니티 2D 게임 제작