유니티C# 강의- 바닥, 땅, 지면 인식 / 점프 / 낙하데미지(낙뎀) 구현

2025. 7. 27. 09:00·Unity | C#

 

결과물

 

 

 

 

 

원리

여러가지 방법이 있겠지만, 어느 상황에서든 잘 먹히는 로직은

캐릭터가 지면에서부터 떨어진 시점부터 현재 높이를 측정하기 시작

즉, 캐릭터가 체공 중에 가장 높게 올라간 높이(position.y)를 측정하고

발이 땅에 닿은 시점에 가장 높게 올라갔던 높이에 따라 데미지를 줍니다.

가장 높게 올라간 위치를 측정

 

- 장점

시간 값을 측정하는것이 아니라 체공 높이에 따라 낙하데미지를 측정하기에

  • 어느 상황에서든 잘 먹힙니다.
  • 즉, 점프하면서 더 높은 곳의 발판을 밟았다고 하더라도 문제되지 않습니다.
  • 떨어질때 낙하산이나 바닥 스프링같은 기능을 넣을때도 코드 연계가 쉽습니다.
  • 자연스럽습니다
  • 비용 측면, 가성비 갑

땅을 밟고있는지 체크하기

우선 캐릭터가 땅을 밟고 있는지 아닌지를 먼저 체크를 해야합니다.

많이 쓰이는 방식이 크게 두가지가 있는데

Physics.Raycast 와 Physics.CheckSphere 입니다.

 

둘다 물리 충돌 검사를 수행하는 기능이지만 약간의 차이가 존재합니다.

둘 차이를 명확하게 설명을 하는 곳이 없던데 딱 정의 드리겠습니다.

- Raycast vs CheckSphere

  Raycast CheckSphere
설명 가상의 직선을 쏘아 조건에 맞는물체가 선에 닿았는지 확인 가상의 구체를 만들어 조건에 맞는 것이 닿으면 true 반환
반환값 무엇이 닿았는지 구체적으로 알 수 있음
(RaycastHit 리턴)
무엇이 닿았는지 구체적으로 알수없음
닿았다 닿지 않았다만 판별
( bool 값만 리턴 )
범위 선 (포인트, 방향이 중요) - 좁고 정밀 구체 (위치와 반지름이 중요) - 넓음
용도 시야체크, 조준, 레이저, 클릭 등 주변 탐지, 범위 내 충돌

즉,

지면을 체크할때 이 지면이 어떤 오브젝트인지, 어떤 정보를 가지고있는지를 파악할때는 Raycast

그냥 '땅을 밟았다'를 확인하는 용도로만 쓰일 것이라면 CheckSphere를 사용하시면됩니다.

 

예를들어

지면의 성질에 따라 발소리를 다르게 주고싶다. → 지면의 정보가 있어야 하므로 Raycast

지면인지 아닌지 확인만 할 것이다 → 지면에 대한 정보가 필요없으므로 CheckSphere

 

여기서는 땅을 '확인'하는 용도로만 사용할 것이기에 CheckSphere를 사용합니다.

그럼 성능 이슈가있지않을까?

하실 수 있는데, 이해를 돕기 위해 아래이미지를 확인하면 바로 알 수 있습니다.


- 왜 CheckSphere 를 사용하는가

일반적인 지면 위에서는 둘 다 모두 잘 작동합니다.

일반적이지 않은 지면인 절벽이나, 울퉁불퉁한 지면에서는 Raycast의 경우 직선체크를 하기에

땅을 인식하지 못하는 경우가 종종있습니다. → 유저입장에서 꽤 불합리하다고 생각할겁니다.

Raycast를 사용하여 이런 지면을 지나가거나 걸쳐있다면 떨어지는 중이라고 판단해 떨어지고 있는 애니메이션이 재생될 수도 있습니다.

 

→ 이렇기에 CheckSphere를 선택했고,
구체의 지름을 작게 지정해 체크하면 퍼포먼스적으로도 큰 문제가 되지 않고 코드도 간결해집니다.

지면 체크용 Transform 오브젝트 추가

캐릭터의 땅의 기준이 될 GroundCheck 라는 오브젝트를 하나 만들어주었습니다.

조금 직관적으로 이해하기 쉽게 GroundCheck라는 오브젝트를 만들었습니다.

위치는 대충 발 부분에 위치 시킵니다.

GroundCheck 위치

 


지면이 될 오브젝트를 설정

