
개요
게임에서 물리적 상호작용은 플레이어가 게임 세계에 몰입하는 데 중요한 역할을 합니다. 물체가 떨어지거나 부딪히는 모습, 캐릭터가 점프할 때 중력의 영향을 받는 모습은 게임을 더욱 현실감 있게 만들어 줍니다. 특히, 실감 나는 시뮬레이션 게임이나 액션 게임에서는 물리적인 요소들이 게임의 재미를 좌우하기도 합니다.
Unity는 이러한 물리 효과를 쉽게 구현할 수 있도록 도와주는 강력한 물리 엔진을 제공합니다. NVIDIA의 PhysX 엔진을 기반으로 한 Unity 물리 시스템은 정확하고 효율적인 물리 시뮬레이션을 가능하게 해 줍니다. 2D와 3D 게임 모두 지원하며, 충돌 처리나 중력, 힘 적용 같은 기능을 간단하게 설정할 수 있어 개발자들이 손쉽게 사용할 수 있습니다.
게임에서 중력은 캐릭터의 이동이나 점프, 물체의 낙하와 같은 동작에 큰 영향을 미칩니다. 적절하게 설정된 중력은 게임플레이를 더 흥미롭게 만들고, 플레이어가 게임 세계에 몰입하는 데도 큰 역할을 합니다. 예를 들어, 플랫폼 게임에서는 중력의 세기나 방향을 조절하여 플레이어에게 색다른 경험을 제공할 수 있습니다.
1.유니티의 중력 시스템 기초
1.1 Rigidbody 컴포넌트 이해하기
Rigidbody는 게임 오브젝트에 물리적 특성을 부여해 중력, 힘, 토크 등의 물리 법칙을 적용하는 핵심 컴포넌트입니다. 이를 통해 오브젝트는 중력의 영향을 받고, 충돌이나 힘의 작용을 받아 현실적인 움직임을 하게 됩니다. 특히 플랫폼 게임, 액션 게임, 시뮬레이션 게임 등에서 물리적 상호작용을 자연스럽게 구현할 때 매우 중요한 역할을 합니다.
Rigidbody는 Unity의 Inspector 창에서 오브젝트에 쉽게 추가할 수 있습니다.

- Unity 에디터에서 원하는 게임 오브젝트를 선택합니다.
- Inspector 창에서 "Add Component" 버튼을 클릭합니다.
- "Physics" 카테고리에서 "Rigidbody"를 선택합니다.
기본 설정으로 추가된 Rigidbody는 중력의 영향을 받으며, 다른 물체와 충돌할 수 있는 물리적 특성을 가집니다.

- Mass (질량):
- 객체의 질량을 설정합니다. 기본값은 1이며, 질량은 중력의 영향을 받는 속도에는 영향을 주지 않지만, 힘과 충돌 시 반응에 영향을 미칩니다.
- Drag (항력):
- 객체가 이동할 때 공기 저항의 영향을 설정합니다. 0은 저항이 없음을 의미하며, 높은 값일수록 빠르게 감속합니다.
- Angular Drag (각 항력):
- 객체가 회전할 때 공기 저항의 영향을 설정합니다. 높은 값일수록 회전이 더 빨리 멈춥니다5.
- Use Gravity (중력 사용):
- 활성화되면 객체가 중력의 영향을 받습니다.
- Is Kinematic (키네마틱 여부):
- 활성화되면 객체는 물리 엔진에 의해 구동되지 않으며 Transform으로만 조작할 수 있습니다. 주로 애니메이션이나 이동 플랫폼에 사용됩니다4.
- Interpolate (보간):
- 객체의 움직임이 끊기는 것을 방지하기 위해 보간 옵션을 설정합니다. None, Interpolate, Extrapolate 옵션이 있습니다.
- Collision Detection (충돌 감지):
- 빠르게 움직이는 객체가 다른 객체를 통과하지 않도록 충돌 감지를 설정합니다. Discrete, Continuous 등의 옵션이 있습니다.
- Constraints (제약 조건):
- Freeze Position: 특정 축(X, Y, Z)에서 객체의 이동을 막습니다.
- Freeze Rotation: 특정 축에서 객체의 회전을 막습니다.
1.2 전역 중력 설정
Project Settings에서 중력 조정 방법

