게임 개발 일지/유니티 엔진 공부

5. 힘을 이용해 물체 움직이기, 물리 충돌

인텔리킴 2024. 4. 19. 16:24

1) 힘을 이용해 물체 이동시키기

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyBall : MonoBehaviour
{
    Rigidbody rigid;    
    void Start()
    {
        rigid = GetComponent<Rigidbody>();
        rigid.velocity = Vector3.right;
    }

    void Update()
    {
        
    }
}

변수이름 = GetComponent<컴포넌트>(); 를 이용해 컴포넌트 안의 내용물을 변수에 적용할 수 있음

변수.velocity를 통해 물체에 속도를 줄수 있음 (속도는 3차원 백터로 주어짐) 

*3D 컴포넌트에 2D 컴포넌트를 넣거나 그 반대를 하면 오류 발생

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyBall : MonoBehaviour
{
    Rigidbody rigid;    
    void Start()
    {
        rigid = GetComponent<Rigidbody>();
    }

    void Update()
    {
        rigid.velocity = new Vector3(2,4,-1);
    }
}

 

위와 같이 Update에 속도를 적용하면 같은 속도가 계속해서 유지됨

 

#되도록이면 Rigidbody 관련 코드는 FixedUpdate()에 적용하길 권장함

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyBall : MonoBehaviour
{
    Rigidbody rigid;    
    void Start()
    {
        rigid = GetComponent<Rigidbody>();
        rigid.AddForce(Vector3.up * 50, ForceMode.Impulse);
    }

    void Update()
    {
        
    }
}

 

변수.AddForce(Vector3, ForceMode.방식)에 의해 물체를 특정 부분으로 힘을 줌

ForceMode는 힘을 주는 방식을 뜻함

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyBall : MonoBehaviour
{
    Rigidbody rigid;    
    void Start()
    {
        rigid = GetComponent<Rigidbody>();

    }

    void Update()
    {
        if(Input.GetButtonDown("Jump"))
        {
            rigid.AddForce(Vector3.up * 50, ForceMode.Impulse);
            Debug.Log(rigid.velocity);
        }
    }
}

위와 같이 간단한 코드로 jump 기능 구현 가능

대신 위와 같은 코드를 작성하면 공중에서 여러번 점프 버튼을 누르는 것이 가능해짐

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyBall : MonoBehaviour
{
    Rigidbody rigid;    
    void Start()
    {
        rigid = GetComponent<Rigidbody>();

    }

    void Update()
    {
        if(Input.GetButtonDown("Jump"))
        {
            rigid.AddForce(Vector3.up * 50, ForceMode.Impulse);
            Debug.Log(rigid.velocity);         
        }

        Vector3 vec = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical"));
        rigid.AddForce(vec, ForceMode.Impulse);
    }
}

 

위와 같이 오브젝트에 힘을 주는 방식으로 물체를 이동시킬 수 있음

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyBall : MonoBehaviour
{
    Rigidbody rigid;    
    void Start()
    {
        rigid = GetComponent<Rigidbody>();

    }

    void Update()
    {
        if(Input.GetButtonDown("Jump"))
        {
            rigid.AddForce(Vector3.up * 50, ForceMode.Impulse);
            Debug.Log(rigid.velocity);         
        }

        Vector3 vec = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical"));
        rigid.AddTorque(vec, ForceMode.Impulse);
    }
}

 

변수.AddTorque(벡터, ForceMode) 를 통해 물체에 회전력을 주어서 이동시키는 것 또한 가능함

 

2. 물리 충돌 이벤트

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OtherBall : MonoBehaviour
{
    MeshRenderer mesh;
    Material mat;
    // Start is called before the first frame update
    void Start()
    {
        mesh = GetComponent<MeshRenderer>();
        mat = mesh.material;
    }

    void OnCollisionEnter(Collision collision)
    {
        mat.color = new Color(0,0,0);
    }
}

MeshRenderer 를 통해 머테리얼을 불러옴

OnCollisionEnter(Collision collision) : 충돌 시작

OnCollisionStay(Collision collision) : 충돌 중

OnCollisionExit(Collision collision) : 충돌 끝났을때

Color <- 기본 색상 클래스 Color32 <- 255개의 색상 클래스

 

하지만 이대로 시작하면 바닥 오브젝트와 맡닿는 순간 색상이 변경됨

 

Collision : 충돌 정보 클래스

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OtherBall : MonoBehaviour
{
    MeshRenderer mesh;
    Material mat;
    // Start is called before the first frame update
    void Start()
    {
        mesh = GetComponent<MeshRenderer>();
        mat = mesh.material;
    }

    void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.name == "My ball")
        {
            mat.color = new Color(0, 0, 0);
        }
    }
}

 

 

위와 같이 if 문을 통해 "My ball" 이라는 이름을 가진 오브젝트에만 충돌이 반응해서 색상이 변경되도록 할 수 있음

 

    void OnCollisionExit(Collision collision)
    {
        if (collision.gameObject.name == "My ball")
        {
            mat.color = new Color(1, 0, 0);
        }
    }

위 코드로 충돌이 끝나는 순간 빨간색으로 색상을 변경할 수도 있음

 

3) 트리거 이벤트

Is Trigger 체크

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyBall : MonoBehaviour
{
    Rigidbody rigid;    
    void Start()
    {
        rigid = GetComponent<Rigidbody>();

    }

    void FixedUpdate()
    {
        if(Input.GetButtonDown("Jump"))
        {
            rigid.AddForce(Vector3.up * 50, ForceMode.Impulse);
            Debug.Log(rigid.velocity);         
        }

        Vector3 vec = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical"));
        rigid.AddForce(vec, ForceMode.Impulse);
    }

    private void OnTriggerStay(Collider other)
    {
        if(other.name == "Cube")
            rigid.AddForce(Vector3.up * 2, ForceMode.Impulse); 
    }
}

위와 같은 코드로 Cube라는 오브젝트에 접촉했을때 y축 방향으로 힘을 가해줄 수 있음

 

OnTriggerEnter(Collider other) { } : 트리거 시작했을때

OnTriggerStay(Collider other) { } : 트리거 발동 도중

OnTriggerExit(Collider other) { } : 트리거 끝났을때

 

요약 : 

* 실제 물리적인 충돌이 발생했을 때의 이벤트

OnCollisionEnter(Collision collision) : 충돌 시작

OnCollisionStay(Collision collision) : 충돌 중

OnCollisionExit(Collision collision) : 충돌 끝났을때

 

* 콜라이더 충돌이 발생했을 때의 이벤트

OnTriggerEnter(Collider other) { } : 트리거 시작했을때

OnTriggerStay(Collider other) { } : 트리거 발동 도중

OnTriggerExit(Collider other) { } : 트리거 끝났을때