저의 경우는 지면을 3D로 제작했기에 MeshRenderer를 사용하고있는데,

2D를 사용하시는 분이라면 SpriteRenderer 사용하고 계실겁니다. 이것은 큰 상관이 없으므로

지면의 충돌을 감지할 Collider만 잘 추가해주시면 됩니다.

 

그리고 레이어를 변경해야하는데 저는 이미 Structure라고 레이어를 추가해두었습니다.

레이어를 추가하려면 AddLayer.. 를 눌러 주세요

레이어 이름 입력으로 추가

그리고 다시 지면오브젝트를 눌러 레이어를 방금 추가한 레이어로 변경해줍니다.

 

 

이제 해당 위치 중심으로 구체가 생성되어 지면에 닿아있는지 체크할 것입니다.


코드

캐릭터 스크립트에서 아래와 같이 추가해줍니다.

[SerializeField] Transform groundCheck;
[SerializeField] LayerMask StructureLayer;
bool isGround;

void Update()
{
// 0.125f 는 구체의 지름을 결정합니다.
// 각자 프로젝트에 맞는 사이즈가 있을겁니다.
// 저는 기준을 삼을때
// 캐릭터의 무릎정도 되는 높이 값을 넣어주었습니다.
// 그럼 캐릭터 발에서 부터 무릎높이값을 가지는 지름의 구체가 생성되어 체크할 것입니다.
    isGround = Physics.CheckSphere(groundCheck.position, 0.125f, StructureLayer);
}

지면체크는 이게 끝입니다.

땅에 닿아 있으면 true / 떨어져있으면 false를 반환할 것입니다.

 

그리고 캐릭터 스크립트가 적용된 오브젝트를 눌러 인스펙터에 groundCheck와 StructureLayer를 설정해줍니다.

이미 저는 다른 변수들도 많이 들어있어 혼란을 줄수있기에 불필요한 부분은 모자이크 처리했습니다.

groundCheck는 아까 추가했던 오브젝트, Layer는 아까 추가했던 레이어를 선택해주시면됩니다.

 

당연하겠지만 원리를 이해하고 나시면 추후에는 지면 레이어를 매니저를 통해 불러와 따로 관리하시는 것이 좋습니다.

 

이제 이 isGround 변수를 통해 이것저것 살을 붙일 수 있게 되었습니다.


점프 기능 작성

우선 캐릭터 오브젝트에 리지드바디를 추가하고

2.D환경이다 보니 Rigidbody에 의해 축이 틀어지지 않도록 축고정을 하고 있습니다.그 외에는 당장은 기본 설정으로도 충분합니다.

 

점프 기능 추가와 Update에 점프 키를 할당해 점프가 실행 되도록 넣어줍니다.

//------------추가-----
[SerializeField] Rigidbody rb; //Awake에서 GetComponent<Rigidbody> 로 넣어도 되고 직접 인스펙터에서 리지드바디를 넣어주어도 무방
[SerializeField] float jumpSpeed = 5; //점프 높이 측정
[SerializeField] float jumpChkMax = 0; //점프 혹은 낙하시 최대 높이 측정용
//--------------------

[SerializeField] Transform groundCheck;
[SerializeField] LayerMask StructureLayer;
bool isGround;

//------------추가-----
public void Jump()
{
    rb.AddForce(new Vector2(0, jumpSpeed), ForceMode.Impulse);
   	
    // 점프 시작시 함께 진행되어야할 코드들을 넣어줍니다.
    // 예: 점프 시작 애니메이션 실행 등
    
}
//--------------------

void Update()
{
    isGround = Physics.CheckSphere(groundCheck.position, 0.125f, StructureLayer);
    
    //점프 키 추가
    if (Input.GetKeyDown(KeyCode.Space))
    {
        Jump();
    }
    
}

 

 

이제 테스트용 데미지를 주는 부분과 isGround를 이용해 높이 측정 코드를 추가하겠습니다.

void Update()
{
    isGround = Physics.CheckSphere(groundCheck.position, 0.125f, StructureLayer);
    
    if(isGround) //지면에 닿아있을때
    {
     	// jumpChkMax가 0 이상의 값이 있다면 방금 전에 땅에 착지혹은 낙하한 것임
        
        if(jumpChkMax > 3){
        	FallDownDamage(); //3이상의 값으로 착지했다면 떨어진 것으로 간주. 값은 수정가능
        	//낙하 모션 등 추가
        
        }else{
        	//착지 모션 등 추가
            
        }
        jumpChkMax = 0;
    
    }
   	else //체공중일때
    {
    	//현재 캐릭터의 y값과 jumpChkMax의 값중 가장 큰 값을 jumpChkMax에 대입
        float compareY = Mathf.Max(jumpChkMax, transform.position.y);
    	jumpChkMax = compareY;
    }
    
    
    //점프 키 추가
    if (Input.GetKeyDown(KeyCode.Space))
    {
        Jump();
    }
    
}