- 3D 프로젝트:
- Unity 메뉴에서 Edit > Project Settings > Physics로 이동합니다.
- Gravity 설정에서 X, Y, Z 축의 중력 값을 조정할 수 있습니다. 기본적으로 Y축에 -9.81로 설정되어 있습니다.
- 2D 프로젝트:
- Edit > Project Settings > Physics 2D로 이동합니다.
- 마찬가지로 Y축의 중력 값을 조정할 수 있습니다. 기본값은 -9.81입니다.
2D와 3D 프로젝트의 중력 설정 차이
- 3D 프로젝트: 중력은 X, Y, Z축 모두에 적용되며, Y축의 기본값은 -9.81로, 중력이 아래쪽으로 작용하도록 설정되어 있습니다.
- 2D 프로젝트: 중력은 XY 평면에서만 작용하며, 보통 Y축에만 적용됩니다. 따라서 2D 캐릭터는 위아래로만 중력의 영향을 받게 됩니다.
다양한 행성 환경 시뮬레이션을 위한 중력 값 예시
전역 중력 값을 조정하면 다양한 행성이나 환경을 시뮬레이션할 수 있습니다. 예를 들어:
- 지구: -9.81 (기본값)
- 달: 약 -1.62
- 화성: 약 -3.71
- 목성: 약 -24.79
1.3 개별 오브젝트의 중력 조절
Unity에서 개별 오브젝트의 중력을 조절하는 방법은 두 가지가 있습니다: Rigidbody의 useGravity 속성 활용과 스크립트를 통한 동적 중력 제어입니다.
Rigidbody의 useGravity 속성 활용
useGravity 속성을 통해 오브젝트가 중력의 영향을 받을지 여부를 간단하게 설정할 수 있습니다. 기본적으로 이 속성은 활성화되어 있어, 오브젝트는 전역 중력의 영향을 받습니다. 그러나 특정 오브젝트에서 중력을 비활성화하려면 이 속성을 끄면 됩니다.
Rigidbody rb = GetComponent<Rigidbody>();
rb.useGravity = false; // 중력 비활성화
스크립트를 통한 동적 중력 제어
런타임 중 특정 상황에 따라 오브젝트의 중력 상태를 동적으로 변경하려면 C# 스크립트를 사용하여 제어할 수 있습니다. 예를 들어, 키 입력에 따라 중력을 켜거나 끄는 등의 동작을 구현할 수 있습니다.
using UnityEngine;
public class GravityControl : MonoBehaviour
{
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
// G 키를 눌러 중력 토글
if (Input.GetKeyDown(KeyCode.G))
{
rb.useGravity = !rb.useGravity;
}
}
}
또한, 특정 방향으로 중력을 적용하거나, 오브젝트에 맞는 커스텀 중력 값을 추가할 수도 있습니다. 이 부분은 밑에서 응용 문제로 더 자세하게 다룰 예정입니다. 간단한 예시를 먼저 보여드리겠습니다.
void ApplyCustomGravity(Vector3 gravityDirection, float gravityStrength)
{
rb.AddForce(gravityDirection * gravityStrength);
}
void Update()
{
Vector3 customGravity = new Vector3(-1f, 0, 0); // 왼쪽 방향으로 중력 적용
ApplyCustomGravity(customGravity, 9.81f); // 중력값 적용
}
이렇게 스크립트를 통해 오브젝트의 중력을 유동적으로 제어함으로써, 게임 내에서 더 다양한 물리적 상호작용을 구현할 수 있습니다.
2. 중력 시스템 실습
2.1 간단한 낙하 물체 만들기
Unity에서 기본 큐브에 Rigidbody를 추가하여 간단한 낙하 물체를 만들고, 낙하 속도를 조절하며 충돌 처리를 구현할 수 있습니다.
기본 큐브 생성 및 Rigidbody 추가
- 큐브 생성:
- Unity 에디터에서 Hierarchy 창을 우클릭한 후 3D Object > Cube를 선택하여 기본 큐브를 생성합니다.
- Rigidbody 추가:
- 생성된 큐브를 선택한 후 Inspector 창에서 Add Component 버튼을 클릭합니다.
- "Rigidbody"를 검색하고 선택하여 큐브에 Rigidbody 컴포넌트를 추가합니다. 이를 통해 큐브는 중력의 영향을 받아 자유 낙하하게 됩니다.

