본문 바로가기

GAME

[Unity]오브젝트 컨트롤

728x90

<목표>

- 실제와 같은 물체 만들기 ( 골드 메탈 - 유니티 기초 B9 )

- 오브젝트에 힘을 주기 ( 골드 메탈 - 유니티 기초 B10 )

- 오브젝트 물리 충돌 이벤트 ( 골드 메탈 - 유니티 기초 B11 )

 

기본 오브젝트가 아닌 추가 설정을 통해

실제와 같은 물체 만들기

 

오브젝트에는 기본적으로 4개의 컴포넌트가 존재 (Inspector상에서 확인 가능)

Transform/Mesh Renderer(빛나는 물체를 만들 수 있음?)/Collider/RigidBody(추가해야 함)

 

물체의 필수요소

Mesh/Material/Collider/RigidBody 

 

1. 중력 적용하기 

오브젝트에 Add component

RigidBody를 추가하면 중력의 영향을 받게 됨 

 

2. 충돌 영역 정하기

연두색 선으로 표시되며, 실제 오브젝트가 아닌 이 선에 의해 충돌 영역이 정의된다

Shpere Collider : 제거

물리효과를 받기 위한 컴포넌트 , 다른 오브젝트와 충돌하지 않고 통과하거나 다른 오브젝트가 존재하지 않는 듯이 움직이게 됨

Radius : 크기를 조절 가능한데 크게 하면, 오브젝트 자체와는 직접 충돌하지 않게 되고, 작게 하면 오브젝트와 겹치게도 가능

 

 

3.RigidBody설정

Mass : 무게 / 수치가 높을수록 충돌이 무거워짐 but 중력의 영향을 더 많이 받아 빨리 떨어지거나 하지는 않음 

Use Grabity: 중력의 영향을 받을지 안 받을지 결정하는 것 

Is Kinematic : 외부의 물리효과(충돌 후 밀려나는 현상 등등)를 무시함 (스크립트를 통한 이동만 가능해진다)

*움직이는 장애물 등 함정을 만들 때 유용

 

4. 재질 만들기

지금 오브젝트의 겉표면? 디자인적 / 외부적 / 시각적 부분

 

Default - Material : 오브젝트의 표면 재질을 결정하는 컴포넌트인데 바꾸고 싶으면 새로 제작해서 바꾸어야 함

Project에 커서를 두고 오른쪽 -> Create -> Material

Insepctor창에서 여러 가지를 조절 가능

Albedo : - 색

               - 무늬 : 자신만의 그림을 넣을 수 있음 / project창에 자신의 그림(Texture)을 불러온 후(드래그로 가능) Albedo옆에 네모 박스에 드래그

Emission.  텍스트 발광(밝기) 조절 //밝아진다고 오브젝트가 빛나는 것은 아니고 재질이 밝아지는 것임

            - Tiling : 텍스처 반복 타일 개수 X(열) * Y(행) 바둑판 식으로 표현됨 ( 소수점도 가능하나 그림이 잘려서 들어감 )

           - Offset 

metallic : 금속 재질의 느낌을 표현하고 싶을 때

               - Smoothness : 빛 반사 수치 (0 : 무광)

만든 Material을 재질을 적용할 오브젝트에 드래그하면 됨(스크립트를 적용할 때와 같음)

 

 

 

5. 물리 재질 만들기 

탄성과 마찰을 다루는 물리적 재질

더보기

ex) 볼링공 : 탄성이 없고 무거움 

탁구공 : 가볍고 플라스틱 느낌으로 튀어 오름

고무공 : 탄성이 있고 단단함

외부적 모습이 아닌 내부/물리/재료? 적 성질을 설정

 

Project에 커서를 두고 오른쪽 -> Create -> Physic Material

마찬가지로 오브젝트로 드래그해서 적용하는데 -> collider내에 있는 Material항목에서 적용 모습을 볼 수 있음 

아까 Collider이 물리(충돌) 등을 관할한다고 했는데, 이를 보면 Physic Material이 물리 재질을 결정하는 것을 다시 한번 알 수 있음

 

탄성력 조절

Bounciness :  탄성력 / 높을수록 많이 튀어 오름(최대 1) 

Bounceiness Combine : 튕긴 후 다음번 튕길 때의 탄성을 계산하는 방식

                                     Average(중간값)/Minimum/Multiply/Maximum(점점 더 많이 튀어 오름)

 

 

마찰력 조절

Dynamic Friction : 움직임 마찰력

Static Friction : 전기 마찰력

