[Unity] position, localPosition

Unity 3D 오브젝트의 이동에 대해 정리를 해보려고 합니다.

추가적인 내용을 알아보려면
Transform.position, Transform.localPosition 참고하시면 됩니다.

말하기에 앞서 예시를 들기 위해 3D 오브젝트인 Cube, Plane을 생성해보겠습니다.

3D 오브젝트의 위치 값은 Transform의 position에 Vector3 ( x, y, z )의 형태로 담겨 있습니다.

위의 Transform 정보는 Cube Object의 데이터입니다.

현재 Position은 (0, 1, 0)의 값을 가지고 있습니다.

해당 오브젝트를 우측으로 이동시켜보겠습니다.

오브젝트를 우측으로 이동시키니 Position의 x값의 변화가 있습니다.

오브젝트의 위치 이동을 위해서는 Position 값의 변화가 필요하다는 것을 알 수 있습니다.


3d 오브젝트 방향 벡터

3D 오브젝트의 간편한 이동을 위해 Unity에는 방향을 나타내는 전역 벡터가 정의되어 있습니다.

방향 벡터

Direction Vector3
Vector3.forward (0, 0, 1)
Vector3.back (0, 0, -1)
Vector3.up (0, 1, 0)
Vector3.down (0, -1, 0)
Vector3.right (1, 0, 0)
Vector3.left (-1, 0, 0)
Vector3.zero (0, 0, 0)
Vector3.one (1, 1, 1)

Position

Position 값을 직접적으로 수정하여 Cube를 이동시키겠습니다.

아래의 코드가 작성된 스크립트를 Cube 오브젝트의 컴포넌트로 추가하였습니다.

1
2
3
4
5
6
7
//오브젝트의 이동 속도
private float _moveSpeed = 5f;

void Update(){
//위로 이동
transform.position += Time.deltaTime * _moveSpeed * Vector3.up;
}

[결과]

매 프레임마다 프레임이 흐른 시간과 moveSpeed 를 이용하여 Position의 y값을 증가시켰습니다.

localPosition

위의 position은 localposition으로도 표현할 수 있는데요.

position과 localPosition은 어떤 차이가 있는걸까요?

position은 오브젝트의 위치 좌표를 월드 좌표 기준으로 가지고 있습니다.

localPosition은 오브젝트의 위치 좌표를 로컬 좌표 기준으로 가지고 있습니다.

월드 좌표와 로컬 좌표의 차이는 무엇일까요?

월드 좌표란 절대적인 좌표를 말합니다.

절대적인 시점에서 바라본 오브젝트의 위치이므로
어디에서 오브젝트 위치를 불러와도 항상 같은 값을 가지게 됩니다.

로컬 좌표는 상대적인 좌표를 말합니다.

만약 Cube 오브젝트가 또 다른 오브젝트의 자식 오브젝트로 존재한다면 부모 오브젝트가 이동할 경우 Cube 오브젝트가 같이 이동을 하게 됩니다.

이때 Cube의 position은 변하지만 localPosition은 변하지 않습니다.

그런 이유는 Cube 오브젝트의 기준이 부모 오브젝트이기 때문입니다.

1
2
3
4
5
6
7
//오브젝트의 이동 속도
private float _moveSpeed = 5f;

void Update(){
//위로 이동
transform.localPosition += Time.deltaTime * _moveSpeed * Vector3.up;
}

오른쪽으로 이동하는 기능을 부모 오브젝트에 추가해보겠습니다.

[Parent Object Position]

ParentMove

부모 오브젝트인 파란색 Cube를 이동시켜보았습니다.

우측의 inspector창에 보이는 position은 부모 오브젝트의 position입니다.

해당 오브젝트는 position 값이 변하는 것을 알 수 있습니다.

자식오브젝트인 분홍색 Cube의 position은 어떻게 변할까요?

[Child Object Position]
image/Movement2.gif

자식 오브젝트의 Position값은 변하지 않습니다.

이는 특정 오브젝트의 자식형질을 가지게 되면서 인스펙터 창에서 확인할 수 있는 position이 localPosition이기 때문입니다.

부모 오브젝트를 기준으로 일정한 간격을 두고 이동하기 때문에 localPosition에는 변동이 없는 상태입니다.

이런 경우에 저희가 눈으로 확인할 수 있는 값은 localPosition이므로

자식오브젝트 trnasform.position을 이용하여 자식오브젝트를 이동시키는 것과
transform.localPosition을 이용하여 이동시키는 것은 차이가 발생하게 됩니다.

그렇다면 자식 오브젝트를 이동시키기 위해서는 어떤 값을 이용할 수 있을까요?

이럴 때 사용하는 것이 localPosition입니다.

1
2
3
4
5
6
7
//오브젝트의 이동 속도
private float _moveSpeed = 5f;

void Update(){
//위로 이동
transform.localPosition += Time.deltaTime * _moveSpeed * Vector3.up;
}

자식 오브젝트를 일정하게 위로 이동시켜보겠습니다.