낙하 속도 조절 및 충돌 처리
Rigidbody의 Mass, Drag, Angular Drag 값을 조절하여 물체의 낙하 속도를 제어할 수 있습니다. 또한, 큐브에는 기본적으로 Box Collider가 포함되어 있어 다른 물체와의 충돌을 처리할 수 있습니다.
- Mass: 물체의 질량을 설정하여 낙하 속도에 영향을 줍니다.
- Drag: 공기 저항을 설정하여 낙하 속도를 조절할 수 있습니다.
- Angular Drag: 물체가 회전할 때의 저항을 설정합니다.
낙하 물체 스크립트 예제
아래는 낙하 속도를 조절하고, 충돌 처리를 위한 간단한 스크립트 예제입니다.
using UnityEngine;
public class FallingObject : MonoBehaviour
{
private Rigidbody rb;
void Start()
{
// Rigidbody 컴포넌트 초기화
rb = GetComponent<Rigidbody>();
rb.mass = 1f; // 질량 설정
rb.drag = 0.1f; // 항력 설정
rb.angularDrag = 0.05f; // 각 항력 설정
}
void Update()
{
// 스페이스바를 눌렀을 때 낙하 속도를 증가시키는 로직
if (Input.GetKeyDown(KeyCode.Space))
{
rb.AddForce(Vector3.down * 10f, ForceMode.Impulse);
}
}
void OnCollisionEnter(Collision collision)
{
// 충돌 발생 시 로직 처리
Debug.Log("충돌 발생: " + collision.gameObject.name);
}
}
이 스크립트는 Rigidbody의 기본 속성(질량, 항력 등)을 설정하고, 특정 키 입력(예: 스페이스바)을 통해 낙하 속도를 제어합니다. 또한, 충돌이 발생했을 때 OnCollisionEnter 메서드가 호출되어 충돌 메시지를 출력합니다
2.2 중력을 이용한 점프 구현
Unity에서 캐릭터의 점프 기능을 구현하는 방법을 설명하며, 기본적인 점프 로직과 기본 점프 로직과 지면 감지를 통해 자연스러운 점프 메커니즘을 구현합니다. 이어서 다중 점프(더블 점프, 삼단 점프)까지 다루어 보겠습니다.
캐릭터 컨트롤러 기본 설정
- Rigidbody 및 Collider 추가:
- 캐릭터 오브젝트에 Rigidbody와 Collider(예: Box Collider 또는 Capsule Collider)를 추가합니다. Rigidbody는 캐릭터가 중력의 영향을 받도록 하고, Collider는 지면과의 충돌을 감지하게 합니다.
- Rigidbody의 Use Gravity 옵션을 활성화하여 중력의 영향을 받도록 설정합니다.
- 지면 체크:
- 캐릭터가 지면에 있는지 확인하기 위해 OnCollisionEnter와 OnCollisionExit 메서드를 사용하여 지면과의 충돌을 감지합니다. 지면에 닿으면 isGrounded 변수를 true로 설정하고, 지면에서 떨어지면 false로 설정합니다. 이 때, 지면으로 활용할 오브젝트에 'Ground' 라는 태그를 만들어 추가합니다.
점프력 계산 및 적용
캐릭터가 점프하려면 AddForce 메서드를 사용하여 Y축 방향으로 힘을 가해야 합니다. 이때, isGrounded 변수를 이용해 캐릭터가 지면에 있을 때만 점프할 수 있도록 합니다.은 캐릭터의 질량, 중력, 그리고 원하는 점프 높이에 따라 계산됩니다.
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float jumpForce = 5f; // 점프 힘 설정
private bool isGrounded; // 캐릭터가 지면에 있는지 여부 확인
private Rigidbody rb;
void Start()
{
// Rigidbody 초기화
rb = GetComponent<Rigidbody>();
}
void Update()
{
// 스페이스바를 눌렀을 때 점프 처리
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
}
// 지면에 닿았을 때 호출
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = true;
Debug.Log("Grounded");
}
}
// 지면에서 벗어났을 때 호출
void OnCollisionExit(Collision collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = false;
Debug.Log("Not Grounded");
}
}
}
기존 큐브에 붙어 있던 FallingObject 스크립트를 제거한 후, 위에서 작성한 PlayerController 스크립트를 추가합니다. 그런 다음, Play 버튼을 누르고 Space 키를 누르면 큐브가 점프하는 모습을 확인할 수 있습니다.
이 스크립트는 캐릭터가 지면에 있을 때만 점프할 수 있도록 구현되었습니다. OnCollisionEnter와 OnCollisionExit 메서드를 사용해 캐릭터가 지면에 닿았는지 여부를 감지하여 isGrounded 변수를 관리합니다. 이 변수를 이용해 캐릭터가 공중에 있을 때는 점프하지 않도록 제어합니다.
다중 점프 구현 (더블 점프, 삼단 점프)
다중 점프를 구현하려면 공중에 있을 때도 점프를 허용하도록 jumpCount 변수를 추가해 점프 횟수를 관리할 수 있습니다. 이를 통해 더블 점프 또는 삼단 점프 같은 기능을 구현할 수 있습니다.
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float jumpForce = 5f; // 점프 힘 설정
public int maxJumpCount = 2; // 최대 점프 횟수 설정 (더블 점프)
private int jumpCount; // 현재 점프 횟수
private bool isGrounded; // 지면 감지
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
jumpCount = 0; // 점프 횟수 초기화
}
void Update()
{
// 점프 처리
if (Input.GetKeyDown(KeyCode.Space) && (isGrounded || jumpCount < maxJumpCount))
{
rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z); // Y축 속도 초기화
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse); // 점프 힘 적용
jumpCount++; // 점프 횟수 증가
}
}
// 지면에 닿았을 때 점프 횟수 초기화
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = true;
jumpCount = 0; // 지면에 닿으면 점프 횟수 초기화
}
}
// 지면에서 벗어났을 때
void OnCollisionExit(Collision collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = false;
}
}
}
이 스크립트는 maxJumpCount를 사용해 더블 점프나 삼단 점프를 구현할 수 있습니다. jumpCount 변수를 통해 점프 횟수를 관리하고, 공중에서 추가 점프를 허용합니다. 캐릭터가 지면에 닿으면 점프 횟수가 초기화됩니다.
핵심 포인트:
- 점프력은 캐릭터의 Rigidbody에 힘을 가해 Y축 방향으로 점프를 실행합니다.
- 다중 점프는 점프 횟수를 추적하여 공중에서도 추가 점프를 허용하는 방식으로 구현할 수 있습니다.
2.3 중력 방향 변경 실험
Unity에서는 중력 방향을 변경하여 캐릭터가 벽을 걷거나 행성 주변에서 중력에 따라 움직이는 다양한 시뮬레이션을 구현할 수 있습니다. 중력의 기본 방향은 Y축 하향(-9.81f)이지만, 이를 변경하여 독특한 물리적 효과를 만들 수 있습니다.
중력 방향을 변경하여 벽 걷기 구현
이 코드는 캐릭터가 벽을 따라 이동할 수 있도록 중력 방향을 변경하는 방식으로 커스텀 중력을 적용한 방식입니다. Physics.gravity를 사용하지 않고, Rigidbody.AddForce 메서드를 사용해 개별 오브젝트에 커스텀 중력을 적용하는 방식입니다. 이 방식은 중력의 방향을 동적으로 변경하여 캐릭터가 벽이나 다른 표면을 따라 움직일 수 있게 합니다.
using UnityEngine;
public class WallWalkController : MonoBehaviour
{
public Vector3 gravityDirection = Vector3.down; // 기본 중력 방향 (아래로)
public float gravityStrength = 9.81f; // 중력의 세기
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
rb.useGravity = false; // 전역 중력 비활성화
}
void FixedUpdate()
{
// 중력 방향과 세기에 따라 커스텀 중력 적용
rb.AddForce(gravityDirection * gravityStrength, ForceMode.Acceleration);
}
}
스크립트를 오브젝트에 부착한 후, Inspector에서 Gravity direction의 XYZ 값을 조정하여 원하는 방향으로 중력을 설정할 수 있으며, gravityStrength 값을 조절하여 중력의 세기도 변경할 수 있습니다.

