임시 정리 / Blah blah
참고 링크들 북마크에 정리
C/C++ 헤더 선언 순서
0. (stdafx.h | pch.h)
1. C/C++ Standard Library
2. Architecture-specific headers
3. User-defined headers
인스펙터 여러 개 띄우는 방법
Alt + P
Destroy 지연시키는 방법
// Destroy 함수 실행시 초단위 인자를 전달하면 된다.
// 2초 후 Destroy
Destroy(2.0f);
에셋 임포트시 정상적으로 보이지 않을 때
Hidden/InternalErrorShader 로 되어 정상적으로 보이지 않을 때
Shader를 Standard로 바꿔주면 되는 경우도 있다.
Sketchfab for Unity 오류나면서 패키지 임포트 안될 때
유니티를 껐다 키면 된다.
목적지 도달 확인 시 주의 사항
// 기본적으로 이동은 다음과 같이 처리한다.
transform.position += dir * speed * Time.deltaTime;
float distance = Vector3.Distance(transform.position, destination.position)
// 목적지 위치에 오차 없이 정확히 도달하기란 거의 불가능하다.
if (distance == 0)
// 따라서, 다음과 같은 방식으로 처리해야 한다.
if (distance <= 0.1f)
UI 작업시 유의사항
캔버스 내의 게임 오브젝트들은 아래로 갈수록 앞에 보여지기 때문에, 위 쪽에 있는 오브젝트가 가려지지 않도록 주의해야 한다.
UnityEngine.Mathf 와 System.Math
유니티의 Mathf 에는 Math 보다 3D 계산에 특화된 함수들이 추가되어 있다.
System.Math 는 double 을 사용하는 반면,
UnityEngine.Mathf 는 float 을 사용한다.
레이어와 태그
레이어 : 오브젝트를 그룹으로 구분하는 것이다.
0~7까지는 기본 레이어, 8~31까지는 사용자 지정 레이어로 32비트로 표현된다.
(1) Layer Collision Matrix 에서 체크로 조정할 수 있다.
해제된 레이어끼리는 충돌 체크를 하지 않는다.
(2) Culling Mask 를 이용해 게임 뷰에서 보이지 않게 처리할 수 있다.
체크를 해제한 레이어는 실제 존재하지만 보이지 않는다.
(3) 레이 캐스트 시에 특정 레이어만 캐스트할 수 있다.
// Player 만 포함
int mask = 1 << LayerMask.NameToLayer("Player");
// Player 만 제외
int mask = ~(1 << LayerMask.NameToLayer("Player"));
bool Physics.Raycast(ray, out raycastHit, Mathf.Infinity, mask)
(4) 충돌 시에 특정 레이어인지 확인할 수 있다.
if (other.gameObject.layer == LayerMask.NameToLayer(strLayer))
if (LayerMask.LayerToName(other.gameObject.layer) == strLayer)
태그 : 단일 오브젝트에 부여하며, 여러 오브젝트가 동일한 태그를 가질 수 있다.
(1) 오브젝트를 찾는데 사용할 수 있다.
GameObject.FindWithTag(strTag);
(2) 충돌 시에 특정 태그인지 확인할 수 있다.
if (other.gameObject.CompareTag(strTag))
- 참고
https://notyu.tistory.com/38
https://sorting.tistory.com/12
프리팹에서의 게임 오브젝트 할당
에디터에서 드래그를 통해 게임 오브젝트를 할당할 때, 프리팹 내에서는 프리팹 내의 게임 오브젝트와 프로젝트 창의 프리팹만 할당할 수 있다.
- 참고
https://onecoke.tistory.com/entry/%EC%9C%A0%EB%8B%88%ED%8B%B0-prefab%EC%97%90-%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8-%ED%95%A0%EB%8B%B9
곱셈이 나눗셈보다 빠른 이유
곱셈은 곱해지는 수를 곱하는 수의 각 자릿수에 곱해 더하면 한 번에 끝낼 수 있지만,
나눗셈은 나머지가 나누는 수보다 작아질 때까지 나머지를 기억하며 계속 빼야하기 때문이다.
- 참고
https://blog.naver.com/fah204/221573584390
애니메이션 재생할수록 위치가 이상해질 때
// 비추천
애니메이션 편집 창에서 Animator.Root 관련 키들을 삭제해준다.
원본 에니메이션이 수정되고 작업이 번거롭다는 단점이 있다.
// 추천 (모델에 적용하여 모든 애니메이션이 영향을 받음)
간단하게 애니메이터의 Apply Root Motion 을 꺼준다.
애니메이션으로 인해 위치/회전이 변경되지 않게 한다는 뜻이다.
// 추천 (각 애니메이션마다 적용)
애니메이션 옵션에서 Root Transform 관련 속성의 Bake Into Pose 를 켜준다.
Bake Into Pose 는 해당 이동/회전을 잠그겠다는 의미이다.
두 방법 모두 위치가 고정돼버리므로 생동감이 사라지는 단점이 있다.
- 참고
https://bm4904.tistory.com/20
https://blog.naver.com/sasayakki/221358263271
gameObject.GetComponent() 와 Component.GetComponent() 의 차이점
두 함수는 완벽히 같은 동작을 수행할 뿐만 아니라, 사실 수행되는 함수도 동일하다.
유니티 공식 문서에는 Component.GetComponent() 는 게임 오브젝트에 컴포넌트가 존재할 경우 반환한다고 되어 있으며, 애초에 자신과 상관 없이 게임 오브젝트에서 컴포넌트를 찾는다는 뜻이다.
따라서, 다음과 같은 괴상한 코드도 정상적으로 작동한다.
other.transform.GetComponent<MyComponent>().gameObject.GetComponent<MyComponent>().transform.gameObject.GetComponent<MyComponent>().something = true;
transform 과 GetComponent 등은 사실 gameObject 의 멤버이지만, 자주 쓰이므로 컴포넌트에서 바로 사용할 수 있게 해놓은 것이다.
실제, GetComponent 가 구현돼 있는 부분을 보면 단순히 gameObject.GetComponent 를 프록시하여 호출하는 것을 볼 수 있다.
모든 컴포넌트는 스크립트 클래스가 인스턴스화된 객체이다.
게임 오브젝트는 컴포넌트를 담는 컨테이너이다.
게임 오브젝트와 컴토넌트는 부모, 자식 등의 상속 관계는 아니다.
에디터에서 public Transform transform 에 게임 오브젝트를 지정 가능한 이유는 유니티가 내부적으로 GetComponent()를 통해 변환해 주기 때문이다.
부모, 자식 관계가 아니기에 타입 캐스팅이 불가능하고 코드에서는 Transform tr = other.gameObject; 와 같이 사용할 수 없다.
모든 게임 오브젝트의 타입은 같지만, 컴포넌트는 각기 다른 타입을 갖는다.
모든 게임 오브젝트는 무조건 Transform 컴포넌트를 갖는다.
// 게임 오브젝트 비활성화 하기
GameObject.SetActive(false);
// 컴포넌트 비활성화 하기
Component.enabled = false;
이름이 같은 게임 오브젝트는 여러 개 존재할 수 있고, 이름이 같은 자식도 가능하다.
한 오브젝트에 같은 컴포넌트를 어러 개 붙이는 것도 가능하다.
- 참고
https://forum.unity.com/threads/gameobject-getcomponent-vs-getcomponent.948035/
https://docs.unity3d.com/ScriptReference/MonoBehaviour.html
https://github.com/Unity-Technologies/UnityCsReference/blob/2022.2/Runtime/Export/Scripting/Component.bindings.cs
https://answers.unity.com/questions/1360282/what-is-the-difference-between-gameobjectgetcompon.html
GameObject 와 Component 의 부모 클래스
https://devbot.tistory.com/entry/%EC%9C%A0%EB%8B%88%ED%8B%B0-monobehaviour-%EC%83%81%EC%9C%84-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%A0%95%EB%A6%AC
https://skuld2000.tistory.com/25
https://we1cometomeanings.tistory.com/106
https://blog.eyas.sh/2020/10/unity-for-engineers-pt5-object-component/
- 참고
https://devbot.tistory.com/entry/%EC%9C%A0%EB%8B%88%ED%8B%B0-monobehaviour-%EC%83%81%EC%9C%84-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%A0%95%EB%A6%AC
https://skuld2000.tistory.com/25
https://we1cometomeanings.tistory.com/106
https://blog.eyas.sh/2020/10/unity-for-engineers-pt5-object-component/
IEnumerator
실행 흐름을 넘겼다가 중단된 다음 부분부터 이어서 실행할 수 있다.
public static void Main(string[] args)
{
IEnumerator it = IE();
Console.ReadLine();
Console.WriteLine(it.MoveNext());
Console.WriteLine(it.Current);
Console.ReadLine();
Console.WriteLine(it.MoveNext());
Console.WriteLine(it.Current);
Console.ReadLine();
Console.WriteLine(it.MoveNext());
Console.WriteLine(it.Current);
Console.ReadLine();
Console.WriteLine(it.MoveNext());
Console.WriteLine(it.Current);
Console.ReadLine();
Console.WriteLine(it.MoveNext());
Console.WriteLine(it.Current);
}
public static IEnumerator IE()
{
Console.WriteLine("1");
yield return 1;
Console.WriteLine("2");
yield return 2;
Console.WriteLine("3");
yield return 3;
Console.WriteLine("4");
yield return 4;
Console.WriteLine("5");
}
- 참고
https://blog.naver.com/happybaby56/221322535793
1
True
1
2
True
2
3
True
3
4
True
4
5
False
4
IEnumerable?
일반적으로 foreach 문에 사용되며, GetEnumerator() 를 통해 IEnumerator 를 가져올 수 있다.
비표준적으로(홀수만 가져오기 등) 값을 가져오고 싶을 때는 IEnumerator 를 사용해야 한다.
- 참고
https://stackoverflow.com/questions/619564/what-is-the-difference-between-ienumerator-and-ienumerable#:~:text=An%20IEnumerator%20is%20a%20thing,method%20that%20returns%20an%20IEnumerator%20.
코루틴
StartCoroutine(MyCoroutine()); 으로 코루틴을 시작하는 것은 MyCoroutine() 에서 반환된 IEnumerator를 이용해, MoveNext() 의 결과가 false일 때까지 매 프래임마다 MoveNext()를 호출하겠다는 뜻이다.
단순히 MyCoroutine() 으로 실행한 상태에서는 코드가 시작되지 않으며, 첫 MoveNext() 를 실행해야 첫 yield return 부분까지 실행된다.
// 3초 동안은 MoveNext()를 실행하지 않는다.
yield return new WaitForSeconds(3.0f);
https://www.jacksondunstan.com/articles/3036/comment-page-1
https://docs.unity3d.com/es/530/ScriptReference/CustomYieldInstruction.html
https://forum.unity.com/threads/c-ienumerator-could-someone-help-me-understand-this-code-example.204460/
https://answers.unity.com/questions/233010/yield-and-coroutines-how-do-the-actually-work.html
- 참고
https://velog.io/@uchang903/UnityCoroutine%EC%BD%94%EB%A3%A8%ED%8B%B4%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%ED%99%9C%EC%9A%A9
https://www.csharpstudy.com/CSharp/CSharp-yield.aspx
https://postpiglet.netlify.app/posts/Coroutine-Considerationn/
코루틴을 시작하고 멈추는 방법
IEnumerator it = CoFunc();
StartCoroutine(it);
StopCoroutine(it);
Coroutine cort = StartCoroutine(CoFunc());
StopCoroutine(cort);
StartCoroutine("CoFunc");
StopCoroutine("CoFunc");
모두 멈추기
StopAllCoroutines();
조건문을 넣어 특정 조건에서 중지시킬 수도 있다.
yield break;
- 참고
https://notyu.tistory.com/62
코루틴을 멈추는 잘못된 방법
// 유니티에서는 가능하면 StartCoroutine 과 StopCoroutine 시에 전달 인자를 혼합하여 쓰지 말 것을 권장한다.
StartCoroutine(CoFunc());
StopCoroutine("CoFunc");
StartCoroutine(CoFunc());
StopCoroutine(CoFunc());
- 참고
https://notyu.tistory.com/62
WaitForSeconds
WaitForSeconds 가 시작되는 시점은 호출 직후가 아닌, 현재 프레임이 끝난 후이다.
- 참고
https://docs.unity3d.com/kr/530/ScriptReference/WaitForSeconds.html