Movement3

자식 오브젝트 position의 y값만 변화가 있는 것을 확인할 수 있습니다.

이는 자식 오브젝트의 localPosition에 변화를 주고 있기 때문입니다.

오브젝트의 이동 구현 또는 위치를 수정할 때 position과 localPosition을 적절하게 사용하시면 됩니다.

Node.js 설치

Node.js에서 본인 컴퓨터에 적합한 프로그램을 설치합니다.

hexo 설치

1
$ npm insall hexo-cli -g

More info: Writing

hexo 블로그 폴더 생성 및 설정

1
2
3
$ hexo init blog // blog 폴더가 생성됩니다. (blog 위치에 원하는 폴더명을 입력해주시면 됩니다.)
$ cd blog //새로 생성된 blog 폴더 위치로 이동합니다.
$ npm install

hexo 블로그 테마 불러오기

hexo를 이용하여 테마 불러오기

1
$ npm install hexo-theme-next

git clone을 이용하여 테마 불러오기

1
$ git clone https://github.com/theme-next/hexo-theme-next themes/next

(블로그 폴더)/_config.yml 파일에서 theme : 테마명으로 수정

1
2
# 저는 next theme을 설치하였으므로 next로 수정하겠습니다.
theme: next

(블로그 폴더)/_config.yml 내용 추가적으로 수정

1
2
3
4
5
6
7
8
9
10
11
title: zerone
subtitle: 개발 일지
description: 화이팅 !
author: zerone

# Deployment
deploy:
type: git
repo: https://github.com/eui-young/eui-young.github.io.git
branch: main

새 포스트파일 생성

(블로그폴더)/source/ 폴더안에 _post폴더를 생성합니다.

_post 폴더 안에 포스트 파일을 작성하여 넣어주세요.

예시로 저는

1
2
3
4
5
6
7
8
9
10
---
layout: post
title: 포스트 제목
date: 2023-12-02
categorys: hexo
tags: [hexo]
comments: true
---

내용 작성...

작성하였습니다.

정적 파일 생성 (Generate static files )

1
$ hexo generate

More info: Generating

로컬 서버 구동

1
2
$ npm install hexo-server --save //hexo server 설치
$ hexo server // 또는 hexo s

로컬 서버 구동 후 localhost:4000 에 접속하여 수정사항이 제대로 적용되었는지 확인합니다.

More info: Server

git 레포지터리에 파일 적용

1
2
$ npm install hexo-deployer-git --save //설치 후 deploy가 가능합니다.
$ hexo deploy // hexo d -g generate 후 deploy

More info: Deployment

적용 완료

deploy완료 후 deploy 연결 레포지터리에 업로드가 정상적으로 완료되었다면 블로그에 접속하여 변경사항을 확인해주세요.

