Notice
Recent Posts
Recent Comments
Link
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
Tags
more
Archives
Today
Total
관리 메뉴

개발일기

유니티#18 Rigidbody2D 아이템 줍기 구현 본문

Unity

유니티#18 Rigidbody2D 아이템 줍기 구현

kimjw7815 2025. 4. 29. 20:15

갑자기 만들고 싶어서 만들어봤다.

우선 잘 구르는 느낌을 내고 싶어서 Circle로 만들었고, Rigidbody2D와 Collider2D도 적용시켜줬다.

근데 캐릭터와 공이 부딪혀서, 잘못하면 줍기에 귀찮을 수도 있겠다 싶어서 플레이어와의 충돌을 끄려고, Layer 설정을 해줬다.

Player Layer랑 IgnoreColiisionWithPlayer Layer로 설정해주고, Edit>Project Settings>Physics2D>Layer Collsion Matrix에서 서로 충돌 안 하도록 설정해주었다.

 

그러고선 아래 사항만 적고선 코드 짜달라고 GPT한테 가져다 줬는데, 세부적인 것만 제외하면 잘 짜주더라.

코드 중간중간 요청사항에 보이지 않는 부분은 내가 직접 수정한 거다.

 

+ 공이 자꾸 벽에 충돌 안하고 넘어갈 땐 뭘 해준다? Collision Mode를 Continous로 설정해준다~

    // 오브젝트에 적용, 주변 반경 감지해서 radius 내에 플레이어 있으면 & 플레이어가 pickUpKeyCode을 누르면 ->
    // Rigidbody2D 비활성화, playerObject.transform.position+new Vector3(holdOffsetX,0,0)의 위치로 항상 이동
    // 만약 플레이어가 throwKeyCode를 누르면 ->
    // Rigidbody2D 활성화, playerObject.GetComponent<playerStatusController>().direction * new Vector3(throwPower,0,0)의 힘 작용
using UnityEngine;

public class PickableObject : MonoBehaviour
{
    public float radius = 2f;
    public KeyCode pickUpKeyCode = KeyCode.E;
    public KeyCode throwKeyCode = KeyCode.Q;
    public float throwPower = 15f;
    public float holdOffsetX = 1f;
    public LayerMask playerLayer;

    private Rigidbody2D rb;
    private Transform player;
    private bool isHeld = false;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        // 플레이어가 반경 내에 있는지 감지
        Collider2D[] hits = Physics2D.OverlapCircleAll(transform.position, radius, playerLayer);
        foreach (var hit in hits)
        {
            if (hit.CompareTag("Player"))
            {
                player = hit.transform;

                if (Input.GetKeyDown(pickUpKeyCode) && !isHeld)
                {
                    PickUp();
                }
            }
        }

        if (isHeld)
        {
            bool direction = player.GetComponent<PlayerStatusController>().direction;
            // 플레이어가 들고 있는 상태일 때 오브젝트 위치 유지
            transform.position = player.position + new Vector3(holdOffsetX * player.localScale.x * (direction?1:-1), 0, 0);

            if (Input.GetKeyDown(throwKeyCode))
            {
                Throw(direction);
            }
        }
    }

    void PickUp()
    {
        rb.bodyType = RigidbodyType2D.Kinematic;
        rb.linearVelocity = Vector2.zero;
        isHeld = true;
    }

    void Throw(bool direction)
    {
        rb.bodyType = RigidbodyType2D.Dynamic;
        rb.AddForce((direction?1:-1) * new Vector3(throwPower, 0, 0), ForceMode2D.Impulse);
        isHeld = false;
    }

    void OnDrawGizmosSelected()
    {
        // 반경 시각화
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireSphere(transform.position, radius);
    }
}