본문 바로가기
  • 불확실한 내일을 위해
유니티 C#/C#

C#기초 - 이동과 점프 구현할 때 Transform와 Rigidbody 충돌 오류

by 그린초코 2024. 5. 1.

유니티에서 오브젝트에 이동 구현 스크립트를 적용하려면 Transform 컴포넌트 설정이 필요하고,

점프 구현 스크립트를 적용하려면 Rigidbody 컴포넌트를 추가하여 설정해야 한다. 

따라서 오브젝트에 이동과 점프 둘 다 구현을 하려면 Transform과 Rigidbody 컴포넌트 둘 다 필요하다.

 

(이동과 점프 구현 스크립트는 아래 참고)

 

이동 구현 스크립크 : https://greenchoco.tistory.com/223

 

C#기초 - 방향키로 이동하기 (Input Manager, GetAxis, Vector3)

유니티는 Input Manager 키를 불러와서 GetAxis로 수치화 한 후 이를 Vector 에 적용시킬 수 있다.  (참고 : Input Manager와 GetAxis https://greenchoco.tistory.com/221) 유니티 기초 - Input Manager 시스템으로 입력신호

greenchoco.tistory.com

 

점프 구현 스크립트 : https://greenchoco.tistory.com/227

 

C#기초 - 스페이스바 점프 구현하기 (Getkey, Addforce함수)

스페이스바를 눌렀을 때 오브젝트가 점프할 수 있도록 하는 방법은 어렵지 않다. 1. 오브젝트가 떨어지지 않게 땅 오브젝트 (Plane)을 추가해준다.1. 플레이 할 플레이어 오브젝트에 Rigidbody 컴포

greenchoco.tistory.com

 

 

위의 스크립트를 참고하여 이동과 점프 둘 다 구현된 스크립트는 아래와 같다. 

 - 플레이어는 캡슐 오브젝트로 이름은 player이다.

 - player오브젝트에는 rigidbody컴포넌트를 추가하고 constraints - freeze rotation x, y, z를 체크했다. (그래야 안쓰러짐)

 - plane 오브젝트를 추가한 뒤 Ground 라는 이름으로 tag를 해주었다. 

 - 장애물 오브젝트로 큐브 오브젝트를 추가해주었다. 

using System.Collections;
using System.Collections.Generic;
using UnityEditor.Rendering;
using UnityEngine;

public class Player : MonoBehaviour
{
    
    public float moveSpeed; // 이동구현 - 속도
    public float jumpPower; // 점프구현 - 점프하는 힘
    int jumpCount; // 점프구현 - 점프 횟수
    Rigidbody rb; // 점프구현 - rigid에 이름짓기
    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody>(); // 점프구현 - 오브젝트의 rigid 가져와서 저장 
    }

    void Update()
    {
        float h = Input.GetAxis("Horizontal"); // 이동구현 - 수평
        float v = Input.GetAxis("Vertical"); // 이동구현 - 수직
        Vector3 dir = new Vector3 (h, 0, v); // 이동구현 - 이동 정규화를 위한 dir 선언
        dir.Normalize(); // 이동구현 - dir의 이동 정규화
        transform.position += dir * moveSpeed * Time.deltaTime; // 이동구현 - 이동함수에 dir 적용

        if(Input.GetKeyDown(KeyCode.Space) && jumpCount<2) // 점프구현 - 만약 스페이스파를 누르면 / 2번 미만일 때
        {
            rb.AddForce(Vector3.up * jumpPower, ForceMode.Impulse); // 점프구현 - 위로 순간적인 힘이 발생
            jumpCount++; // 점프구현 - 점프시 1씩 추가한다. 
        }

    }
    private void OnCollisionEnter(Collision collision) // 점프구현 - 충돌 시작하면 호출
    {
        if (collision.gameObject.tag == "Ground") // 점프구현 - 충돌한 물체의 tag가 Ground 일 때
        {
            jumpCount = 0; // 점프구현 - 점프 횟수를 초기화한다. 
        }
    }
}

 

이렇게 작성했을 때 플에이어 오브젝트는 안정적으로 움직인다. 

하지만 방애물이 발생하였을 때 충돌처리방식에 따라 rigidbody 컴포넌트는 더이상 움직이지 못한다고 판단하지만, transform 는 이동 기능에 따라 position 값이 계속 변하려고 하게 된다.

 

그 결과 장애물이 발생했을 때 아래 플레이어가 흔들거리는 현상이 나타난다. 

 

 

이를 해결하기 위해서는 MovePosition 이라는 함수를 이용하면 된다.

이는 물리 작용을 활용해 위치 정보를 계산하는 함수로, Vector3 값을 인수로 지정할 수 있다. 

 

즉 위 스크립트에서      

transform.position += dir * moveSpeed * Time.deltaTime; 이 부분을 
rb.MovePosition(rb.position +(dir * moveSpeed * Time.deltaTime)); 으로 수정하면 된다. 

 

그럼 플레이어는 흔들리지 않고 잘 움직인다. 

 

참고로 설치한 장애물이 untagged 상태면 장애물에 올라간 플레이어는 점프할 수 없다.

위 스크립트에서 Ground 이름이 tag된 오브젝트랑 충돌할 때 발생한다고 적어두었기 때문이다.

따라서 장애물 위에서도 점프를 하기 위해서는 장애물 오브젝트 인스펙터에서 untagged를 Ground로 바꿔주면 된다 

 

따라서 최종 결과물은 아래와 같다.

 

 

 

728x90

댓글