[C#] Serialization, Deserialization

유니티로 종스크롤 슈팅게임을 만들면서 데이터를 저장하고, 불러오는 과정이 있었다.

Json 파일로 데이터를 저장해주었고 DataManager라는 클래스를 통하여 데이터를 불러오고, 저장을 해주었다.

이 과정에서 Deserialization, Serialization 즉, 직렬화와 역직렬화 과정을 통해 데이터를 관리하였다.

Serialization

직렬화는 객체의 형태로 존재하는 데이터를 연속적인 데이터로 변형하는 것이다.

“name” : “euiyoung”,

“age” : 24,

“gender” : “woman”

key - value 의 객체 상태로 존재하는 위 데이터를

“euiyoung” 24 “woman”

형태로 만들어준다.

데이터를 저장하거나 데이터를 전송할 때 직렬화 과정을 거친다.

Deserialization

역직렬화라고 일컫으며 직렬화된 데이터를 객체의 형태로 만드는 것을 의미하는 것이다.

스트림 데이터를 읽어 원래의 객체 형태로 복원을 하는 것으로

특정 데이터를 불러올 때 역직렬화 과정을 거친다.

“euiyoung” 24 “woman”

“name” : “euiyoung”,

“age” : 24,

“gender” : “woman”

위의 연속적인 데이터를 아래의 객체로 변형하는 과정이다.

[Unity] GetComponentsInChildren

한 오브젝트의 자식 오브젝트들의 배열로 불러오고 싶을때

GetComponentsInChildren 을 이용하는데

1
2
3
4
5
6
GameObject ParentObject;
GameObject[] childrenObject;

void Start()
{ childrenObject=ParentObject.GetComponentsInChildren<GameObject>(true);
}

이렇게 사용하니 다음 오류가 발생했다.

ArgumentException: GetComponent requires that the requested component 'GameObject' derives from MonoBehaviour or Component or is an interface

GameObject는 MonoBehaviour의 클래스에서 컴포넌트로 사용되지 않기 때문에

GetComponentsInChildren<GameObject>를 사용하지 못한다는 것이다.

그렇기 때문에 다음과 같이 GameObject의 컴포넌트를 사용해주어야 한다.

1
2
3
4
5
6
GameObject ParentObject;
Transform[] childrenObject;

void Start()
{ childrenObject=ParentObject.GetComponentsInChildren<Transform>();
}

또한 GetCompoentsInChildren은 해당 오브젝트나 자식 오브젝트가 비활성화 상태일 때 이용할 수가 없다.

하지만 GetComponentsInChildren()는 includeInactive라는 매개변수를 가지며 디폴트값으로는 false를 가진다.

GetComponentsInChildren(true)

includeInactive 값을 true로 넘겨준다면 비활성화 되어있는 자식 오브젝트들을 이용할 수 있다.

참고 https://foxtrotin.tistory.com/145

[Unity] 부모, 자식 오브젝트 동시에 투명화시키기

이미지를 부모 오브젝트로 두고 버튼을 자식 오브젝트로 두었을 때,

이미지의 투명도를 조절해도 버튼의 투명도는 변하지 않는다.

자식 오브젝트의 알파 값을 부모 오브젝트의 알파 값과 똑같이 바꾸고 싶다면

부모 오브젝트 컴포넌트에 Canvas  Group 를 추가해주고 Canvas Group Alpha값을 바꾸어 주면 된다.

Canvas Group

1
2
GameObject ParentObject;
ParentObject.GetComponent<CanvasGroup>().Alpha= 0.5f;

[Unity] UI 클릭 시 다른 오브젝트가 클릭될 때

클릭이벤트를 이용하는 오브젝트 위에 안내 메시지창을 뜨게 하거나, 이미지가 뜰 경우

UI에 막혀 클릭이 안될거라고 생각한 오브젝트가 클릭 이벤트를 처리하는 상황이 발생할 수 있다.

이럴 땐

① Inspector창에서 사용되는 Image의 Raycast Target을 체크해준다.

Raycast Target은 z축 방향으로 ray를 쏠 때 광선이 닿는대상이 될 것인지 아닌지를 결정한다.

② 마우스 클릭 처리를 하는 코드를 작성할 때 IsPointerOverGameObject()를 이용해준다.

IsPointerOverGameObject()는 UI가 클릭되면 True, 그렇지 않다면 false를 반환한다.

1
using UnityEngine.EventSystems;

마우스 클릭을 처리하는 부분에 IsPointerOverGameObject() 메소드를 이용하여 작성해주면 된다.

1
2
3
4
5
6
7
private void OnMouseDown()
{
if(!EventSystem.current.IsPointerOverGameObject())
{
//입력 처리 내용
}
}

List 관련 메소드

List생성

1
2
3
4
List <int> num1 = new List<int>();
List <int> num2 = new List<int>(){1,2,3};
List <int> num3 = new List<int>(num2); //contains: 1,2,3
List <int> num4 = new List<int>(10); //capacity:10

Add


Add

List에 원소를 추가

1
2
List<int> num=new List<int>();
num.Add(2); // contains: 1

AddRange

List 끝에 배열 추가

1
num.AddRange(b); // contains: 1, 4, 2, 5, 6

Insert

List 중간에 원소 삽입

1
2
3
num.Add(1); // contains: 1
num.Add(2); // contains: 1, 2
num.Insert(1,4) // contains: 1 ,4, 2

InsertRange

List 중간에 배열 추가

1
2
3
4
int[] b= new int[2];
b[0]=5;
b[1]=6;
num.InsertRange(1,b); // contains: 1, 5, 6, 4, 2

InsertRange(n, name)

n: 특정 배열을 삽입하고 싶은 시작 지점

name: 삽입하고 싶은 배열명

Delete


Clear

List 모든 원소 삭제

1
num.clear(); //empty

Remove

1
num.Remove(4); // contains: 1,2

Remove(item) 삭제하고 싶은 원소를 쓰면 된다 !

RemoveAll

1
2
num // contains: 1,4,2
num.RemoveAll(x=> x<2); // contains: 4,2

RemoveAll(필요한 조건) 해당 조건을 만족하는 원소를 삭제

RemoveAll(x=> true) 모든 원소가 삭제

RemoveAt

1
2
num // contains: 1,4,2
num.RemoveAt(1) // contains: 1,2

RemoveAt(num) num에 해당하는 index의 원소 삭제

Etc


Contains

1
2
num // contains:1,4,2 
num.Contains(1); // 1인 원소가 존재하므로 true

Reverse

1
num.Reverse() //num:2,4,1

Sort

1
num.Sort() //num: 1,2,4 작은 순서대로

ToArray

1
int[] array= num.ToArray(); //array:1,4,2

GetComponent, FindObjectOfType

GetComponet

특정 object의 component를 찾음

1
2
3
GameObject object;
object.GetComponent<SpriteRenderer>();
//object의 component인 SpriteRenderer을 찾음

FindObjectOfType

hierarchy창에 있는 모든 object들을 검색 검색된 object script 함수 사용

1
2
GameManager gameManager = FindObjectOfType<objectManager>();
//object의 script인 objectManager를 찾음