행성 주변 중력 시뮬레이션
행성 주변에서 캐릭터가 움직이는 시뮬레이션을 구현하려면, 캐릭터가 행성의 중심을 향해 끌리도록 중력 방향을 설정해야 합니다. AddForce를 사용해 캐릭터가 행성 중심을 향해 끌려가게 하여, 표면을 따라 자유롭게 이동할 수 있도록 구현할 수 있습니다.
먼저 기존에 있던 땅, 벽, 그리고 큐브를 비활성화한 뒤, 행성의 역할을 할 새로운 Sphere를 생성하겠습니다. 생성한 Sphere의 Scale을 10으로 설정하고, 화면 중앙에 적절히 배치하겠습니다.

이후 Cube를 생성하고 Rigidbody를 추가합니다. 행성과 구분하기 위해 Cube에 Material을 적용해 색상을 변경해주면 좋을 것 같습니다.
다음 스크립트를 작성하고, 생성한 큐브에 부착하고 planetCenter에 Plant를 부여합니다.
using UnityEngine;
public class PlanetGravity : MonoBehaviour
{
public Transform planetCenter; // 행성의 중심
public float gravityStrength = 9.81f; // 중력의 세기
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
rb.useGravity = false; // 전역 중력 비활성화
}
void FixedUpdate()
{
// 행성 중심을 향한 중력 적용
Vector3 directionToCenter = (planetCenter.position - transform.position).normalized;
rb.AddForce(directionToCenter * gravityStrength, ForceMode.Acceleration);
}
}
이 스크립트는 캐릭터가 행성의 중심을 향해 중력을 받아 표면을 따라 이동할 수 있도록 합니다. AddForce를 사용해 행성 중심을 향한 중력을 구현하여, 캐릭터가 자연스럽게 행성 표면에 붙어서 이동하는 느낌을 줄 수 있습니다.

