유니티:컴포넌트 조작하기: 두 판 사이의 차이

학교의 모든 지식. SMwiki
둘러보기로 이동 검색으로 이동
 
(같은 사용자의 중간 판 15개는 보이지 않습니다)
4번째 줄: 4번째 줄:
코드로 오브젝트의 컴포넌트를 조작해야 할 때가 있다.
코드로 오브젝트의 컴포넌트를 조작해야 할 때가 있다.


===방법===
=방법=
단순하게 생각하면 스크립트의 필드에 컴포넌트를 드래그&드롭으로 컴포넌트를 넣을 수 있다.


코드 내에서 public Rigidbody mine; 형태로 리지드바디 컴포넌트를 가져올 수 있다.
==드래그&드롭으로 컴포넌트 지정하기==
단순하게 생각하면 스크립트의 클래스 변수에 컴포넌트를 드래그&드롭으로 컴포넌트를 넣을 수 있다.
 
===컴포넌트 준비.===
조작할 컴포넌트를 게임 오브젝트 내에 추가한다.
 
===코드 내에서의 준비. 프로퍼티 만들기.===
코드 안에서 공용 변수를 지정해주어 인스펙터 창에서 볼 수 있게 한다.<syntaxhighlight lang="c#">
public class 클래스명 : MonoBehaviour {
    public 받을타입명 받을변수명;
 
}
</syntaxhighlight>예컨대 RigidBody를 조작하고자 한다면 <code>public RigidBody mine</code> 형태로 익스펙터 창에서 리지드바디 컴포넌트를 끌어다 놓을 공간을 보이게 할 수 있다.


리지드바디 컴포넌트 안엔 AddForce 등 힘을 가하는 물리기능을 포함하고 있다.
리지드바디 컴포넌트 안엔 AddForce 등 힘을 가하는 물리기능을 포함하고 있다.


=== 프로퍼티 ===
위처럼 필드를 public으로 할당하면 인스펙터 창에서 편집이 가능하게 보인다.(mine이라는 필드 안에 Rigidbody라는 형태로 보임) 이를 프로퍼티라 부른다.
위처럼 필드를 public으로 할당하면 인스펙터 창에서 편집이 가능하게 보인다.(mine이라는 필드 안에 Rigidbody라는 형태로 보임) 이를 프로퍼티라 부른다.(결국... 아무렇게나 필드를 밖에 보이게 만든 다음에 드래그&드롭이네)
 
필드명을 playerRigidbody라고 지정하면 인스펙터 창에선 Player Rigidbody로 표시된다.
 
public GameObject[] 오브젝트; 형식으로 지정하면 인스펙터 창에 Size가 나오고, 이 사이즈에 따라 넣을 수 있는 칸 수가 늘어난다. 이처럼 필요에 따라 여러 오브젝트를 넣어 관리할 수도 있다.
 
===코드에 적용하기===
 
*이처럼 지정된 공용변수를 필드라 부르는데, 필드에 해당 컴포넌트를 드래그&드롭한다.(해당 컴포넌트를 접어두고 옮기면 편하다.)
*이후, '받을변수명'을 조작함으로써 컴포넌트를 다룰 수 있다.
*게임 오브젝트 뿐 아니라 UI요소인 Text 등도 조작이 가능하다.
 
==코드 내에서 오브젝트 내부 컴포넌트 가져오기==
드래그&드롭은 직관적이고 편하지만, 조작에 실수가 있을 수도 있고, 코드로 해결하고 싶은 경우도 있다. 그런 경우, 다음과 같이 해당 컴포넌트를 가져올 수 있다.<syntaxhighlight lang="c#">
public class 클래스명 : MonoBehaviour {
    private 받을타입명 받을변수명;
   
    void 메서드명() {
    받을변수명 = GetComponent<컴포넌트명>();
    }
}
</syntaxhighlight>가져오고 싶은 것이 RigidBody라면 다음과 같이 작성한다.<syntaxhighlight lang="c#">
public class Move : MonoBehaviour {
    private Rigidbody playerRigidbody;
   
    void Start() {
    playerRigidbody = GetComponent<Rigidbody>();
    }
}
</syntaxhighlight>컴포넌트를 가져올 때, 해당 컴포넌트가 없다면 null을 반환한다.
 
