Table of Contents
🔥시나리오
<버거플리즈> 게임의 광고 영상을 보면 플레이어가 들고 나르고있는 햄버거들이 플레이어 이동 방향을 따라 관성의 영향을 받는듯한 연출이 보인다
→ 쉽게말하면 이동하면 휘어진다
퍼포먼스에 자유롭다면 유니티의 스프링 조인트 컴포넌트를 쓸 수도 있지만 물리 연산이기때문에 저렇게 많이 쌓인다면 부담이 클것이다 (근데 저 게임도 예시 이미지만큼 많이 들고다니진 않는다 광고용 연출인듯)
그럼 에셋스토어의 다이나믹본 같은 스프링 본 효과를 구현하면 스프링 조인트 컴포넌트를 쓰는것보단 퍼포먼스가 훨 나을것이다
🔥스프링 본 구현
먼저 결과 코드는 아래와 같다
public Transform player; // 플레이어 오브젝트
public List<Transform> blocks; // 블록들
public float stiffness = 5f; // 탄성 정도
public float damping = 2f; // 감쇠(떨림 완화)
public float inertiaMultiplier = 0.5f; // 관성 효과 조절
private Vector3[] velocities; // 블록별 속도
private Vector3 previousPlayerPos; // 이전 프레임의 플레이어 위치
void Start() {
velocities = new Vector3[blocks.Count];
previousPlayerPos = player.position; // 초기 위치 저장
}
void Update() {
// 플레이어의 이동 변화량(속도)을 계산
Vector3 playerMovementDelta = player.position - previousPlayerPos;
for (int i = 1; i < blocks.Count; i++) {
// 플레이어 이동량을 반영한 목표 위치 (관성 효과 추가)
Vector3 targetPos = blocks[i - 1].position - playerMovementDelta * inertiaMultiplier;
targetPos.y = carrier.CarriedObjects[i].position.y; // 쌓여있는 연출이기에 y축은 움직이지 않게함
// 스프링 힘 계산 (월드 좌표)
Vector3 force = (targetPos - blocks[i].position) * stiffness;
velocities[i] += force * Time.deltaTime;
velocities[i] *= (1 - damping * Time.deltaTime);
// 위치 업데이트
blocks[i].position += velocities[i] * Time.deltaTime;
}
// 현재 플레이어 위치 저장
previousPlayerPos = player.position;
}
찾아보니 이러한 시스템을 Spring-Damper Model(혹은 System)이라고 하는 것 같다
단계별 설명
1️⃣ 플레이어의 이동량 계산
Vector3 playerMovementDelta = player.position - previousPlayerPos;
- 플레이어의 한 프레임 이동 변화량을 계산한다
- 내 시나리오에선 블록들이 플레이어의 자식 오브젝트여야 하기에 플레이어의 이동 변화량을 가지고 계산해야했다
2️⃣ 목표 위치 계산
Vector3 targetPos = blocks[i - 1].position - playerMovementDelta * inertiaMultiplier;
targetPos.y = carrier.CarriedObjects[i].position.y;
- 바로 아래에 있는 블록(`blocks[i - 1]`)의 xy포지션을 따라가되, 약간 뒤처지도록 한다
- 뒤처지게 함으로 관성에의해 밀린 느낌을 주게된다
3️⃣ 스프링 힘 계산
Vector3 force = (targetPos - blocks[i].position) * stiffness;
- 블록이 목표 위치와 얼마나 떨어져 있는 지(`targetPos - blocks[i].position`)에 따라 더 많이 떨어질수록 벡터는 더 큰 길이가 된다
- `force`는 `stiffness`가 가미됐지만 목표 위치로 향하는 길이가 포함된 방향 벡터이기 때문에 목표 위치로 보내주는 힘이다
📝 여기서 `stiffness`는 얼마나 빨리 목표 위치로 돌아가려는지를 조절한다
- 크게 설정 → 빠르고 딱딱한 느낌
- 작게 설정 → 부드럽고 느린 느낌
4️⃣ 속도 업데이트 (관성 + 감쇠)
velocities[i] += force * Time.deltaTime;
velocities[i] *= (1 - damping * Time.deltaTime);
- 블록의 이동 속도, 방향을 업데이트한다
📝 여기서 `damping`은 흔들림이 얼마나 빠르게 줄어드는지를 조절한다
- 크게 설정 → 빨리 멈춤 (덜 흔들림)
- 작게 설정 → 오래 흔들림
- `damping`이 속도를 더 작고 촘촘 하게 만들어서 더 촘촘하고 느리게 움직이게 만들고, 촘촘히 움직이면 목표위치를 지나치지 않기에 흔들림이 덜 해진다
🔥결과
이제 수치들을 좀 조율해주면 부드럽게 움직이는 스프링 효과를 볼 수 있다
'Unity > C#' 카테고리의 다른 글
[Unity] 3D 탑다운 무한 맵 (0) | 2024.11.09 |
---|---|
[Unity] Cinemachine으로 모바일 3인칭 카메라 만들기 (0) | 2024.07.04 |
[C#] 빠르게 C# 단일 스크립트를 슥 작성하고 쇽 실행하는 법 (polyglot notebooks) (0) | 2024.06.27 |
[Unity] JsonUtility.ToJson() 대신 Jobject.FromObject()를 쓰자 (1) | 2024.06.17 |
[Unity] Unity 3D Game Kit Lite템플릿 Damageable스크립트 분석 (1) | 2024.05.22 |