->마찰력을 높게 주면 잘 밀려나지 않음 
보통 현실 세계에선 전기 마찰력이 더 크다고 하나 코딩에선 사용자 마음대로...

Friction Combine : 다음 마찰력을 계산하는 방식

Friction Combine 최대 / Bounceiness Combine은 최소로 하는 것이 극적인? 상황표현에 추천하는 조합 

 

 

힘을 이용하여 물체를 움직이기

C#스크립트와 Rigidbody를 주로 사용합니다

위의 것들을 활용해서 초기 설정을 한번 해보았습니다 

티스토리에는 사진에 연필처럼 낙서할 수 있는 부분이 없나요? 어딘지 표시를 할 수 없으니 설명하기 어렵군요

 

 

오브젝트의 이동 표현

Rigidbody는 물리현상을 표현할 수 있는 컴포넌트라고 했습니다.

전에 물체를 이동시킬 때는 Transform 컴포넌트를 스크립트 상의 변수로 만들고, 이를 함수를 통해 스크립트상에서 코드로

물체의 이동을 확인해보았습니다.

 

그렇다면 이번에는 물리현상을 표현하려고 하니, Rigidbody 변수를 만들어 이를 이용해 물리현상을 표현해야겠네요

    Rigidbody rigid;  //변수 생성 
	rigid = GetComponent<Rigidbody>(); //초기화

 

 

 

아래나 오는 함수들은 모두 Rigidbody의 변수인 rigid에 적용하는 함수입니다. (rigid. 함수명()으로 사용 가능하다는 의미)

 

1. 오브젝트에 속력 주기

속력은 Vector에 해당하는 velocity를 사용해서 표현합니다 

    Rigidbody rigid;  // rigidbody변수를 만듬

    void Start()
    {
        rigid = GetComponent<Rigidbody>(); //rigidbody 변수를 초기화 

        //속력변경 velocity변수 사용 
        rigid.velocity = Vector3.right; //오른쪽 방향으로 속력을 정함

        
    }

이제부터 위에 쓸데없는 코드는 다 빼고 핵심 코드만 올리도록 하겠습니다.

 

Vector는 꼭 right만 있는 것은 아니고 사용자가 마음대로 좌표를 지정해 줄 수도 있습니다.

    Rigidbody rigid; 

    void Start()
    {
        rigid = GetComponent<Rigidbody>(); //초기화 


        //속력변경 velocity변수 사용 
        rigid.velocity = new Vector3(2,4,-1); //(2,4,-1)방향으로 속력을 정함 

        
    }

start()는 1회만 실행되는 함수이므로, 구가 2,4,-1방향으로 1회 튀어 나간 후 굴러가는데

만약 update()처럼 계속 실행되는 함수에서 실행한다면 구는 (2,4,-1)로 무한대로 이동할 것입니다.

 

여기서 주의할 점은 물리현상을 관할하는 Update함수는 FixedUpdate() 함수라는 것입니다.

Rigidbody와 관련된 것은 Update가 아닌 FixedUpdate() 함수 안에서 실행시켜야만 더 안정된 물리현상을 관찰할 수 있습니다.

 

2. 오브젝트에 힘을 가하기 

위에서는 물체 자체에 속력을 주어보았습니다. 

이제 물체 자체에 속력이 아닌, 물체에 힘을 가하여 움직이는 모습을 살펴보도록 합시다

AddForce(Vector3 vec * int force , ForceMode. 모드 4가지) : 힘의 방향으로 계속 속도(velocity) 증가  

매개변수 설명
1) 매개변수인 vec : vec의 방향(vec)과 크기(force)로 힘을줌
2) ForceMode : 힘을 주는 방식(Acceleration/Force/Impulse/VelocityChange) 

 

캐릭터 점프 모션에 가장 많이 활용되는 코드로 예를 들어봅시다.

Rigidbody rigid; 

    // Start is called before the first frame update
    void Start()
    {
        rigid = GetComponent<Rigidbody>(); //초기화 
        rigid.AddForce(Vector3.up*5, ForceMode.Impulse); // 윗쪽 방향, 5의 크기로 
       
    }

실행해보시면 구가 점프하는 모습을 볼 수 있습니다. 

*주의 : Impluse는 오브젝트의 Mass(무게)가 클수록 더 큰 force값이 필요합니다 , Mass가 작을수록 더 높게 뜁니다

 

이번엔 정말 점프를 구현해보도록 합시다 

스페이스키를 눌렀을 때, 점프를 하는 코드를 구현해보면, 