void FallDownDamage()
{
	Debug.Log("떨어진 거리:" + (jumpChkMax - transform.position.y));
}

 

추가적으로 애니메이션을 적용하고 난 뒤 테스트!

일반 점프시 - 정상 착지
높은 곳에서 점프시 - 바닥에 닿을때 일정높이 이상이면 데미지

콘솔창의 디버그도 잘 출력됩니다.


개발하면서 직접 구현해 온 경험을 토대로, 시간이 날 때마다 기록을 남기고 있습니다.
유니티와 언리얼이 지금처럼 풍부한 자료를 갖추기 전부터 개발을 해오면서,
부족한 레퍼런스 속에서 하나하나 직접 구현해 나갔던 경험들이 지금도 큰 도움이 되고 있습니다.
이 글은 과거의 저와 같은 고민을 겪는 초/중급 개발자 분들께 조금이나마 도움이 되길 바라며 작성합니다.
자유롭게 사용/수정/재배포하셔도 좋습니다. 출처만 함께 남겨주시면 감사하겠습니다 :)

물론 부족한 부분이있다면 댓글 주시고, 질문은 환영입니다.
반응형
저작자표시 비영리 동일조건 (새창열림)

'Unity | C#' 카테고리의 다른 글

[Unity C#]Delegate 사용법 - Update() 없이 실시간 갱신하기(재화바 예제 포함)  (4) 2025.08.03
[Unity C#] 여러가지 변수 메모리 변조 방지(암호화)와 원리, 코드  (5) 2025.08.02
[유니티] 오브젝트 풀링 제대로 쓰는 법 – Instantiate 지옥에서 탈출하기  (3) 2025.07.20
[Unity] Asprite→유니티 연동 방법 애니메이션, 텍스쳐등 2D 임포트 수고 덜기  (0) 2025.07.19
[유니티] 패키지매니저에서 git url 안 되거나 다른 컴에서 안될 때 (커서ai)  (1) 2025.07.09
'Unity | C#' 카테고리의 다른 글
  • [Unity C#]Delegate 사용법 - Update() 없이 실시간 갱신하기(재화바 예제 포함)
  • [Unity C#] 여러가지 변수 메모리 변조 방지(암호화)와 원리, 코드
  • [유니티] 오브젝트 풀링 제대로 쓰는 법 – Instantiate 지옥에서 탈출하기
  • [Unity] Asprite→유니티 연동 방법 애니메이션, 텍스쳐등 2D 임포트 수고 덜기
무꼬
무꼬
격투기하는 개발자입니다. 서버, 유니티 강의 및 개발일지, 자작 앱 공유 등을 하는 블로그에요 궁금한 것 무엇이든 남겨주시면 매일 확인하고있으니 알려드려요
  • 무꼬
    무꼬's Art Life
    무꼬
  • 전체
    오늘
    어제
    • 전체글 (136)
      • 개발일지 (53)
      • Unity | C# (18)
      • Server (4)
        • Nest.js (3)
      • JavaScript (2)
      • Visual Basic6 & VBA (10)
      • 자작 프로그램 (2)
      • IT Tip (7)
      • Daily (3)
        • DIY (2)
        • 나들이 (1)
      • 쉼터 (33)
        • Martial Arts (17)
        • 유머 (10)
        • 생활의 노하우 + 와드 (6)
  • 인기 글

  • 최근 글

  • 최근 댓글

  • 250x250
  • 태그

    inventorysystem
    VB6
    2.5D
    강좌
    주짓수
    주짓수 강좌
    unity
    개발일지
    변수
    VB
    비베
    MMA
    유니티
    기초강좌
    6.0
    비주얼 베이직
    inventory system
    devlog
    심테
    레벨디자인
  • hELLO· Designed By정상우.v4.10.4
무꼬
유니티C# 강의- 바닥, 땅, 지면 인식 / 점프 / 낙하데미지(낙뎀) 구현
상단으로

티스토리툴바