컴포넌트 하위의 필드는 . 문법으로 접근할 수 있다.
 
==외부 오브젝트의 컴포넌트 가져오기==
외부 오브젝트의 속성을 가져와 대응하는 게 필요할 때가 있다.
 
다음과 같이 작성하면 해당 컴포넌트를 가진 오브젝트가 target에 매칭된다.<syntaxhighlight lang="c#">
void Start() {
    target = FindObjectOfType<찾을 오브젝트 내 컴포넌트>();
    position = FindObjectOfType<찾을 오브젝트 내 컴포넌트>().transform;  // .문법으로 하위속성에 접근 가능하다.
    example = FindObjectOfType<찾을 오브젝트 내 컴포넌트>().GetComponent<Rigidbody>();  // 이게 정석.
</syntaxhighlight>[컴포넌트가 아니라, 게임오브젝트 이름으로 찾아올 수는 없는 걸까;;?]
 
*컴포넌트가 아닌, 오브젝트를 매칭한다는 것에 유의해야 한다.
*이 메서드는 처리비용이 크기 때문에 start() 메서드처럼 초기에 1,2회 실행되는 메서드 안에서 사용해야 한다. Update()같은 곳에서 사용하면 처리가 크게 늦어질 수 있다.
*FindObjectOfType은 찾으면 검색을 멈추고, FindObjectsOfType은 해당 타입의 오브젝트를 모두 찾아낸다.
 
=외부 메서드에 접근하기=
<syntaxhighlight lang="c#">
void Start() {
    타입 변수명 = FindObjectOfType<클래스이름>();
    변수명.목표메서드();
</syntaxhighlight>오브젝트.메서드명(); 형태로 해당 메서드를 실행시킬 수 있는데, 가장 간단한 건 정적변수처리일 듯하다.
=기타=
 
==transform==
트렌스폼 컴포넌트는 편의상 GetComponent를 사용할 필요 없이, <code>transform</code> 변수로 바로 불러올 수 있게 되어있다.
 
transform은 재미난 속성들을 갖고 있다.
{| class="wikitable"
!함수
!기능
|-
|transform.position(벡터3);
|오브젝트의 위치를 지정할 수 있다.(절대좌표의 위치를 조정한다.)
|-
|transform.Translate(벡터3);
|특정 벡터값만큼 위치값을 이동시키는 메서드가 준비되어 있다. 보통 transform.Translate(벡터3 * Time.deltaTime); 형식으로 사용한다.
이 메서드에 의한 이동은 전역공간이 아니라 지역공간을 기준으로 움직인다는 데에 유의해야 한다. 전역공간에서의 이동으로 고치고 싶다면 transform.Translate(벡터3, Space.World); 처럼 두번째 인자를 준다.
|-
|transform.Rotation(Quaternion.Euler(벡터3));
|오브젝트의 회전값을 지정한다.(절대좌표에 대하여)
|-
|transform.rotation(쿼터니온);
|회전값을 넣을 땐 벡터3이 아닌, 쿼터니온(사원수)을 사용한다. 오일러 각을 사용할 때 발생하는 짐벌락 때문이다. 쿼터니온은 유니티에서 직접 생성할 수 없게 막아두었고, 이를 위한 메서드가 준비되어 있다.<syntaxhighlight lang="c#">
Quaternion rotation = Quaternion.Euler((0, 1, 2));  // 오일러각을 쿼터니온으로 만들고, 한 번에 회전시킨다.
Vector 3 eulerAngle = rotation.eulerAngles;  //  사원수를 오일러각으로 반환한다.
</syntaxhighlight>회전은 기본적으로 행렬을 사용하기 때문에 회전에 회전을 더하려면 +가 아니라, *를 사용한다.
|-
|transform.Rotate(3벡터);
|보통 rotationSpeed 값을 지정하여 Update함수에 transform.Rotate(0f, rotationSpeed * Time.deltaTime, 0f); 처럼 두면 프레임당 이동속도를 볼 수 있다.(혹은 벡터 자체에 Time.daltaTime을 걸든가.)
 
*델타타임에 의한 회전은 연산 순서에 영향을 미치지 않으므로 인수로 벡터3을 사용한다.
*Translate와 동일하게 기본적으로 지역공간을 기준으로 회전시킨다. 마찬가지로 2번째 인수로 Space.World를 넣어주면 된다.
|-
|transform.LookAt(트렌스폼);
|다른 객체의 트렌스폼을 받아 해당 객체를 바라보게 한다.
|-
|transform.localPosition = 값
transform.localRotation = Quaternion.Euler(벡터3)
|어떤 오브젝트가 자식 오브젝트일때, 지역좌표계를 조작해야 하는 상황이 있다. 그 좌표계는 local 속성을 만져 조작할 수 있다.
|}
 
===방향===
오브젝트의 방향을 손쉽게 알 수 있도록 다음의 변수들을 제공한다.
 
일반적으로 캐릭터의 이동을 구현할 땐 절대공간을 기준으로 하지 않고 카메라의 위치에 따라 달리 한다. 이를 구현할 때 이 변수를 사용한다.
{| class="wikitable"
!변수
!기능
|-
|transform.forward
|오브젝트의 앞을 가리키는 방향벡터
|-
|transform.right
|오브젝트의 오른쪽을 가리키는 방향벡터
|-
|transform.up
|오브젝트의 위를 가리키는 방향벡터
|}
나머지 방향들은 위 벡터에 '-1'을 곱해 사용한다.
 
==게임 오브젝트에 접근하기==
코드 내에서 gameObject라는 변수로 코드를 담고 있는 게임오브젝트에 접근이 가능하다.


이후 리지드바디 컴포넌트를 스크립트의 필드에 드래그&드롭.
===게임 오브젝트 활성화, 비활성화===
다음과 같이 게임 오브젝트가 기본적으로 갖고 있는 메서드를 이용해 오브젝트 활성/비활성이 가능하다.<syntaxhighlight lang="c#">
public void End() {  // public으로 해주면 외부에서 이 함수에 접근할 수 있다.
    gameObject.SetActive(false);  // gameObject는 이 코드를 담고 있는 오브젝트를 의미한다.
    }
</syntaxhighlight>Instantiate()나 Destroy()처럼 오브젝트를 실시간으로 생성하거나 파괴하는 작업은 메모리를 많이 요구한다. 이를 대신하여 처음에 오브젝트를 불러오고 활성, 비활성을 반복하는 방식이 일반적이다.

2021년 8월 14일 (토) 13:47 기준 최신판

틀:유니티

  1. 유니티:개요
  2. 유니티:기본 조작
    1. 유니티:에셋스토어
  3. 유니티:카메라
  4. 유니티:오브젝트
    1. 유니티:데이터 입력받기
    2. 유니티:오브젝트 이동(오브젝트 조작)
    3. 유니티:힘으로 오브젝트 이동
    4. 유니티:충돌 이벤트
    5. 유니티:오브젝트 작성 tip
    6. 유니티:프리팹
  5. 유니티:코딩기초
    1. 유니티:C sharp 코딩 편의기능
    2. 유니티:MonoBehaviour
    3. 유니티:이벤트 메서드
    4. 유니티:컴포넌트 조작하기
  6. 유니티:UI
  7. 유니티:게임 내 화면
  8. 유니티:플레이어
    1. 유니티:모델
    2. 유니티:캐릭터 이동
    3. 유니티:애니메이션
    4. 유니티:주인공 시점
  9. 유니티:맵
    1. 유니티:투명한 벽 만들기
    2. 유니티:내비게이션
  10. 유니티:씬
  11. 유니티:몬스터
  12. 유니티:아이템
  13. 유니티:음향
    1. 유니티:배경음
    2. 유니티:효과음
  14. 유니티:빌드
  15. 유니티:VR
    1. 유니티:VR:UI
    2. 유니티:VR:VR로 변환
  16. 유니티:팁

개요[편집 | 원본 편집]

코드로 오브젝트의 컴포넌트를 조작해야 할 때가 있다.

방법[편집 | 원본 편집]

드래그&드롭으로 컴포넌트 지정하기[편집 | 원본 편집]

단순하게 생각하면 스크립트의 클래스 변수에 컴포넌트를 드래그&드롭으로 컴포넌트를 넣을 수 있다.

컴포넌트 준비.[편집 | 원본 편집]

조작할 컴포넌트를 게임 오브젝트 내에 추가한다.

코드 내에서의 준비. 프로퍼티 만들기.[편집 | 원본 편집]

코드 안에서 공용 변수를 지정해주어 인스펙터 창에서 볼 수 있게 한다.

public class 클래스명 : MonoBehaviour {
    public 받을타입명 받을변수명;

}

예컨대 RigidBody를 조작하고자 한다면 public RigidBody mine 형태로 익스펙터 창에서 리지드바디 컴포넌트를 끌어다 놓을 공간을 보이게 할 수 있다.

리지드바디 컴포넌트 안엔 AddForce 등 힘을 가하는 물리기능을 포함하고 있다.

위처럼 필드를 public으로 할당하면 인스펙터 창에서 편집이 가능하게 보인다.(mine이라는 필드 안에 Rigidbody라는 형태로 보임) 이를 프로퍼티라 부른다.

필드명을 playerRigidbody라고 지정하면 인스펙터 창에선 Player Rigidbody로 표시된다.

public GameObject[] 오브젝트; 형식으로 지정하면 인스펙터 창에 Size가 나오고, 이 사이즈에 따라 넣을 수 있는 칸 수가 늘어난다. 이처럼 필요에 따라 여러 오브젝트를 넣어 관리할 수도 있다.

코드에 적용하기[편집 | 원본 편집]

  • 이처럼 지정된 공용변수를 필드라 부르는데, 필드에 해당 컴포넌트를 드래그&드롭한다.(해당 컴포넌트를 접어두고 옮기면 편하다.)
  • 이후, '받을변수명'을 조작함으로써 컴포넌트를 다룰 수 있다.
  • 게임 오브젝트 뿐 아니라 UI요소인 Text 등도 조작이 가능하다.

코드 내에서 오브젝트 내부 컴포넌트 가져오기[편집 | 원본 편집]

드래그&드롭은 직관적이고 편하지만, 조작에 실수가 있을 수도 있고, 코드로 해결하고 싶은 경우도 있다. 그런 경우, 다음과 같이 해당 컴포넌트를 가져올 수 있다.

public class 클래스명 : MonoBehaviour {
    private 받을타입명 받을변수명;
    
    void 메서드명() {
    받을변수명 = GetComponent<컴포넌트명>();
    }
}

가져오고 싶은 것이 RigidBody라면 다음과 같이 작성한다.

public class Move : MonoBehaviour {
    private Rigidbody playerRigidbody;
    
    void Start() {
    playerRigidbody = GetComponent<Rigidbody>();
    }
}

컴포넌트를 가져올 때, 해당 컴포넌트가 없다면 null을 반환한다.

컴포넌트 하위의 필드는 . 문법으로 접근할 수 있다.

외부 오브젝트의 컴포넌트 가져오기[편집 | 원본 편집]

외부 오브젝트의 속성을 가져와 대응하는 게 필요할 때가 있다.

다음과 같이 작성하면 해당 컴포넌트를 가진 오브젝트가 target에 매칭된다.

void Start() {
    target = FindObjectOfType<찾을 오브젝트  컴포넌트>();
    position = FindObjectOfType<찾을 오브젝트  컴포넌트>().transform;  // .문법으로 하위속성에 접근 가능하다.
    example = FindObjectOfType<찾을 오브젝트  컴포넌트>().GetComponent<Rigidbody>();  // 이게 정석.

[컴포넌트가 아니라, 게임오브젝트 이름으로 찾아올 수는 없는 걸까;;?]

  • 컴포넌트가 아닌, 오브젝트를 매칭한다는 것에 유의해야 한다.
  • 이 메서드는 처리비용이 크기 때문에 start() 메서드처럼 초기에 1,2회 실행되는 메서드 안에서 사용해야 한다. Update()같은 곳에서 사용하면 처리가 크게 늦어질 수 있다.
  • FindObjectOfType은 찾으면 검색을 멈추고, FindObjectsOfType은 해당 타입의 오브젝트를 모두 찾아낸다.

외부 메서드에 접근하기[편집 | 원본 편집]

void Start() {
    타입 변수명 = FindObjectOfType<클래스이름>();
    변수명.목표메서드();

오브젝트.메서드명(); 형태로 해당 메서드를 실행시킬 수 있는데, 가장 간단한 건 정적변수처리일 듯하다.

기타[편집 | 원본 편집]

transform[편집 | 원본 편집]

트렌스폼 컴포넌트는 편의상 GetComponent를 사용할 필요 없이, transform 변수로 바로 불러올 수 있게 되어있다.

transform은 재미난 속성들을 갖고 있다.

함수 기능
transform.position(벡터3); 오브젝트의 위치를 지정할 수 있다.(절대좌표의 위치를 조정한다.)
transform.Translate(벡터3); 특정 벡터값만큼 위치값을 이동시키는 메서드가 준비되어 있다. 보통 transform.Translate(벡터3 * Time.deltaTime); 형식으로 사용한다.

이 메서드에 의한 이동은 전역공간이 아니라 지역공간을 기준으로 움직인다는 데에 유의해야 한다. 전역공간에서의 이동으로 고치고 싶다면 transform.Translate(벡터3, Space.World); 처럼 두번째 인자를 준다.

transform.Rotation(Quaternion.Euler(벡터3)); 오브젝트의 회전값을 지정한다.(절대좌표에 대하여)
transform.rotation(쿼터니온); 회전값을 넣을 땐 벡터3이 아닌, 쿼터니온(사원수)을 사용한다. 오일러 각을 사용할 때 발생하는 짐벌락 때문이다. 쿼터니온은 유니티에서 직접 생성할 수 없게 막아두었고, 이를 위한 메서드가 준비되어 있다.
Quaternion rotation = Quaternion.Euler((0, 1, 2));  // 오일러각을 쿼터니온으로 만들고, 한 번에 회전시킨다.
Vector 3 eulerAngle = rotation.eulerAngles;  //  사원수를 오일러각으로 반환한다.
회전은 기본적으로 행렬을 사용하기 때문에 회전에 회전을 더하려면 +가 아니라, *를 사용한다.
transform.Rotate(3벡터); 보통 rotationSpeed 값을 지정하여 Update함수에 transform.Rotate(0f, rotationSpeed * Time.deltaTime, 0f); 처럼 두면 프레임당 이동속도를 볼 수 있다.(혹은 벡터 자체에 Time.daltaTime을 걸든가.)
  • 델타타임에 의한 회전은 연산 순서에 영향을 미치지 않으므로 인수로 벡터3을 사용한다.
  • Translate와 동일하게 기본적으로 지역공간을 기준으로 회전시킨다. 마찬가지로 2번째 인수로 Space.World를 넣어주면 된다.
transform.LookAt(트렌스폼); 다른 객체의 트렌스폼을 받아 해당 객체를 바라보게 한다.
transform.localPosition = 값

transform.localRotation = Quaternion.Euler(벡터3)

어떤 오브젝트가 자식 오브젝트일때, 지역좌표계를 조작해야 하는 상황이 있다. 그 좌표계는 local 속성을 만져 조작할 수 있다.

방향[편집 | 원본 편집]

오브젝트의 방향을 손쉽게 알 수 있도록 다음의 변수들을 제공한다.

일반적으로 캐릭터의 이동을 구현할 땐 절대공간을 기준으로 하지 않고 카메라의 위치에 따라 달리 한다. 이를 구현할 때 이 변수를 사용한다.

변수 기능
transform.forward 오브젝트의 앞을 가리키는 방향벡터
transform.right 오브젝트의 오른쪽을 가리키는 방향벡터
transform.up 오브젝트의 위를 가리키는 방향벡터

나머지 방향들은 위 벡터에 '-1'을 곱해 사용한다.

게임 오브젝트에 접근하기[편집 | 원본 편집]

코드 내에서 gameObject라는 변수로 코드를 담고 있는 게임오브젝트에 접근이 가능하다.

게임 오브젝트 활성화, 비활성화[편집 | 원본 편집]

다음과 같이 게임 오브젝트가 기본적으로 갖고 있는 메서드를 이용해 오브젝트 활성/비활성이 가능하다.

public void End() {  // public으로 해주면 외부에서 이 함수에 접근할 수 있다.
    gameObject.SetActive(false);  // gameObject는 이 코드를 담고 있는 오브젝트를 의미한다.
    }

Instantiate()나 Destroy()처럼 오브젝트를 실시간으로 생성하거나 파괴하는 작업은 메모리를 많이 요구한다. 이를 대신하여 처음에 오브젝트를 불러오고 활성, 비활성을 반복하는 방식이 일반적이다.