실행하면 다음과 같이 나타납니다.
3. 중력 시스템 응용: 맞바람 효과 구현
3.1 맞바람 시스템 개념 소개
실제 물리 현상과 게임 내 구현의 차이
맞바람은 물체가 이동하는 방향과 반대로 작용하는 바람으로, 실제로는 속도를 줄이고 물체에 저항을 가하며 방향을 변경하는 데 영향을 미칩니다. 예를 들어, 차량이 맞바람을 맞고 주행하면 연료 소모가 늘어나고 속도가 느려집니다.
게임에서는 맞바람 효과를 실제 물리와 다르게 구현하는 경우가 많습니다. 물리적 정확성보다는 게임플레이에 초점을 맞춰 단순화하거나 특정 요소만 구현하는 방식으로 적용합니다. 게임 내 맞바람 효과는 물체나 캐릭터의 이동 속도를 감소시키거나, 공중에 떠 있는 오브젝트가 바람에 밀리는 방식으로 표현됩니다.
맞바람 효과가 게임플레이에 미치는 영향
맞바람은 게임플레이에 다양하게 영향을 미칩니다. 플랫폼 게임에서 캐릭터가 점프할 때 맞바람이 불면 공중에서 이동 속도가 느려지거나, 반대로 밀려나는 등의 효과가 나타날 수 있습니다. 이러한 맞바람 효과는 난이도를 조절하거나 전략적 요소를 추가하는 데 유용합니다.
- 속도 저하: 맞바람은 캐릭터나 물체의 이동 속도를 줄여 더 느리게 움직이도록 만듭니다. 플레이어는 이 저항을 극복하기 위한 추가적인 계획이 필요합니다.
- 조작 난이도 증가: 맞바람이 강하게 불 때는 더 정교한 조작이 필요하며, 이는 특정 구간에서 게임의 난이도를 높이는 요소로 작용할 수 있습니다.
- 리얼리즘 강화: 맞바람은 현실적인 물리 효과를 추가하여 게임의 몰입감을 높이며, 게임 세계가 더욱 생동감 있게 느껴지도록 돕습니다.
맞바람 시스템은 게임의 역동성을 높이고 플레이어에게 새로운 도전 과제를 제공하며, 게임의 현실감과 몰입도를 증가시키는 중요한 요소로 작용합니다.
3.2 구현 단계 상세 설명
새로운 Scene에서 작업하기 위해 새 Scene을 만들고 이동하겠습니다. 새 Scene에서도 Ground를 미리 만들어줍시다.
바람 영역 설정
- Box Collider를 이용한 트리거 영역 생성:
- 바람이 작용할 영역을 설정하기 위해 Box Collider를 사용하여 트리거 영역을 생성합니다.
- 빈 오브젝트를 생성하고 Box Collider를 부착하여 Box Collider만 있는 오브젝트를 생성할 수 있습니다.
- Is Trigger 옵션을 활성화하여 캐릭터나 오브젝트가 충돌하지 않고 바람의 영향을 감지하도록 설정합니다.
- Collider 크기는 원하는 바람 영역에 맞게 조정합니다.
- 바람 영역의 시각적 표현 (파티클 시스템 활용):
- Particle System을 사용하여 바람의 시각적 효과를 추가합니다.
- 파티클의 속도와 크기, 색상을 바람의 세기와 일치하도록 설정하여 플레이어가 바람을 시각적으로 인지할 수 있게 합니다.
- 이번 포스트에서는 파티클 시스템을 만드는 방법은 다루지 않습니다.
WindSystem 스크립트 작성
- 바람의 힘과 방향 정의:
바람의 방향과 세기를 Vector3로 정의하고, 바람의 세기는 상황에 맞춰 유연하게 변경될 수 있습니다. 예를 들어, X축 방향으로 바람을 설정하려면 new Vector3(1, 0, 0)처럼 설정합니다. - 트리거 감지 및 힘 적용 로직:
OnTriggerStay 메서드를 사용해 오브젝트가 바람 영역에 들어오면 Rigidbody에 바람의 힘을 가합니다.
public class WindSystem : MonoBehaviour
{
public Vector3 windDirection = Vector3.right; // 바람의 방향
public float windStrength = 10f; // 바람의 세기
void OnTriggerStay(Collider other)
{
Rigidbody rb = other.GetComponent<Rigidbody>();
if (rb != null)
{
rb.AddForce(windDirection.normalized * windStrength);
}
}
}
바람 영역에 스크립트 적용
- Inspector를 통한 바람 속성 조정:
WindSystem 스크립트를 적용한 후, Inspector 창에서 바람의 세기와 방향을 유연하게 조정할 수 있습니다. 이를 통해 각 영역마다 다른 바람의 효과를 설정할 수 있습니다. - 런타임 중 동적 바람 변화 구현:
InvokeRepeating 또는 Update 메서드를 사용해 바람의 세기나 방향이 시간에 따라 변화하도록 구현할 수 있습니다. 이벤트에 따라 바람이 강해지거나 약해지게 할 수 있습니다.
using UnityEngine;
public class WindSystem : MonoBehaviour
{
public Vector3 windDirection = Vector3.right; // 바람의 방향
public float windStrength = 10f; // 바람의 세기
public float changeInterval = 5f; // 바람 변경 간격
public float maxStrengthChange = 5f; // 바람 세기 변경 폭
void Start()
{
InvokeRepeating("ChangeWind", changeInterval, changeInterval);
}
void ChangeWind()
{
windStrength += Random.Range(-maxStrengthChange, maxStrengthChange);
windStrength = Mathf.Clamp(windStrength, 0f, 20f);
}
void OnTriggerStay(Collider other)
{
Rigidbody rb = other.GetComponent<Rigidbody>();
if (rb != null)
{
rb.AddForce(windDirection.normalized * windStrength);
}
}
}
캐릭터 설정
- 플레이어 캐릭터의 Rigidbody 최적화:
- Rigidbody의 Mass(질량), Drag(항력), Angular Drag 등을 적절히 설정하여 캐릭터가 바람에 적절하게 반응하도록 최적화합니다.
- 무거운 캐릭터일수록 바람에 덜 밀리고, 가벼운 캐릭터일수록 바람에 쉽게 밀리도록 설정할 수 있습니다.
4. 중력 시스템 응용: 커스텀 중력 필드 및 블랙홀 구현
4.1 사용자 정의 중력 필드 구현
중력 영역 설정
- "GravityField" 빈 게임 오브젝트 생성
- SphereCollider 컴포넌트 추가 및 "Is Trigger" 활성화
- SphereCollider의 반경 조정하여 중력 영향 범위 설정
복잡한 중력 환경 시뮬레이션
복잡한 중력 환경을 구현하기 위해 개별적인 중력 필드를 설정하거나, 특정 구역마다 중력을 동적으로 적용할 수 있습니다. 이를 통해 다양한 중력 상황을 게임에서 시뮬레이션할 수 있습니다. 예를 들어, 행성 주변 중력, 반중력 구역, 중력이 점차 강해지는 구역을 만들 수 있습니다.
핵심 개념:
- 지역별 중력: 각 구역마다 중력을 다르게 설정하여 캐릭터나 오브젝트가 해당 구역에 들어오면 중력의 영향을 다르게 받도록 할 수 있습니다.
- 중력 방향 변경: 특정 구역에 진입하면 중력 방향을 변경하여 캐릭터가 벽이나 다른 표면을 걷는 등의 다양한 중력 환경을 구현할 수 있습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CustomGravityField : MonoBehaviour
{
private Transform gravitySource; // 중력의 중심 (예: 행성)
public float gravityStrength = 9.81f; // 중력 세기
private void Start()
{
gravitySource = transform;
}
void OnTriggerStay(Collider other)
{
Rigidbody rb = other.GetComponent<Rigidbody>();
if (rb != null)
{
Vector3 gravityDirection = (gravitySource.position - other.transform.position).normalized;
rb.AddForce(gravityDirection * gravityStrength);
}
}
}
설명:
- gravitySource: 중력의 중심을 나타내는 위치입니다. 예를 들어, 행성이나 특정 오브젝트를 중심으로 중력 방향을 계산합니다.
- OnTriggerStay: 트리거 영역 안에 있는 오브젝트에 대해 중력 방향을 계산하고, AddForce로 중력을 가합니다. 중력 방향은 중심점에서 오브젝트로 향하며, 중력의 세기는 조절할 수 있습니다.
4.2 블랙홀 효과 구현
블랙홀 효과는 중력이 점점 강해지며, 가까이 갈수록 더 강한 중력에 의해 물체가 빨려 들어가는 현상을 구현합니다. 중력의 세기를 거리에 따라 비선형적으로 증가시켜, 블랙홀에 가까워질수록 강한 가속도를 얻고 결국 블랙홀 중심으로 빨려 들어가는 효과를 만듭니다. 이후 중심에 도달하면 오브젝트가 블랙홀에 고정되는 효과를 제공합니다. SphereCollider를 사용하여 중력 범위를 설정하고, 거리에 따라 중력 세기를 동적으로 변경합니다.
using UnityEngine;
public class BlackHole : MonoBehaviour
{
public float gravityStrength = 100f; // 기본 중력 세기
public float maxDistance = 10f; // 사건의 지평선 (중력 범위)
public float holdThreshold = 0.5f; // 블랙홀 중심에 고정될 거리
private SphereCollider sphereCollider;
private void Start()
{
// SphereCollider 설정 및 maxDistance 연동
sphereCollider = GetComponent<SphereCollider>();
if (sphereCollider != null)
{
sphereCollider.isTrigger = true; // 트리거로 설정
}
UpdateColliderRadius();
}
// Update에서 Inspector 값이 변경되면 실시간 반영
private void Update()
{
UpdateColliderRadius();
}
// Collider의 반경을 실시간으로 maxDistance와 동기화
private void UpdateColliderRadius()
{
if (sphereCollider != null)
{
sphereCollider.radius = maxDistance; // SphereCollider의 반경을 maxDistance로 설정
}
}
// 트리거 안에 있는 오브젝트에 중력을 적용
void OnTriggerStay(Collider other)
{
Rigidbody rb = other.GetComponent<Rigidbody>();
if (rb != null)
{
Vector3 directionToCenter = transform.position - other.transform.position;
float distance = directionToCenter.magnitude;
if (distance < maxDistance)
{
if (distance > holdThreshold)
{
// 거리에 따라 중력 세기 조정 (거리에 반비례)
float gravityEffect = gravityStrength / Mathf.Pow(distance, 2);
rb.AddForce(directionToCenter.normalized * gravityEffect);
}
else
{
// 중심에 가까워지면 오브젝트를 고정
rb.velocity = Vector3.zero; // 오브젝트의 속도를 0으로 설정
rb.position = transform.position; // 블랙홀 중심으로 이동
}
}
}
}
}
주요 변수 설명:
- gravityStrength: 블랙홀이 작용하는 기본 중력 세기입니다. 오브젝트가 블랙홀에 가까워질수록 중력의 강도가 더 강해집니다.
- maxDistance: 블랙홀의 사건의 지평선(Event Horizon)으로, 이 범위 내에서 중력이 작용하며, 해당 범위를 벗어나면 중력의 영향을 받지 않습니다.
- holdThreshold: 블랙홀 중심에 도달했을 때, 오브젝트가 블랙홀 중심에 고정되는 거리를 설정합니다.
중력 세기와 고정 효과
- 거리에 따른 중력 적용: 오브젝트가 블랙홀에 가까워질수록 중력의 세기가 강해지며, 이는 거리에 반비례하여 계산됩니다. 블랙홀 중심으로 향하는 힘이 거리의 제곱에 반비례하도록 설정하여, 가까울수록 중력의 힘이 급격히 증가하는 비선형 효과를 제공합니다.
- 중심 고정: 오브젝트가 holdThreshold 거리 이내로 접근하면, 중력을 더 이상 적용하지 않고, 오브젝트의 속도를 0으로 설정하여 블랙홀 중심에 고정됩니다. 이를 통해 오브젝트가 블랙홀에 빨려 들어가는 듯한 느낌을 제공할 수 있습니다.
추가적인 시각적 효과 (선택 사항)
- 블랙홀 주위에 Particle System을 추가하여, 입자가 블랙홀 중심으로 빨려 들어가는 시각적 효과를 추가할 수 있습니다.
- Post-processing을 사용하여 블랙홀 주변의 시각적 왜곡 효과를 구현하면 더욱 몰입감 있는 경험을 제공합니다
5. 물리 기반 시스템 사용 시 주의사항 및 팁
5.1 물리 기반 시스템의 일반적인 문제점과 해결 방법
물리 시스템을 구현할 때 자주 발생하는 문제와 그 해결 방법은 다음과 같습니다:
- 오브젝트가 충돌을 통과하는 문제:
충돌이 감지되지 않거나 물체가 서로 겹치는 문제가 발생할 수 있습니다. 특히 빠르게 움직이는 오브젝트는 프레임 간 충돌이 누락될 수 있습니다.- 해결 방법:
- Continuous Collision Detection을 사용하여 고속 이동하는 물체의 충돌을 정확히 처리합니다.
- 시뮬레이션 스텝 수를 증가시키거나 Time.fixedDeltaTime을 적절히 조정해 물리 연산의 빈도를 높입니다.
- 해결 방법:
- 오브젝트가 떨리면서 진동하는 문제:
충돌 처리 후 오브젝트가 제대로 정지하지 못하고 진동하는 현상이 나타날 수 있습니다.- 해결 방법:
- 충돌체의 마찰 계수(Friction)와 반발 계수(Bounce) 값을 조정하여 자연스럽게 정지 상태로 만들 수 있습니다.
- Physics Material을 사용해 세부 물리 속성을 최적화합니다.
- 해결 방법:
- 비정상적으로 빠른 낙하 문제:
중력이나 물리 연산의 불균형으로 인해 물체가 비정상적으로 빠르게 떨어지는 현상이 발생할 수 있습니다.- 해결 방법:
- Fixed Timestep을 적절히 설정하여, 물리 연산이 일정한 시간 간격으로 처리되도록 하고 Time.fixedDeltaTime 값을 조정합니다.
- 해결 방법:
5.2 프레임 레이트 독립적인 물리 시스템 구현
물리 시스템은 프레임 레이트에 영향을 받을 수 있으므로, 프레임 레이트 독립적인 물리 계산이 중요합니다. 이를 구현하기 위해 Unity에서는 FixedUpdate 메서드를 사용하여 물리 연산을 고정된 시간 간격으로 처리합니다.
- FixedUpdate: 물리 연산은 FixedUpdate에서 수행됩니다. FixedUpdate는 게임 프레임 속도와 상관없이 일정한 시간 간격으로 실행되므로, 물리 연산이 일정하게 처리됩니다.
void FixedUpdate()
{
// 물리 연산 처리
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
- Time.fixedDeltaTime: Unity에서 물리 엔진이 고정된 시간 간격으로 업데이트되도록 하는 설정입니다. 이 값을 통해 물리 연산이 프레임 속도에 상관없이 일정하게 유지됩니다.
- 프레임 레이트와 관계없는 움직임 구현:
csharp코드 복사void Update()
{
// 프레임에 독립적인 움직임
float moveSpeed = 5f;
transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
}
이 코드는 Time.deltaTime을 사용하여 프레임 속도에 따라 이동 거리가 조정되므로, 저속/고속 프레임 환경에서도 일관된 움직임을 유지할 수 있습니다.
5.3 디버깅 도구 및 기법 소개 (Physics Debugger 활용)
Unity는 물리 시스템을 디버깅할 수 있는 다양한 도구를 제공합니다. Physics Debugger는 물리 엔진의 동작을 시각적으로 확인하고, 문제를 발견하는 데 유용합니다.
- Physics Debugger
- Unity에서 Window > Analysis > Physics Debugger를 통해 물리 디버깅 창을 열 수 있습니다. 이를 통해 게임 내 물리 오브젝트의 충돌체, 중력, 속도 등을 실시간으로 확인하고 분석할 수 있습니다.
- Debug.Log
- 물리 상호작용을 확인하기 위해 중요한 이벤트나 상태를 출력합니다. 예를 들어, 충돌이 발생할 때 로그를 남겨 물리 상호작용이 정상적으로 작동하는지 점검할 수 있습니다.
void OnCollisionEnter(Collision collision)
{
Debug.Log("충돌 발생: " + collision.gameObject.name);
}
- Debug.DrawLine 및 Debug.DrawRay
- 충돌 검사와 레이캐스트를 시각적으로 확인하기 위해 유용한 기법입니다. 화면에 실제 물리적인 상호작용을 시각적으로 표시하여 디버깅할 수 있습니다.
- Unity Profiler
- Profiler를 사용하여 물리 연산의 성능을 분석하고 최적화 지점을 찾을 수 있습니다.
정리
- 물리 시스템의 문제 해결: 충돌 누락, 진동 문제, 비정상적인 속도 문제 등을 해결하기 위해 Collision Detection 모드 변경, 마찰 및 반발 계수 조정, Fixed Timestep 최적화를 적용합니다.
- 프레임 레이트 독립적인 물리 시스템: FixedUpdate와 Time.deltaTime을 사용하여 프레임에 무관한 일관된 물리 연산을 구현합니다.
- 디버깅 도구 활용: Physics Debugger, Debug.Log, Profiler 등 다양한 도구를 통해 물리 시스템의 작동 상태를 확인하고, 문제를 신속하게 해결할 수 있습니다.
결론: 중력 시스템의 게임 디자인에 미치는 영향
중력 시스템은 게임의 핵심 메커니즘 중 하나로, 플레이어의 몰입도와 게임의 재미를 크게 좌우합니다. 중력의 세기와 방향을 조절하거나 특수한 중력 효과를 적용하면, 게임의 난이도와 전략성을 높일 수 있으며, 플레이어에게 새로운 도전과 상호작용을 제공합니다.
또한, 중력은 캐릭터의 움직임을 다양하게 만들고, 감정적 경험을 강화하는 데도 중요한 역할을 합니다. 무중력 상태나 중력이 변화하는 환경은 게임의 분위기를 독특하게 만들어 줄 수 있습니다.
결론적으로, 중력 시스템을 창의적으로 활용하면 게임의 재미와 몰입감을 높일 수 있으며, 이를 통해 플레이어에게 더욱 풍부한 경험을 제공할 수 있습니다.
'Unity' 카테고리의 다른 글
| [Unity] 스크립터블 오브젝트(Scriptable Object) : 게임 데이터를 효율적으로 관리하는 방법 (0) | 2025.06.08 |
|---|---|
| [Unity] 네이버 지도 Dynamic Map API로 마커와 정보 창 구현하기 (3) | 2025.06.08 |
| [Unity] NavMesh를 활용한 AI 캐릭터 경로 탐색 구현 가이드 (3) | 2025.06.08 |
| [Unity] 유니티 레이캐스트(Raycast) 기초 : 이해 및 활용 (0) | 2025.06.08 |
| [Unity] 유니티 연습 개발 환경 기본 세팅 (2) | 2025.06.08 |