[https://velog.io/write?id=b4644d46-72f3-404b-81a3-aca81ec2a7dc]
줍기 애니메이션과 연동해 쓰레기 프리팹을 손 오브젝트의 자식 오브젝트로 추가 & 위치를 고정.
쓰레기를 오른손 위치에 고정했을때 캐릭터가 뒷 방향으로 계속 스스로 움직임.
쓰레기 프리팹에는 RIGIDBODY컴포넌트가 적용되어 있으므로 캐릭터가 지나가다 건드린 프리팹을 주웠을 때 프리팹의 속도가 캐릭터에게 전이된것인가?
-> rb.linearVelocity = Vector3.zero;, rb.angularVelocity = Vector3.zero; 이런식으로 쓰레기 프리팹의 속도를 없앴다.
해결되지 않음.
중력을 지우고 kinematic 옵션을 켜보자.
isKinematic = true:isKinematic = false:물리적 반응을 없앴으므로 해결이 되어야 하지만 해결되진 않았다.
(시도 1 & 2 를 적용한 코드)
public void PickUpTrash()
{
if (currentTrash == null) return;
Rigidbody rb = currentTrash.GetComponent<Rigidbody>();
Collider trashCollider = currentTrash.GetComponent<Collider>();
if (rb != null)
{
rb.linearVelocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
rb.isKinematic = true;
rb.useGravity = false;
}
currentTrash.transform.SetParent(trashPosition);
currentTrash.transform.localPosition = Vector3.zero;
currentTrash.transform.localRotation = Quaternion.identity;
}
비교적 작은 찌그러진 캔 프리팹은 캐릭터가 밀려나지 않는다. 대왕 브로콜리나 대왕 크로와상같은 큰 프리팹을 주웠을 때만 뒤로 밀려난다. 콜라이더끼리 겹치면 생기는 오류인가?
-> 캐릭터가 밀려나고 있는 도중 is trigger 옵션을 체크해봄 -> 캐릭터 정지. 빙고
프리팹의 is trigger를 켰더니 로딩시 프리팹들이 바닥으로 가라앉는다... -> 주울때만 체크하고 던질때(물리적 상호작용이 필요할때) 체크 해제하자. -> 문제 해결
(최종 코드)
public void PickUpTrash()
{
if (currentTrash == null) return;
Rigidbody rb = currentTrash.GetComponent<Rigidbody>();
Collider trashCollider = currentTrash.GetComponent<Collider>();
if (rb != null)
{
rb.linearVelocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
rb.isKinematic = true;
rb.useGravity = false;
}
if (trashCollider != null)
{
// 물리 충돌을 막기 위해 트리거로 전환
trashCollider.isTrigger = true;
// 플레이어와의 충돌을 무시할 필요가 없다면, 아래는 생략 가능
}
currentTrash.transform.SetParent(trashPosition);
currentTrash.transform.localPosition = Vector3.zero;
currentTrash.transform.localRotation = Quaternion.identity;
}
아이디어는 매우 간단함.
줍기를 실행하고나선 쓰레기는 항상 캐릭터의 오른손에 고정돼 있다.
따라서 던지기 애니메이션이 나올 때 쓰레기를 원하는 시점에 오른손에서 분리하고, addForce를 사용해 전방으로 밀어내면 됨.

바로 지금!
public void ThrowTrash(Vector3 throwDirection, float throwForce)
{
if (currentTrash == null) return;
Collider trashCollider = currentTrash.GetComponent<Collider>();
// 자식 관계 해제
currentTrash.transform.SetParent(null);
if (trashCollider != null)
{
// 던지기 전에 다시 콜라이더를 일반 콜라이더로 되돌림
trashCollider.isTrigger = false;
}
Rigidbody rb = currentTrash.GetComponent<Rigidbody>();
if (rb != null)
{
rb.isKinematic = false;
rb.useGravity = true;
rb.AddForce(throwDirection * throwForce, ForceMode.Impulse);
}
currentTrash = null;
}
던지는 방향인 throwDirection 은 캐릭터가 바라보고 있는 방향으로 했었는데, 쓰레기가 너무 낮게 던져지는 느낌이 들어서
Vector3 throwDirection = playerCamera.transform.forward;
// throwDirection에 위쪽 벡터 추가하여 방향을 약간 위로 향하게 함
float elevationFactor = 0.3f;
throwDirection += Vector3.up * elevationFactor;
throwDirection.Normalize(); // 방향을 정규화하여 크기가 1이 되도록 함
이런식으로 정면보다 살짝 위를 향하도록 지정함.
던지는 힘은 마우스를 꾹 눌렀을때 값이 변하도록 설계 했다. 막대 슬라이더도 UI로 추가해 게이지가 얼마나 찼는지 확인하게끔 만들었음.
// 던지기 힘을 10~40 사이에서 사이클링
currentThrowForce += Mathf.Sin(Time.time * throwForceCycleSpeed) * Time.deltaTime * (maxThrowForce - minThrowForce) / 2f;
// 던지기 힘을 최소값과 최대값 사이로 클램프
currentThrowForce = Mathf.Clamp(currentThrowForce, minThrowForce, maxThrowForce);
// UI 슬라이더 업데이트 (min~max를 0~1로 정규화)
float normalizedForce = (currentThrowForce - minThrowForce) / (maxThrowForce - minThrowForce);
throwForceSlider.fillAmount = normalizedForce * 2;
ForceMode.Force
mass(질량)에 따라 적용된 힘의 효과가 다르게 나타납니다.ForceMode.Acceleration
mass와 상관없이 힘을 가속도로 적용합니다.ForceMode.Impulse
ForceMode.VelocityChange
대왕브로콜리와 찌그러진 캔은 질량이 차이가 날텐데, 따라서 날아가는 속도가 달랐으면 좋겠다.
던지는 행위는 지속적인 가속이 필요하지 않고 순간적인 힘만을 요구하기 때문에 가장 적절한 방법인 Impulse 를 사용함.
프로젝트를 시작하기 전에는 정말 간단한 프로젝트일거라 생각했지만, 생각보다 공부해야 할것도 너무 많고, 해야할 것들도 너무 많다. 어찌보면 내가 게임개발을 너무 만만하게 봤던게 맞다. 남들보다 늦게 시작한 만큼 앞으로도 꾸준히 정진해야하고 공부하는데 있어 요령피우면 안되겠다.
아무튼 내일 해야할것 :
1. 게임매니저 제작
2. 쓰레기통에 골인했을 때 점수올라가기 기능 구현
3. 잘못된 쓰레기통에 골인시 사운드, 성공시 사운드 구현
4. 전반적인 게임 UI구현
5. 깃헙 리포 제작
6. (시간적 여유가 된다면) 쓰레기 프리팹이 날아갈 때 방향과 속도에 영향을 줄 바람기능 구현