유니티/기능
리지드바디(Rigidbody), 이동, 회전, 폭발
MJ_119
2024. 6. 24. 23:02
출처 : https://www.youtube.com/watch?v=_U7qUUfRMYs
FixedUpdate와 Update의 차이
- FixedUpdate:
- 물리 계산: FixedUpdate는 물리 계산이 이루어지는 고정된 시간 간격(기본적으로 0.02초)마다 호출됩니다.
- 일관성: 물리 엔진과의 일관성을 유지합니다. 물리 엔진의 시간 스텝과 동일한 간격으로 호출되므로, 물리적 상호작용이 정확하고 예측 가능하게 동작합니다.
- 사용 사례: 물리와 관련된 모든 업데이트(예: Rigidbody의 이동, 힘 적용 등)는 FixedUpdate에서 처리하는 것이 권장됩니다.
- Update:
- 프레임 기반: Update는 매 프레임마다 호출되며, 프레임 속도에 따라 호출 빈도가 달라질 수 있습니다.
- 비일관성: 프레임 속도가 변동될 수 있기 때문에, 물리 엔진과의 상호작용이 일관되지 않을 수 있습니다.
- 사용 사례: 사용자 입력 처리, UI 업데이트 등 프레임 기반 로직에 사용됩니다.
중력 조절
- Edit -> Project Settings -> Physics -> Gravity에서 조절 가능.
RigidBody 속성
- Mass (질량):
- 객체의 무게를 결정합니다. 값이 클수록 객체가 무겁고, 물리적 상호작용 시 더 큰 힘이 필요합니다.
- Drag (저항):
- 객체가 이동할 때 공기 저항을 시뮬레이션하는 값입니다. 값이 클수록 객체의 속도가 더 빨리 감소합니다.
- Angular Drag (회전 저항):
- 객체가 회전할 때 공기 저항을 시뮬레이션하는 값입니다. 값이 클수록 객체의 회전 속도가 더 빨리 감소합니다.
- Use Gravity (중력 사용):
- 체크하면 객체에 중력이 적용됩니다. 체크 해제 시 객체는 중력의 영향을 받지 않습니다.
- Is Kinematic (키네마틱):
- 체크하면 객체는 물리 엔진의 영향을 받지 않고, 스크립트를 통해 직접 위치와 회전을 제어할 수 있습니다. 다른 객체와의 충돌은 감지하지만, 물리적 반응은 하지 않습니다.
- Interpolate (보간):
- 객체의 움직임을 부드럽게 만드는 옵션입니다.
- None: 보간을 사용하지 않습니다. 움직임이 뚝뚝 끊길 수 있습니다.
- Interpolate: 이전 프레임의 위치를 사용하여 부드러운 움직임을 만듭니다.
- Extrapolate: 다음 프레임의 예상 위치를 사용하여 부드러운 움직임을 만듭니다.
- 객체의 움직임을 부드럽게 만드는 옵션입니다.
- Collision Detection (충돌 감지):
- 충돌 감지 방식을 설정합니다.
- Discrete: 기본 충돌 감지 방식으로, 프레임 간의 충돌을 감지하지 못할 수 있습니다.
- Continuous: 고속으로 움직이는 객체의 충돌을 감지합니다. (예를들어 총알.)
- Continuous Dynamic: 고속으로 움직이는 동적 객체와의 충돌을 감지합니다.
- Continuous Speculative: 예측 기반 충돌 감지 방식으로, 충돌을 더 잘 감지하도록 합니다.
- 충돌 감지 방식을 설정합니다.
- Constraints (제약):
- 객체의 위치와 회전을 고정하거나 제한할 수 있습니다.
- Freeze Position: 특정 축에 대한 위치 이동을 고정합니다 (X, Y, Z).
- Freeze Rotation: 특정 축에 대한 회전을 고정합니다 (X, Y, Z).
- 객체의 위치와 회전을 고정하거나 제한할 수 있습니다.
오브젝트 이동시키기
- Drag를 높이면 공기저항으로 인해 떨어지는속도나 이동하는 속도가 서서히 느려짐
- velocity
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
private Rigidbody myRigid;
private void Start()
{
myRigid = GetComponent<Rigidbody>();
}
void Update()
{
if(Input.GetKey(KeyCode.R))
{
myRigid.velocity = Vector3.forward;
}
}
}
오브젝트 회전시키기
- angular Drag를 높이면 회전저항으로 인해 물체의 회전속도가 서서히 줄어듦.
- angularVelocity
- 물리적 힘을 사용하여 자연스러운 회전 운동을 만들 수 있습니다.
- 객체에 각속도를 적용하여 회전시킵니다.
- 다른 물리 객체와의 상호작용이 자연스럽습니다.
- 직접적인 각도 설정이 어렵고, 각속도를 조절해야 합니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
private Rigidbody myRigid;
private void Start()
{
myRigid = GetComponent<Rigidbody>();
}
void Update()
{
if(Input.GetKey(KeyCode.R))
{
myRigid.angularVelocity = Vector3.right;
}
}
}
- MoveRotation();
- 질량과 관성에 영향받지 않음.
- 물리효과 X
- 특정 각도로 바로 회전시키고 싶을 때 유용합니다.
- 물리적 힘을 사용하지 않기 때문에 예측 가능한 회전 결과를 얻을 수 있습니다.
- 물리 엔진의 영향을 받지 않기 때문에 자연스러운 회전 운동을 만들기 어렵습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
private Rigidbody myRigid;
private Vector3 rotation;
private void Start()
{
myRigid = GetComponent<Rigidbody>();
rotation = this.transform.eulerAngles;
}
void Update()
{
if(Input.GetKey(KeyCode.R))
{
rotation += new Vector3(90, 0, 0) * Time.deltaTime;
myRigid.MoveRotation(Quaternion.Euler(rotation));
}
}
}
- AddTorque()
- 객체에 토크(회전력)를 가하여 회전시킵니다.
- 물리적 힘을 사용하여 자연스러운 회전 운동을 만들 수 있습니다.
- 직접적인 각도 설정이 어렵습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
private Rigidbody myRigid;
private void Start()
{
myRigid = GetComponent<Rigidbody>();
}
void Update()
{
if(Input.GetKey(KeyCode.R))
{
myRigid.AddTorque(Vector3.up);
}
}
}
오브젝트 회전속도 늘리기
- maxAngularVelocity
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
private Rigidbody myRigid;
private void Start()
{
myRigid = GetComponent<Rigidbody>();
}
void Update()
{
if(Input.GetKey(KeyCode.R))
{
myRigid.maxAngularVelocity = 100; // 회전속도 최대치 증가
myRigid.angularVelocity = Vector3.right * 100;
}
}
}
@ MovePosition();
오브젝트를 특정 위치로 한번에 이동시키기
- 물리효과 X
- 강제로 순간이동
- 관성과 질량에 영향을 받지 않음
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
private Rigidbody myRigid;
private void Start()
{
myRigid = GetComponent<Rigidbody>();
}
void Update()
{
if(Input.GetKey(KeyCode.R))
{
myRigid.MovePosition(new Vector3(2,2,2));
}
}
}
using UnityEngine;
public class CharacterMovementRigidbody : MonoBehaviour
{
public float moveSpeed = 5f;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 moveDirection = new Vector3(moveHorizontal, 0.0f, moveVertical).normalized;
rb.MovePosition(transform.position + moveDirection * moveSpeed * Time.fixedDeltaTime);
}
}
설명
- 연속적인 이동: 이 코드는 캐릭터를 플레이어 입력에 따라 연속적으로 이동시키는 예제입니다.
- 물리 기반: Rigidbody를 사용하여 물리 법칙에 따라 이동이 이루어집니다.
- FixedUpdate: 물리 계산과 관련된 업데이트는 FixedUpdate에서 이루어지며, 이는 물리 시뮬레이션의 일관성을 유지하기 위해 고정된 시간 간격으로 호출됩니다.
- 충돌 처리: 이동 중에 다른 오브젝트와의 충돌이 자연스럽게 처리됩니다.
위 두개의 코드 차이점 요약
항목연속적인 이동 (CharacterMovementRigidbody)특정 위치로 순간 이동 (Test)
이동 방식 | 플레이어 입력에 따라 연속적인 이동 | 특정 키 입력 시 즉시 특정 위치로 이동 |
물리 기반 | 물리 법칙에 따라 이동 | 물리 법칙을 무시하고 강제로 이동 |
메서드 호출 위치 | FixedUpdate에서 호출 | Update에서 호출 |
관성 및 질량의 영향 | 관성과 질량에 영향을 받음 | 관성과 질량에 영향을 받지 않음 |
주 사용 사례 | 캐릭터와 같은 움직이는 오브젝트 | 순간 이동이나 텔레포트와 같은 경우 |
- Rigidbody.MovePosition을 FixedUpdate에서 사용하는 경우, 물리 기반의 자연스러운 이동을 구현할 수 있습니다. 이는 캐릭터의 연속적인 이동이나 물리적 상호작용이 중요한 경우에 적합합니다.
- Rigidbody.MovePosition을 Update에서 사용하는 경우, 특정 위치로 오브젝트를 강제로 이동시키는 데 사용할 수 있습니다. 이는 물리 법칙을 무시하고 즉시 특정 위치로 이동시켜야 하는 경우(예: 텔레포트)에 적합합니다.
- AddForce는 Rigidbody에 물리적 힘을 가하여 이동시키는 방법입니다.
- 물리 엔진의 영향을 받아 더 자연스러운 이동을 만들어 줍니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
private Rigidbody myRigid;
private void Start()
{
myRigid = GetComponent<Rigidbody>();
}
void Update()
{
if(Input.GetKey(KeyCode.R))
{
myRigid.AddForce(Vector3.forward);
}
}
}
물리적 상호작용이 중요한 경우 AddForce를, 특정 위치로 정확하게 이동시켜야 하는 경우 MovePosition을 사용하는 것이 좋습니다.
- AddExplosionForce(폭발세기, 폭발위치, 폭발반경)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
private Rigidbody myRigid;
private void Start()
{
myRigid = GetComponent<Rigidbody>();
}
void Update()
{
if (Input.GetKey(KeyCode.R))
{
myRigid.AddExplosionForce(20, this.transform.position, 20);
myRigid.AddExplosionForce(20, this.transform.right, 20);
}
}
}