당연히 FixedUpdate() 함수 내에 구현해야 합니다.

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

여기서 사용된 up, back 등등은 많이 쓰는 벡터를 단위 벡터로 정리해둔 대표적 벡터입니다.

 

스페이스 바를 누를 때마다 오브젝트가 점프하는 모습을 볼 수 있습니다.

다만 무한대로 점프가 가능하겠군요 힘의 방향으로 velocity가 증가하는 함수이므로 누를 때마다 증가하니 당연한 것입니다.

 

더 응용해서 움직임까지 구현해봅시다

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

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

오른쪽 /왼쪽 : Horizontal = x 값 변경

위/아래 : Vertical = z값 변경

스페이스 바 : Jump = y값 변경 

실행해보면 공을 이 조작키로 움직일 수 있습니다. 

Rigidbody만 사용하는 것보다 훨씬 자연스럽습니다.

 

 

3. 회전력 주기

회전력은 물리에서 Torque라고 많이 불리는 힘인데.. 뭐 물리 시간이 아니니 넘어가도록 합시다

AddTorque(Vector3); : 제공한 벡터를 축으로 삼아 회전하기 때문에 이동 방향에 주의

예를 들어 제공한 벡터가 up일 경우 (0,1,0)을 축으로 삼아 회전하니 제자리 spin모션이 실행될 것
down이면 up과는 반대방향으로 spin 할 것이고,
back이면 (0,0,1)이므로 회전하면 오른쪽 방향으로 이동할 것 

이동방향이 헷갈릴 수 있을 것 같네요

 

 

오브젝트 충돌 이벤트

충돌 이벤트에는 무엇이 있을까요? 

보통 게임에서 적의 공격을 맞으면 캐릭터가 깜빡이거나 붉은색이 되었다 돌아오거나 맞았다는 효과음이 나왔거나

카트라이더에서 차량끼리 서로 부딪히면 어떤 일이 일어나나요? 제대로 기억이 안 나네요

이런 것들이 모두 충돌 이벤트입니다

 

충돌 이벤트를 보여주기 위하여 위의 상태에서 조금 더 오브젝트를 추가해보도록 합시다

Other_Ball을 한 3개 정도 추가해주고,

y좌표는 메인 공과 동일하게 해 주고 x, y 축은 마우스로 대충 적절하게 조절해줬습니다

물리 충돌 이벤트를 해야 하니 Rigidbody를 꼭 추가해줘 야해요

저는 대충 이 정도로 했습니다

이제 Other_Ball들에 적용시킬 스크립트를 만들고 3개 모두에게 적용시켜주었습니다.

 

충돌 시 어떤 일이 일어나게 만들려면, 일단 충돌을 감지하는 함수가 있어야 합니다

이미 그런 함수를 유니티에서 제공합니다 

private void OnCollisionEnter(Collision collision){ //발생시킬 이벤트 } : 물리적 충돌이 시작할 때 호출되는 함수

private void OnCollisionExit(Collision collision){ //발생시킬 이벤트 } : 물리적 충돌이 끝날 때 호출되는 함수

private void OnCollisionStay(Collision collision){ //발생시킬 이벤트 } : 물리적 충돌이 유지될 때 호출되는 함수

여기서 매개변수로 받는 Collision collision은 해당 스크립트를 가진 오브젝트가

다른 무엇과 충돌했는지를 받아오는 매개변수입니다. 

 

 

 

충돌 시 색 변경

먼저 충돌 시 색을 바꿔보도록 해봅시다 

제일 메인 볼인 빨간색 공을 움직여(위에서 이미 코딩을 완료한 것을 사용)

다른 파란색 공들과 부딪혔을 때, 파란 공이 흰색 공이 되도록 해봅시다

오브젝트의 색을 관리하는 컴포넌트는 Mesh Renderer의 Material 부분이었습니다 

Material을 열어보면 개개인이 생성해서 적용시켜준 Material이 여기 적용된 것을 볼 수도 있죠

그렇다면 이제 눈치껏

Mesh Renderer과 Material 변수가 필요하겠군..이라고 감이 오실 겁니다

둘을 생성해 초기화해줍시다

    MeshRenderer mesh;
    Material mat;

	mesh = GetComponent<MeshRenderer>();
	mat = mesh.material;

 

이제 위에서 나온 함수를 이용해 부딪히면 색을 흰색으로 변경합시다

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;
    }


//충돌이 발생했을 때 실행되는 함수
    private void OnCollisionEnter(Collision collision){
        if(collision.gameObject.name == "Main_Ball"){
            mat.color = new Color(1,1,1);
        }
    }
}

위에서 설명했듯 Collsion 은 어떤 오브젝트와 충돌했는지를 알아오는 매개변수입니다.

if문을 넣어주지 않는다면, 우리의 Other ball들은 이미 Floor과 충돌해있는 상태이기 때문에 실행하자마자 흰색으로 변경될 것입니다. 

우리는 이것을 원하는 게 아니라 우리의 MainBall과 충돌했을 때만 흰색으로 변경되는 것을 원하기 때문에 저렇게 해주면 됩니다

 

이렇게 충돌한 공은 흰색이 되는 것을 볼 수 있습니다. (캡처가 너무 어려워서 상태가 안 좋네...

 

에어본 효과 (Is Trigger)

이런 효과는 뭐라고 해야 하나.. 가끔 맵에 왕 선풍기가 있고 그 영역에 올라타면 위로 떠오르는? 그런 효과를 구현해보도록 합시다

일단 영역을 가시적으로 보이게 하기 위해 큐브를 사용했습니다.

더보기

<참고적으로 반투명 큐브를 만드는 법>

Material에서

Rendering Mode를 Transparent로 해주고

색에서 A부분을 조절해주시면 됩니다 

저렇게 배치하는 법은 유니티 기초 페이지를 보고 오시면 됩니다

 

Cube Object의 Box Collider에 있는 Is Trigger에 체크해줍시다

 

OnTrigger도 마찬가지로 3가지 상태가 전부 다 존재합니다

트리거는 뭐라고 설명할까요.. 둘이 겹치면? 충돌은 아니고 오브젝트 두 개가 같은 공간상에 있다?(어찌 보면 충돌이라고 할 수도 있지만.. 조금 부적절한 면이 있네요) 정도로 생각하시면 될 것 같습니다.

Collision이 아니라 Collider인 모습을 볼 수 있습니다. 바로 위와 같은 이유 때문입니다.

또한 이 때문이 아니더라도 Collider컴포넌트에서 is trigger를 체크해준 것을 보아 

Collider 변수로 조절하는 것이 필요해 보이네요

private void OnTriggerEnter(Collider other){ //발생시킬 이벤트 } : 시작할 때 호출되는 함수


private void OnTriggerExit(Collider other){ //발생시킬 이벤트 } : 끝날 때 호출되는 함수


private void OnTriggerStay(Collider other){ //발생시킬 이벤트 } : 유지될 때 호출되는 함수

 

저희는 이제 공간상에 있는 동안 에어본 효과를 주어야 하므로 Stay를 이용하면 적당할 것 같네요

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

public class MyBall : MonoBehaviour
{

    Rigidbody rigid; 
    


    // Start is called before the first frame update
    void Start()
    {
        rigid = GetComponent<Rigidbody>(); //초기화 

    }

    // Update is called once per frame
    void FixedUpdate()
    {   

        //2. 힘을 가하기 적용해서 물체 게임모드 

		
        float horizon = Input.GetAxisRaw("Horizontal")*0.5f;
        float vertic = Input.GetAxisRaw("Vertical")*0.5f;

		//점프
        if(Input.GetButtonDown("Jump")){
        rigid.AddForce(Vector3.up*5, ForceMode.Impulse);
        }

		//이동
        Vector3 vec = new Vector3(horizon,0,vertic);
        rigid.AddForce(vec, ForceMode.Impulse);
        
        
    }

    private void OnTriggerStay(Collider other) {

		//큐브 내에 들어왔을 때 위로 떠오르는 효과
        if(other.name == "Cube"){
            rigid.AddForce(Vector3.up*2,ForceMode.Impulse);
        }
    }
}

 

확인해보려면 카메라를 조정해주시면 더 편할 거예요

카메라를 이 정도로 조정해주었습니다.

떠오르는 모습은 캡처가 어려워 직접 해보시길 추천드립니다

 

<참고자료>

youtu.be/kYmYCMAiOUk

youtu.be/h_MA36TGFsc

youtu.be/salZ7t98xi8

 

728x90

'GAME' 카테고리의 다른 글

[Unity]기초 3D게임 만들기-1  (4) 2020.07.30
[Unity]UI Setting  (0) 2020.07.17
[Unity]입력처리와 오브젝트 이동  (0) 2020.07.15
[Unity]C#기초와 유니티LIFE CYCLE  (0) 2020.07.10
[Unity]유니티 기초  (0) 2020.07.10