검색결과 리스트
programmer/OpenGL,Unity에 해당되는 글 13건
- 2012/03/28 Unity3D,X-Code... 이젠.. 포팅이당.
- 2011/08/23 MonoBehaviour 오버라이딩 가능 함수 레퍼런스 총 정리..랄까?? (1)
- 2011/08/23 Unity3D iOS Porting Tips
- 2011/07/01 UnityKorea 강좌 중에 몇가지 정리
- 2011/06/30 Sound & Object Collection
- 2011/06/30 Unity GUI 공부하기
- 2011/06/29 Newbie guide to Unity Javascript (초보자를 위한 자바스크립트 가이드)
- 2011/06/28 Cinema4D Animation & Interaction
- 2011/06/27 Unity3DStudent 를 이용한 공부 2
- 2011/06/27 Unity3DStudent 를 이용한 공부
글
http://unity3d.com/unity/download/
Unity3D 에서 이번에 mobile 용 iOS,android 에 대한 기간 한정 무료 배포(를 해서...
기쁜 마음에 세팅을 완료하고 진행을 하던중에 무수히 많은 에러들로 인해 곤혹을 치뤘습니다.
1. MAX OSX Lion 을 버전업 했습니다.
2. XCode 4.31을 설치 했습니다.
3.Unity3.5 를 설치하고... iOS
이것저것 검색해보니 Unity3.5 이번 버전에서... XCode4.31에 제대로 호환이 안된다구.. XCode4.3 으로 설치해서 하면 잘된다고함.
http://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wo/5.1.17.2.1.3.3.1.0.1.1.0.3.1.3.3.1
이곳에서 XCode를 다운 받으시면 됩니다.
설정
트랙백
댓글
글
11년동안 구글이 얻는 것들 Google: 11 Years of Acquisitions (Infographic)
1. MonoBehaviour
모든 스크립트가 상속받는 기본 클래스입니다.
(Javascript 는 무조건 MonoBehaviour 를 상속받고 C#, Boo 의 경우 명시적으로 상속받아야 합니다.
C#, Boo 에서 단순 데이터 보관용 클래스, 전역으로 동작하는 매니저 클래스같은 건 상속받지 않고 쓸 수 있습니다.)
MonoBehaviour 는 Behaviour 클래스를 상속받고 Behaviour 는 Component 를 상속받습니다.
즉 MonoBehaviour 를 상속받은 클래스는 게임 오브젝트에 component 로 붙일 수 있다는 뜻입니다.(붙일 수 있다는 건 모두 알고 계시죠? ㅎㅎ)
Behaviour 클래스는 enable/disable 가능합니다.
때문에 MonoBehaviour 도 역시 켜고 끌 수 있습니다.
(스크립트를 Inspector 에 붙이면 앞에 체크박스가 나오죠? 그겁니다.)
레퍼런스를 보면 MonoBehaviour, Behaviour, script 라는 명칭을 혼재해서 쓰는데 혼란을 줄 수 있으니, 앞으로 모두 '스크립트'로 통칭하도록 하겠습니다.
2. 앞에 On 이 붙지 않는 함수
1) Update
Update 함수는 스크립트가 켜져 있을 때(enabled 상태일 때) 매 프레임마다 호출됩니다.
Update 함수는 스크립트에서 가장 빈번하게 사용되는 함수입니다.
지나간 시간을 알고 싶으면, Time.deltaTime 을 사용하면 됩니다.
이 함수는 스크립트가 켜져 있을 때만 불립니다.
2) LateUpdate
LateUpdate 함수는 스크립트가 켜져 있을 때 매 프레임마다 호출됩니다.
LateUpdate 함수는 모든 Update 함수가 호출된 후 호출됩니다.
이것은 스크립트의 실행 순서를 정하는 것에 도움이 됩니다.
예를 들어 따라다니는 카메라는 언제나 LateUpdate 를 구현해야 하는데, 그 이유는 이 카메라가 따라가는 오브젝트들은
Update 함수 안에서 움직일 가능성이 있기 때문입니다. 이 함수는 스크립트가 켜져 있을 때만 불립니다.
3) FixedUpdate
FixedUpdate 함수는 스크립트가 켜져 있을 때 매 프레임마다 호출됩니다.
FixedUpdate 함수는 Rigidbody 를 다룰 때 Update 대신에 사용됩니다.
예를 들어 rigidbody에 일정한 힘을 가할 때, FixedUpdate를 구현하여 매 fixed frame 마다 힘을 가해주어야 합니다.
※ FixedUpdate 는 매 프레임마다 호출되지만 한 프레임에 여러번 호출될 수도 있습니다. ??
더보기
// 즉 이 예는 등가속 운동입니다. (Vector3.down 하면 중력을 받는 것과 동일하다는 뜻입니다.)
function FixedUpdate()
{
rigidbody.AddForce(Vector3.up);
}
4) Awake
Awake 함수는 스크립트 객체가 로딩될 때 호출됩니다.
Awake 함수는 게임이 시작하기 전에 변수나 게임 상태를 초기화하기 위해 사용합니다.
Awake 함수는 스크립트 객체의 라이프타임 동안 단 한번만 호출됩니다.
Awake 함수는 모든 오브젝트가 초기화된 후 호출되기 때문에, 다른 오브젝트에 메시지를 날리거나 GameObject.FindWithTag 같은 함수를 안전하게 사용할 수 있습니다.
이런 이유로 Awake 함수에서 스크립트를 레퍼런싱한 후, Start 함수에서 필요한 정보를 넘겨받거나 넘겨줄 수 있습니다.
Awake 함수는 언제나 Start 함수 전에 호출됩니다. 이것은 스크립트의 초기화 순서를 정할 수 있게 합니다.
Awake 함수는 coroutine 으로 동작할 수 없습니다.
5) Start
Start 함수는 Update 함수가 처음 호출될 때 Update 함수 직전에 호출됩니다.
Start 함수는 스크립트가 동작하는 라이프타임 동안 단 한번만 호출됩니다.
Awake 함수와의 차이는 Start 함수는 스크립트가 켜져있을 때만 호출된다는 것입니다.
이것은 정말로 필요할 때까지 초기화 코드 실행을 연기시킬 수 있습니다.
Awake 함수는 언제나 Start 함수가 호출되기 전에 호출됩니다. 이것은 스크립트의 초기화 순서를 정할 수 있게 합니다.
Start 함수는 모든 스크립트 객체의 Awake 함수가 호출된 후에 호출됩니다.
6) Reset
기본값으로 리셋합니다.
Reset 함수는 유저가 Inspector의 context menu 에서 Reset 버튼을 눌렀을 때나, 게임 오브젝트에 스크립트를 처음 붙였을 때 호출됩니다. 이 함수는 에디터 모드에서만 호출됩니다.
Reset은 Inspector에 초기 값을 설정할 때 가장 자주 사용하는 함수입니다.
7 ) Awake, Start, Update, LateUpdate 순서도
'A, B, C 라는 게임 오브젝트가 있고, A, B 에 스크립트가 하나씩 붙어있습니다. B는 스크립트가 비활성화 되어 있습니다.'
라는 상황을 가정하겠습니다.
1. 게임이 로딩되면 우선 A, B, C 모든 게임 오브젝트가 초기화 됩니다.
2. 이후 A, B 에 붙어있는 스크립트의 Awake 함수가 호출됩니다.
(이 상황에서도 이미 A, B, C 게임 오브젝트와 구성 컴포넌트는 모두 메모리에 들어있는 상태이므로 null 체크
이런 거 없이 안심하고 데이터 전달 등을 할 수 있습니다.)
3. 이후 A 의 Update 함수가 호출되려고 합니다. B 는 스크립트가 비활성화 상태이기 때문에 동작하지 않습니다.
4. A 의 Update 함수가 호출되려고 하는데, 이번이 첫번째 호출이네요! 우선 Start 가 호출됩니다.
5. A 의 Start 가 호출되었으니 Update 가 호출됩니다. 앞으로 매 프레임마다 호출되겠네요.
6. A 의 LateUpdate 도 호출됩니다. 역시 앞으로 매 프레임마다 호출됩니다.
- 여기서 B의 스크립트를 활성화시켰습니다.
7. B 의 Update 함수도 호출되기 시작합니다. 제일 처음 Update 호출될 때 역시 Start 가 우선 한 번 호출됩니다.
8. A, B 의 Update 함수가 모두 호출된 후 A, B 의 LateUpdate 가 호출됩니다.
- 여기서 C에 스크립트 컴포넌트를 붙였습니다.
9. C 에 스크립트가 붙자 C의 Awake 가 호출됩니다.
10. A, B, C 의 Update 차례. C의 경우 처음 Update 호출이라서 그전에 Start 함수가 우선 호출됩니다.
11. A, B, C 의 LateUpdate 차례. A, B, C 의 모든 Update가 끝나면 호출되기 시작합니다.
3. On~ 계열 함수
1) OnMouse~ 함수군
마우스와 GUIElement, Collider 사이의 인터랙션에 관련한 함수 집합입니다.
게임 오브젝트가 Ignore Raycast 레이어에 속해있으면 호출되지 않습니다. (내부적으로 Raycast 를 하는 듯.)
이 함수들은 co-routine 으로 사용할 수 있습니다. (yield 사용 가능.)
이 이벤트는 GUIElement, Collider 에 붙어있는 모든 스크립트에 전달됩니다.
OnMouseEnter - 마우스가 처음 오브젝트 위로 올라왔을 때 호출.
OnMouseOver - 마우스가 오브젝트 위에 있을 경우 매 프레임마다 호출.
OnMouseExit - 마우스가 처음 오브젝트 밖으로 나갔을 때 호출.
OnMouseDown - 오브젝트 위에서 마우스 버튼을 눌렀을 때 호출.
OnMouseUp - 오브젝트 위에서 마우스 버튼을 땠을 때 호출. 눌렀을 때의 오브젝트와 같은 오브젝트일 때만 호출됨.
OnMouseDrag - 오브젝트 위에서 마우스 버튼을 누른 상태로 있을 때 매 프레임마다 호출.
여기서 Drag 는 일반적으로 생각하는 드래그가 아니라 그냥 꾸욱 누르고 있는 상태를 나타냅니다.
(물론 그 상태로 마우스를 움직이면 드래그지만..)
그리고 오브젝트 위에 마우스를 올려놓고 누르고 있으면 Over와 Drag 가 매 프레임마다 호출됩니다.
Drag 호출된다고 Over 호출 안된다거나 하는 거 없습니다. *ㅅ*
스크립트가 enable / disable 과 상관없이 호출됩니다.
즉 Inspector 에서 체크박스를 해제해도 스크립트가 붙어있다면 무조건 호출됩니다.
앞으로 '스크립트가 켜져있을 때만 호출된다.' 는 말이 없으면 기본적으로 비활성화 상태에서도 호출된다고 생각하세요.
2) OnTrigger~(other : Collider), OnCollision~(collisionInfo : Collision) 함수
OnTrigger~, OnCollision~ 은 모두 충돌 관련 함수입니다.
충돌이 일어나려면 두 오브젝트 모두 Collider 를 가져야 하고 둘 중 하나는 Rigidbody 를 가져야 합니다.
그리고 Rigidbody 를 가진 쪽이 움직여서 서로 만날 경우만 이벤트가 일어납니다. 물론 둘 다 움직이고 있어도 됩니다.
(그러니까 Rigidbody 를 가진 녀석은 가만히 있는데 그냥 Collider 가 아무리 와서 들이박아도 아무런 일도 생기지 않는다는 겁니다. ==> 중요한것입니다.)
Trigger 는 Inspector 창에서 Collider 의 Is Trigger 속성이 켜져있을 때 발생합니다.
Trigger 가 켜져있을 때는 Collision 관련 함수는 호출되지 않습니다.
Trigger 가 켜져있을 때는 두 오브젝트 사이에 물리 계산이 이루어지지 않습니다.
그래서 Trigger 는 단순한 '영역' 으로 이해하는 것이 좋습니다.
Collision 은 두 오브젝트 중 적어도 하나가 Inspector 창에서 Rigidbody 의 Is Kinematic 속성이 꺼져있을 때 발생합니다.
(Is Kinematic 이 켜져있으면 이 오브젝트는 내부 물리연산을 하지 않기 때문에 부딪쳐도 그냥 뚫고 지나갑니다.)
두 오브젝트 모두 Kinematic 속성이 켜져있으면 어느 쪽이 움직여서 겹치더라도 물리 연산이 이루어지지 않기 때문에
충돌 함수가 호출되지 않습니다.
Trigger 는 함수의 파라메터로 Collider 변수가 들어옵니다. 이것은 자신과 접촉한 오브젝트의 Collider 입니다.
Collision 은 함수의 파라메터로 Collision 변수가 들어옵니다. 이것은 접촉에 대한 여러가지 정보를 담고 있는 클래스입니다.
relativeVelocity - 두 오브젝트의 상대 속도입니다. 충격량이라는 느낌일까요? (읽기 전용)
rigidbody - 자신과 접촉한 Rigidbody 입니다.
만약 상대가 Rigidbody 가 없는 Collider 라면 이 값은 null 입니다. (읽기 전용)
collider - 자신과 접촉한 Collider 입니다. (읽기 전용)
transform - 자신과 접촉한 오브젝트의 Transform 정보입니다. (읽기 전용)
gameObject - 자신과 접촉한 오브젝트입니다. (읽기 전용)
contacts - 물리 엔진에서 연산한 접촉 포인트 정보입니다. ContactPoint 의 배열입니다.
두 종류 모두 ~Enter, ~Stay, ~Exit 함수를 제공합니다.
Enter 는 접촉을 시작했을 때 호출,
Stay 는 접촉 중일 때 매 프레임마다 호출,
Exit 는 접촉이 끝났을 때 호출됩니다.
두 함수군 모두 yield 사용 가능합니다.
* Mesh Collider 관련해 추가 설명
기본 도형으로 이루어진 Collider 이외에 실제 모델같은 Mesh Collider 를 붙일 수도 있습니다. (알고 계시겠죠? ㅎ)
그런데 기본적으로 Mesh Collider 는 다른 Mesh Collider 와 충돌 계산이 이루어지지 않습니다.
아마 계산이 오래 걸리기 때문에 막아놓은 것으로 보입니다. 기본 도형은 대체로 방정식 몇번 풀면 체크 끝나지만, Mesh 는... 모든 폴리곤을 순회하면서 체크해야 하니까요.
그래도 하고 싶은 사람을 위해 준비된 Inspector 창의 Mesh Collider 의 Convex 속성을 켜면 다른 Mesh Collider 와 충돌 계산을 합니다. 단, Convex 속성을 켜기 위해서는 Mesh Collider 의 폴리곤 개수가 255개를 넘으면 안됩니다.
이런 제한이 있습니다~ 간단한 게임이나 계산 파워가 부족한 iphone 게임을 만들 때는 굳이 Mesh Collider 쓸 필요는 없을 것 같습니다.
3) OnControllerColliderHit(hit:ControllerColliderHit)
CharacterController 가 Move 함수로 이동하는 도중 다른 Collider 와 충돌했을 때 호출됩니다.
(CharacterController 가 붙어있는 gameObject 를 Translate 로 움직여서 충돌할 때는 호출되지 않습니다.
무조건 CharacterController 의 Move 함수로 움직일 때만 호출됩니다.)
CharacterController 는 이전 충돌 함수 때처럼 따로 Rigidbody, Collider 가 필요없습니다.
4) OnJointBreak(breakForce:float)
게임 오브젝트에 붙어있는 조인트가 끊어질 때 호출됩니다.
조인트에 설정된 breakForce 보다 높은 힘이 가해지면 조인트는 끊어집니다.
조인트가 끊어질 때 주어진 힘이 파라메터로 들어옵니다.
조인트가 끊어지고 OnJointBreak 가 호출된 후 조인트는 자동적으로 게임 오브젝트에서 지워집니다.
5) OnParticleCollision(other:GameObject)
파티클이 Collider 와 충돌했을 때 호출됩니다.
WorldParticleCollider 와 충돌한 Collider 에 붙어있는 모든 스크립트에 호출됩니다.
Inspector 창에서 WorldParticleCollider 의 sendCollisionMessage 속성을 켜야지 호출됩니다.
(즉, 기본적으로 WorldParticleCollider 가 붙어있어야 합니다.)
Collider 는 따로 Rigidbody 일 필요 없습니다. yield 사용 가능합니다.
6) OnBecameVisible / OnBecameInvisible
renderer 가 어떤 카메라에 보이기 시작할 때, 보이지 않기 시작할 때 호출됩니다.
레퍼런스 설명은 위와 같은데, '어떤' 카메라라는 것은 여러대의 카메라가 있을 때 그 중 하나라도 보이기 시작하면 Visible, 모두 보이지 않을 때 Invisible 이라는 것이며, 단, 카메라가 있어도 비활성화 상태이거나 화면에 보이지 않을 경우 (즉 View Port Rect 의 width, height 가 0일 때) 는 '어떤' 카메라에 포함되지 않습니다.
오브젝트의 renderer 컴포넌트를 꺼도 마찬가지로 Invisible 입니다.
그러니까 단순히 말해서 어쨌든 화면에 보이기만 하면 Visible, 안보이면 Invisible 입니다.
renderer 에 붙어있는 모든 스크립트에 호출됩니다.
화면에 보일 때만 스크립트가 처리되도록 할 때 유용합니다.
yield 사용 가능합니다.
function OnBecameVisible ()
{
enabled = true;
}
function OnBecameInvisible()
{
enabled = false;
}
주의점이 있습니다. 툴에서 작업할 때 Scene View 에도 동일하게 동작합니다.
Game View 에서 안보여도 Scene View 에서 보이고 있는 상태라면 Invisible 호출이 안됩니다.
7) OnLevelWasLoaded(level:int)
새로운 레벨(scene)이 로딩되었을 때 호출됩니다.
level 파라메터는 로딩된 레벨의 인덱스를 나타냅니다.
메뉴 File - Build Settings... 에서 레벨과 인덱스를 설정할 수 있습니다.
yield 사용 가능합니다.
레퍼런스에는 적혀있지 않지만 해당 장면의 모든 스크립트에서 호출되는 것 같습니다.
8) OnEnable/OnDisable
스크립트가 켜지거나 꺼졌을 때 호출됩니다.
추가로 OnDisable 의 경우 스크립트가 붙은 게임 오브젝트가 제거될 때도 호출되므로 파괴자로 사용할 수 있습니다.
툴에서 플래이 모드 중에 스크립트를 편집할 경우, 편집이 끝난 후 스크립트가 다시 로딩되면서 OnDisable, OnEnable 이 순차적으로 호출됩니다.
참고로 툴에서 플래이 중 스크립트를 고쳤을 때 고쳐진 스크립트의 Awake, Start 는 호출되지 않습니다.
그리고 OnEnable 은 Awake 함수 바로 다음에 호출됩니다. (켜져있을 경우)
9) OnGUI
GUI 를 그리거나 이벤트를 처리하기 위해 호출됩니다.
이벤트 처리도 맡고있기 때문에 한 프레임에 여러번 호출될 수 있습니다. (한 이벤트에 한 번) 스크립트가 꺼져있으면 호출되지 않습니다.
OnGUI 함수 안에서 Event.current 를 사용하면 현재 처리하고 있는 이벤트 내용을 알 수 있습니다.
이 때 사용되는 Event 클래스의 내용은 다음과 같습니다.
type - 이벤트의 타입. (http://unity3d.com/support/documentation/scriptReference/EventType.html)
mousePosition - 마우스 위치. (Vector2)
delta - 지난번 처리한 이벤트와 현재 마우스 위치의 차이. (Vector2)
button - 어떤 마우스 버튼이 눌려졌는지. (int) (0:왼쪽, 1:오른쪽, 2:가운데)
clickCount - 마우스 클릭 횟수. (int)
character - 키보드로 입력한 문자. (char)
commandName - 단축키로 입력된 명령. (string) ("Copy", "Cut", "Paste", "Delete"... 툴에서만 호출.)
keyCode - 키보드로 입력한 가공되지 않은 키코드.(http://unity3d.com/support/documentation/scriptReference/KeyCode.html)
shift - 쉬프트 눌려져 있는지.
control - 컨트롤 눌려져 있는지.
alt - 알트 눌려져 있는지.
command - Command(맥)/Windows(윈도우) 키 눌려져 있는지.
capsLock - CapsLock 켜져있는지.
numeric - 키패드 입력인지.
functionKey - 펑션키 입력인지.
isKey - 키보드 이벤트인지.
isMouse - 마우스 이벤트인지.
Event 클래스의 기타 함수는 영역이 애매해서 따로 설명하지 않습니다. (http://unity3d.com/support/documentation/scriptReference/Event.html)
10) OnApplicationPause(pause:bool)
플레이어가 정지/재개될 때 모든 스크립트에서 호출됩니다. yield 사용 가능합니다.
11) OnApplicationQuit
어플리케이션이 종료되기 직전에 모든 스크립트에서 호출됩니다.
12) OnDrawGizmos
게임 오브젝트에 기즈모를 추가합니다.
이 기즈모는 선택할 때 사용할 수 있고 언제나 그려집니다.
13) OnDrawGizmosSelected
게임 오브젝트가 선택되었을 때 기즈모를 그리고 싶을 때 구현합니다. 이 기즈모는 선택에 사용할 수 없습니다.
Gizmos 클래스는 http://unity3d.com/support/documentation/scriptReference/Gizmos.html 에서 사용법을 확인할 수 있습니다.
혹 기즈모가 뭔지 모르시는 분은..
툴의 Scene 뷰에 빛이나 카메라의 위치를 볼 수 있게 해 주는 아이콘이 기즈모입니다.
눈에 보이지 않지만 위치 설정이 필요할 때, 중요한 오브젝트를 보기 좋게 표현하기 위해.. 기타 여러가지 이유로 사용할 수 있습니다. 실제 어플리케이션에는 표시되지 않지만 툴로 작업할 때 여러모로 편하게 해 줍니다.
공동 작업할 때 자주 사용하면 좋을 거라 생각합니다.
4. 렌더링에 관련한 고급 기능
1) OnPreCull
카메라에서 장면을 컬링하기 전에 호출됩니다. 여기서 컬링이란 프러스텀 컬링입니다. (후면 컬링 아님)
카메라에 붙어있는 스크립트에만 호출됩니다.
카메라의 속성을 바꾸고 싶을 때, 이 함수 안에서 하면 좋습니다.
이 함수가 호출된 후 실제 프러스텀 컬링을 하고 각 오브젝트가 화면에 그려질지 그려지지 않을지 정해집니다.
2) OnPreRender
카메라가 장면을 렌더링하기 전에 호출됩니다.
카메라에 붙어있는 스크립트에만 호출됩니다.
yield 사용 가능합니다.
3) OnPostRender
카메라가 장면을 렌더링한 후 호출됩니다.
카메라에 붙어있는 스크립트에만 호출됩니다.
yield 사용 가능합니다.
이 함수는 해당 카메라가 모든 오브젝트를 렌더링한 후 호출됩니다.
만약 '모든' 카메라와 GUI가 렌더링된 후 무언가를 하고 싶으면 WaitForEndOfFrame coroutine 을 사용하면 됩니다.
4) OnWillRenderObject()
해당 오브젝트를 렌더링하는 카메라마다 한 번 호출됩니다.
(세 대의 카메라가 하나의 오브젝트를 보고 있으면 그 오브젝트에 붙어있는 스크립트에서 세 번 불린다는 뜻.)
(툴에서 작업할 때는 Scene View 카메라도 들어갑니다.)
이 함수는 렌더링하기 전, 컬링 중에 호출됩니다.
Camera.current 를 사용하면 현재 어떤 카메라가 렌더링할 것인지 알 수 있습니다.
5) OnRenderObject(queueIndex:int)
오브젝트가 렌더링될 때 호출됩니다. queueIndex 는 해당 오브젝트를 렌더링할 때 사용하는 렌더 큐의 값입니다.
RenderBeforeQueues 속성으로 특정한 렌더링 큐에서 동작하도록 설정할 수 있습니다.
이 함수도 OnWillRenderObject 함수처럼 각 카메라가 그릴 때마다 한 번 호출됩니다.
6) OnRenderImage(source:RenderTexture, destination:RenderTexture)
모든 렌더링이 끝난 후 호출됩니다. 카메라에 붙어있는 모든 스크립트에서 호출됩니다.
포스트 프로세스 효과를 줄 때 사용합니다. (Pro 전용)
source 는 렌더링이 끝난 화면이며 destination 텍스쳐에 결과물을 그려주면 됩니다.
카메라에 여러 이미지 필터가 붙어있을 경우 순차적으로 진행됩니다.
게임의 경우 때깔내는데 가장 중요한 포스트 프로세싱 부분이 Pro 전용으로 빠져있습니다.
(그러고 보니 free 에서 렌더 타겟이 사용 불가였으니 당연히 이것도 사용이 불가능하겠네요.)
여기 있는 함수들은 제가 사용해 본 적이 없고, 지금 당장 특별히 어떻게 쓰면 좋을지 잘 모르는 관계로 특별한 부연 설명 없이 레퍼런스를 옮겨적기만 했습니다.
참고로 3.0 부터 이쪽 함수들은 스크립트가 꺼져있으면 동작하지 않는다고 합니다.
5. 네트워킹 관련 함수
점점 써 본적이 없는 함수만 나와서 정말 난감하네요;;;
1) OnPlayerConnected(player:NetworkPlayer)
새 유저가 성공적으로 접속했을 경우 서버에서 호출됩니다.
2) OnServerInitialized
Network.InitializeServer 를 호출한 후 완료되었을 때 서버에서 호출됩니다.
3) OnConnectedToServer
서버에 성공적으로 접속했을 경우 클라이언트에서 호출됩니다.
4) OnPlayerDisconnected(player:NetworkPlayer)
유저의 접속이 끊겼을 경우 서버에서 호출됩니다.
5) OnDisconnectedFromServer(mode:NetworkDisconnection)
서버와 접속이 끊기거나 접속을 종료했을 때 클라이언트에서 호출됩니다.
6) OnFailedToConnect(error:NetworkConnectionError)
접속 시도가 실패했을 때 클라이언트에서 호출됩니다.
7) OnFailedToConnectToMasterServer(error:NetworkConnectionError)
서버나 클라이언트에서 마스터 서버로의 접속에 문제가 있을 경우 호출됩니다.
8) OnMasterServerEvent(msEvent:MasterServerEvent)
서버나 클라이언트로 마스터 서버에서 보낸 이벤트를 받았을 때 호출됩니다.
9) OnNetworkInstantiate(info:NetworkMessageInfo)
Network.Instantiate 함수로 네트워크를 통해 게임 오브젝트가 생성되었을 때 해당 오브젝트에서 호출됩니다.
네트워크 상에서 새 게임 오브젝트가 생성되었을 때 다른 사람이 생성했는지 내가 생성했는지에 따라 오브젝트에 특별한
처리를 할 때 유용합니다.
10) OnSerializeNetworkView(stream:BitStream, info:NetworkMessageInfo)
네트워크 상에서 전달되는 변수들(variables in a script watched by a network view)의 동기화 처리를 커스터마이징할
때 사용합니다..
이 함수는 직렬화된 값 (즉 BitStream으로 바뀐 정보)을 전달할 것인지 받을 것인지에 대해서 자동으로 판단합니다.
(이 오브젝트를 소유권에 따라서 처리됩니다. 소유자는 보내고 나머지는 받고.)
사실 저같은 경우 tcp, udp 연결이 필요한 게임을 만드는 게 아니라 그냥 WWW 클래스만으로도 충분합니다..
설정
트랙백
댓글
글
사진에 나온건 the Apple mothership ... 애플에서 만드는 사옥이라고 알고 있습니다. 우주선이 따로 없네요
Gallery : http://www.engadget.com/photos/the-apple-mothership/
암튼 각설하시구... 아래 내용은 좀.. 필요할듯 싶어서.. 긁어왔습니다.
원문 출처 : http://roperacket.tumblr.com/post/2544450508/unity-ios-porting
번역본 출처 : http://unity3dkorea.com/bbs/board.php?bo_table=m03_9&wr_id=148
This presentation was given in the 2010 Gaming Unconference, 31 Dec 2010. I hope you find it useful.
December 31, 2010 at 1:51pm 에 작성한 글이니까.. 거의 1년이 다 되어 가지만.. 도움이 될것으로 생각되어 정리 해놓습니다.
The following is an incomplete, unsorted bullet list of tips I picked up while porting my Unity3D game ‘Rope Racket’ to iOS (iPhone/iPad).
I will try to keep this list updated as needed, so check back soon
아래의 글은 유니티3D로 만들었던 제 게임 'Rope Racket'을 iOS(iPhone/iPad)로 이식하면서 얻은 팁들에 대해 대략적으로 정리해놓은, 미완성된 리스트입니다.
아래 리스트를 필요하면 그때그때 업데이트할 예정이니, 종종 들러서 확인해보시기 바랍니다.
Physics(물리)
Unity3D uses the highly optimized PhysX physics engine. Normally all operations involving physics should be taken care of automatically by the engine. Here are some points to consider:
■Colliders – remove unneeded colliders and combine colliders into one. E.g. an enemy object can typically use one collider.
■Overlapping colliders can produce as many as 3 solving iterations per each frame so pay special attention when forcing position on an object with a collider.
■Use simpler colliders – sphere is simpler than cube, which is simpler than mesh collider.
■Joints chain reaction – a movement on one end of the joint always yields movement on the other end. Using several interconnected joints can produce a chain reaction of consequent movements, and should be used with care.
유니티3D는 매우 잘 최적화된 PhysX 물리엔진을 사용합니다.
일반적으로 물리에 관련된 모든 기능들은 이 엔진에 의해 자동적으로 처리됩니다.
하지만 iOS에 적용할 경우 고려해 볼 만한 점이 좀 있습니다 :
•충돌자Colliders : 불필요한 충돌자들을 없애고, 하나로 묶으세요. Ex) 적 오브젝트는 한개의 충돌자만 쓰게끔
•겹쳐진 충돌자들Overlapping colliders은 매 프레임당 (많으면)3번까지의 반복 처리를 유발할 수 있으므로, 충돌자가 붙은 오브젝트의 위치를 강제로 배치할 경우 특별히 유념하시기 바랍니다.
(씬 에디터 상에서의 수동 배치나, transform값 수정에 의한 배치 등 직접 position값을 주는 경우를 말함 - 역주)
•좀 더 간단한 형태의 충돌자를 사용 : 메쉬mesh 충돌자보다는 입방체cube, 입방체 보다 구체sphere 충돌자가 더 간단합니다.
•조인트Joints의 연쇄 반응에 주의 : 조인트 사용시, 한쪽 끝의 움직임은 항상 반대쪽 끝까지의 연쇄적인 움직임을 유발합니다. 서로 연결된 몇개의 조인트를 사용하게 되면 필연적으로 연쇄 반응하는 움직임을 양산하므로, 사용에 주의하시기 바랍니다.
General Optimization (일반 최적화)
Code optimization can significantly improve performance. In most cases, inefficient programming is the main blame for unoptimized performance.
■Some operations do not need to be called with every frame. E.g. button states, check distances, AI decisions etc. Most actions can be called 10 times per sec without anyone noticing.
■Get functions are a neat concept but can be expensive. Declaring a variable as public is crude, but is faster when external access is needed.
■transform is also a get function. Cache it in a variable when used repetitively.
■To avoid cpu spikes call garbage collector at scheduled intervals with System.GC.Collect();
■Precalculate arithmetic tables where possible, or at least cache values when they don’t change (sin/cos/atan/sqrt).
코드 최적화는 성능을 두드러지게 향상시킬 수 있습니다.
대부분의 경우, 최적화가 안돼서 성능이 떨어지는 주된 원인은 프로그래밍이 (애초에) 부적절하게된 점에서 발생합니다.
■몇가지 작업들은 굳이 매 프레임마다 돌릴 필요가 없는 경우가 있습니다.
Ex) 버튼의 상태 체크, 거리 체크, AI 전략 판단 등등 이런 동작들 대부분은 초당 10번 정도만 하게끔 바꿔도 아무도 모를 겁니다.
■Get...()류의 함수들은 개념적으로는 좋습니다만, 성능적으로 (처리 비용이) 비쌀 경우가 있습니다.
public 변수 정의로 값을 빼놓는 방법은 지저분해보이긴 합니다만, 외부에서 값을 억세스할 경우 더 빠릅니다.
■transform도 알고 보면 Get...()류의 함수를 쓰고 있습니다. 반복해서 사용할 경우 변수값에다 따로 빼놓으세요.
■종종 CPU 사용량이 비정상적으로 튀는(CPU spikes) 현상을 방지하려면, System.GC.Collect()를 사용, 적절히 정해진 간격으로 가비지 컬렉터를 호출하세요.
■sin/cos/atan/sqrt등의 수학 함수는 가능한 한 미리 계산된 테이블값을 사용하거나, 최소한 자주 변하지 않는 값들을 찾아 변수에 담아놓고 불러다 사용하세요.
Graphics (그래픽)
iOS GPU is very different from your PC’s. Some well known caveats:
■Triangle count – I’ve read a lot about some hard limits like 7k but my experience shows that it doesn’t change that much in comparison to other factors. Try to keep below 10k per scene if possible.
■Memory optimization – change the target maximum texture size per iOS to the smallest possible size without losing details. I found the 256x256 or less is quite sufficient for most objects. You can also change it per each target platform so it looks detailed on PC, and saves on memory on iOS.
■Complex and multi-pass shaders are slow on iPhone’s GPU. Toon and cutout shading are examples of shaders that should be avoided if possible.
■Lighting is very expensive. In general, every light is another drawing pass for all affected objects. Use one bright directional light. Use other lights, especially spot and point, with caution. Note that additional lights have two wrongs – they take an additional draw pass per each lit item, and initial light-on calculation takes a few milliseconds of stalled application.
■Changing vertex position, normals or tangents is expensive and should not be done repetitively. Changing UV (pixel position within texture) is fast, however.
■OnGUI is called every frame, plus every event. Furthermore, it does not share materials between subsequent calls to texture or text, even when the same resource is used (e.g. 2 calls for text and its shadow). Avoid if you can.
iOS에서 사용되는 GPU는 PC에서 사용되는 것과는 많이 다릅니다.
잘 알려진 제약 사항들 몇 가지를 살펴보자면 :
■ 폴리곤 수
7,000개가 HW 한계라던지(3GS 기준인 듯 - 역주) 같은 글들을 많이 읽어봤습니다만,
경험적으로는 폴리곤 수가 다른 요인에 비해 특별히 더 중요한 영향을 끼친다고 생각되진 않습니다.
한 씬에서 10,000개 이하로 유지하기 위해 가능한 한 노력해보세요.
■ 메모리 최적화
iOS 플랫폼에서 사용할 최대 텍스쳐 사이즈값Maximum Texture Size for iOS지정을, 디테일을 잃어버리지 않는 한도에서 최대한 줄여보시기 바랍니다.
(해당 Texture의 Inspector 메뉴 하단에서, 각 빌드 플랫폼별로 Override for... 체크박스를 켜고 최대 텍스쳐 사이즈 및 포맷 지정 가능. 자세한 사항은 http://unity3d.com/support/documentation/Manual/Textures.html 위 링크에서 Per-Platform Overrides 항목 및 플랫폼별 사용 가능한 텍스쳐 포맷 설명을 참조 - 역주)
제 경우는 대부분의 오브젝트에서 최대 256x256, 또는 그 이하로도 충분했었습니다.또한 이것을 각각의 대상 플랫폼별로도 지정하실 수가 있는데 (위의 역주 참고)PC에선 디테일하게, iOS에선 메모리 사용을 줄이는 식으로 지정할 수도 있습니다.
■iPhone의 GPU상에서 복잡하고 여러번의 패스multi-pass를 거쳐야 하는 셰이더를 쓰면 느려집니다. 예를 들어 Toon 계열 셰이더라든지, Transparent/Cutout 계열 셰이더는 가능한 한 사용을 피해야 합니다.
■라이팅은 (처리 비용이) 매우 비쌉니다. 일반적으로 조명이 추가될때마다 (영향받는 모든 오브젝트들에 대한) 그리기 패스drawing pass 또한 추가가 됩니다.밝은 지향성 조명directional light 하나만 사용하세요.
다른 조명, 특히 점point 광원이나 스포트라이트를 사용할 땐 주의하시기 바랍니다.조명을 추가하는 데엔 두 가지 문제점이 있음을 기억하세요 -그 조명을 받는 모든 물체에 대해 렌더링 작업이 늘어난다는 점과,그 조명이 켜지는 시점에서 조명 초기화를 위해 몇밀리초를 더 잡아먹게 된다는 점.
■정점vertex의 위치/노말/탄젠트 값을 바꾸는 것은 (처리 비용이) 비싸며, 반복적으로 해선 안됩니다.반면, UV(텍스쳐 내에서의 픽셀 위치) 값을 바꾸는 것은 빠릅니다.
■OnGUI()는 매 프레임마다, 추가적으로 매 이벤트마다 호출됩니다. 게다가, 연속되는 OnGUI() 내에서 같은 리소스, 매터리얼을 반복 사용하더라도
이를 공유해서 최적화해준다던가 하지 않습니다.(예를 들어, 텍스트와 그 그림자를 그리면 그대로 2번의 그리기 호출2 calls이 발생) 그러니 가능한 한 사용을 피하세요.
Draw Calls(그리기 호출)
A Draw Call is one or more objects, sharing a single material on a single camera, in a single shader pass, being placed on screen.
My experience proves that the most important element to optimize is to reduce the number of draw calls, even in high-end mobile device such as iPad. Apparently the pipeline between the CPU and GPU is not as efficient as in non-mobile devices.
■Make sure Dynamic Batching is checked.
■When checked, the engine groups all objects by their shared material, up to a maximum number of vertices per batch. Make sure that member sharedMaterial is used instead of material, whenever applicable.
■Furthermore, all batched objects must share queue pass. Each camera has multiple drawing passes. If a few materials share the same pass, there is no guarantee that all objects using the same material will be batched. Therefore you can help Unity by placing a material in a particular pass by changing its pass order.
For example, shader directive Tags {“Queue” = “Transparent-1” }
will make sure that this shader is drawn right after Transparent pass. So setting Transparent-1 separates this new material from normal Transparent shaded materials, and batches all objects using this material into one pass.
Note: This trick also helps when trying to sort depths and fix Z issues.
■Most importantly: Use one material (one texture) for as many objects as you can. For example, use an icon atlas and change UV position according to the desired image.
■Alternative solution: load a font and export its texture. Place all your images on the exported font texture instead of the original letters. Then, use Text Mesh and change the letters to display the proper icon.
그리기 호출Draw Call 은 (카메라를 통해 한 프레임의 화면을 만들어내는 동안) 하나의 셰이더 패스, 하나의 매터리얼로 오브젝트를 한 번 그리는 작업의 단위를 말합니다.
(같은 셰이더/같은 매터리얼을 갖는 여러 개의 오브젝트라도 한번의 draw call 작업에서 그릴 수 있음 - 역주)
iPad같은 하이엔드급 모바일 장치에서조차, 이 그리기 호출Draw Call 수를 줄이는 일이
제 경험상 최적화에서 가장 중요한 요소라고 생각이 됩니다. 확실히 모바일 장비는 비-모바일 장비non-mobile devices에 비해 CPU와 GPU간의 파이프라인이 그리 효율적이지가 않습니다.
■동적 배칭Dynamic Batching 기능이 켜져있는가 확인하세요 (File 메뉴 > Build Settings... 메뉴 > Player Settings 버튼 >
Inspector창에서 Other Settings 항목 > Rendering 항목 밑에 Dynamic Batching 체크박스 선택.
자세한 설명은 http://unity3d.com/support/documentation/Manual/iphone-DrawCall-Batching.html 위 링크에서 Dynamic Batching 부분을 참조 - 역주)
■이것이 켜져있으면, 게임 엔진은 모든 오브젝트를 공유된 매터리얼 단위로 묶습니다.
이 경우, (스크립트에서 건드릴 땐) material 멤버 대신 sharedMaterial 멤버를 사용하도록 해야 합니다.
■나아가, 배치 처리될 모든 오브젝트all batched object는 같은 셰이더 큐 패스queue pass를 공유해야 합니다.
각각의 카메라는 여러 개의 그리기 패스drawing pass를 가지고 있습니다. 몇몇 매터리얼이 같은 그리기 패스를 공유하고 있다 하더라도, 같은 매터리얼을 사용하는 모든 오브젝트가 한번에 배치 처리된다는 보장은 없습니다.
그러므로, 매터리얼의 셰이더 패스 순서pass order를 직접 지정해줌으로써 그 매터리얼이 특정 그리기 패스 안에서 동작하도록 강제할 수 있습니다.
예를 들자면, 셰이더 명령어 Tags {"Queue" = "Transparent-1" } 을 사용하면 해당 셰이더가 Transparent pass 직후(*주1*)에 동작하도록 강제할 수 있습니다. 이렇게 Transparent-1로 셋팅하게 되면, 이 새로운 매터리얼은 기존의 Transparent 셰이더와 분리되며,
이 새로운 셰이더를 사용하는 모든 오브젝트를 묶어 한 패스 안에서 배치batch 처리하게 됩니다. 주 : 이 방법은 깊이값 소팅이나 Z값 관련 문제를 해결하는데도 도움이 됩니다.
(이 항목의 내용은 제가 셰이더를 공부 안해서 제대로 번역이 되었는지 확신이 없네요 - 역주)
■가장 중요한 사항: 가능한 한 많은 오브젝트를 한 매터리얼(한 장의 텍스쳐)로 묶어야 합니다.예를 들어, 한장의 아이콘 맵icon atlas을 만들고 필요한 상황에 따라 UV위치값을 바꿔가며 쓰는 방법이 있습니다.
■대안책: 폰트를 하나 읽어들이고 이 텍스쳐를 export합니다. 찍고싶은 이미지를 조각내서 이 export된 폰트 텍스쳐 위치에 갖다 붙입니다.
그리고, Text Mesh를 사용해서 이것들을 가져다 적절한 아이콘으로 사용합니다.
More Tips
Here are some handy non-optimization tips:
■Instead of OnGUI or GUITexture, display all GUI in a new camera.
◦Create a new camera for GUI: isometric, ignores all other layers, Depth 1 (to draw after main camera) and Don’t Clear.
◦Use Text Mesh and Mesh Renderer to draw text. Make sure that the GameObject is set to the GUI camera layer. This is a very fast and versatile to use dynamic, localized text in Unity. Text can be changed, rotated, scaled and a user-defined material can be used instead of standard font.
◦Similarly, logos and images can be displayed on boxes. The triangle cost is minimal and on this isometric camera, the side walls are culled.
When transparent image is used, either use a shader with Culling On so the back wall is removed, or place the box very close to the camera so the front wall is behind the camera and only the back wall is shown.
■White border around textures is caused when a zero-alpha color partly bleeds into a visible pixel. In this case, the RGB part of that supposedly transparent pixel is taken into effect. To fix it in Photoshop:
◦Select all zero-alpha pixels
◦Paint around the edges of the images with the edge color (the select region will protect the image)
◦Create Layar Mask -> Hide selected area.
The result is an image where the RGB part of zero-alpha pixels matches the edges of the texture and bled pixels look nice.
More tips to follow soon.
최적화와는 관계없지만 몇가지 편리한 팁들이 더 있습니다 :
■OnGUI()나 GUITexture를 사용하는 대신, 별도의 카메라로 모든 GUI를 그려주기
◦GUI를 위한 별도의 카메라를 만듭니다
: 평행isometric 카메라로 지정하고, 별도로 만든 GUI 오브젝트 레이어 이외의 모든 다른 레이어를 끄고,
(메인 카메라보다 나중에 찍도록) Depth값을 1로 주고, Clear flag를 Don't Clear로 맞추세요.
◦텍스트를 찍기 위해선 Text Mesh 와 Mesh Renderer를 사용합니다.
만들어진 GUI용 GameObject들은 별도로 만든 GUI 오브젝트 레이어 쪽으로 넣어줍니다.
이렇게 하면 유니티에서 현지화된 텍스트를 사용할때 매우 빠르고 융통성있게끔 만들 수 있습니다.
이런 덱스트는 변경 가능하고, 회전, 확대/축소할 수도 있으며 기본 폰트대신 사용자 정의된 매터리얼로 대치할수도 있습니다.
◦비슷한 형태로, 로고나 이미지는 박스를 이용해 찍을 수 있습니다.
평행isometric 카메라 상에서 상각 폴리곤을 찍는 처리비용은 거의 미미하며, 불필요한 옆면 등은 알아서 무시됩니다.
투명값을 가진 이미지를 사용할때는, 뒷면이 없어지게끔 컬링이 적용된 셰이더를 사용하거나 박스 자체를 카메라에 아주 가깝게 가져와서, 박스 앞면은 카메라 평면 뒤로 보내고 박스 뒷면만 보이게 합니다.
■(투명값을 갖는 텍스쳐의 경우) 텍스쳐 테두리의 흰색 띠가 보일 경우는 알파값 0를 가진 픽셀 색이 주변으로 일부 번지기 때문에 발생합니다.
이 경우, 테두리의 주변 RGB값들이 영향을 미치고 있는 것인데, 포토샵에서 이를 수정하려면 :
◦알파값 0 인 배경 픽셀들을 전부 선택한다
◦이미지 테두리를 따라 원하는 경계선 색을 다 칠해준다 (이미지 안쪽은 선택 영역이 보호해준다)
◦Layar Mask를 만들어, 방금 칠해준 선택 영역을 hide 시킨다
결과적으로 알파값이 0인 픽셀들도 원하는 테두리 색을 가지게 되어 보기 좋게 섞여진다.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*주1*
원문에는 will make sure that this shader is drawn right after Transparent pass. 라고 되어 있어서
원 저자의 의도대로 'Transparent pass 직후' 라고 번역이 되었습니다만...
http://unity3d.com/support/documentation/Components/SL-SubshaderTags.html 을 보시면, 각 렌더 패스마다 내부적으로 1000단위의 숫자가 매겨져 있고, Transparent의 값이 3000이니
저 Transparent-1 패스의 경우는 2999가 되어, 실제론 'Transparent pass 직전'이 맞습니다.
하지만 원문 내용은 Transparent pass 앞이냐 뒤냐가 중요한게 아니고, 저런 식으로 태그를 부여해서 원하는 drawing 작업을 분리된 하나의 drawing pass로 통합하는 방법을 보여주는 것이니
틀린 내용이라 하더라도 원 저자의 문맥대로 일단 번역하고 별도로 각주를 남깁니다.
* 원문에 이렇게 애매모호(?)한 부분이 두어 군데 더 보입니다만, 마찬가지로 패스... *
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
END
설정
트랙백
댓글
글
아.. 팁에 있는 내용들을 보면서 대충 정리 한건데.. 곧 책이 온다... ^^ 좋았어!!!
1. Rendering Components
This group contains all Components that have to do with rendering in-game and user interface elements. Lighting and special effects are also included in this group.
해당 그룹에 속한 컴포넌트들은 게임안의 렌더링과 사용자 인터페이스 요소안에 쓰여지는 것을 이란다. 빛과 특별한 효과들은 모두 이 그룹에 포함되어 있데유
1) Camera : http://unity3d.com/support/documentation/Components/class-Camera.html
**새로운 프로젝트를 만들 때 포함된 기본 asset 패키지에 도움이 될만한 카메라 스크립트들(메뉴의 Components->Camera-Control)
2) Flare Layer(Camera 연계) : http://unity3d.com/support/documentation/Components/class-FlareLayer.html
3) GUILayer (Camera 연계): http://unity3d.com/support/documentation/Components/class-GUILayer.html
4) GUI Text : http://unity3d.com/support/documentation/Components/class-GuiText.html
5) GUI Texture : http://unity3d.com/support/documentation/Components/class-GuiTexture.html
6) Halo (후광) : http://unity3d.com/support/documentation/Components/class-Halo.html
7) Halo Layer(Camera 연계) : http://unity3d.com/support/documentation/Components/class-HaloLayer.html
8) Lens Flare : http://unity3d.com/support/documentation/Components/class-LensFlare.html
9) Light : http://unity3d.com/support/documentation/Components/class-Light.html
10) Projector : http://unity3d.com/support/documentation/Components/class-Projector.html
11) Sky box : http://unity3d.com/support/documentation/Components/class-Skybox.html
2. Movie Texture ( tex·ture 미국∙영국 [|tekstʃə(직물의) 감촉[질감])
http://unity3d.com/support/documentation/Components/class-MovieTexture.html
==> 요건 지난번에 설명을 한것 같기도 하고.. Pro 버전에서만 지원을 한다... texture를 사용해서 적용하면 되는 것 뭐 어려운것 없다.. play 와 stop 정도만 ^^;;
3. Game Object
http://unity3d.com/support/documentation/Components/class-GameObject.html
게임 오브젝트들은 하나의 저장고 !!
라이트 매핑된 섬이라든가 물리적인 효과가 적용된 자동차와 같은 여러 다른 조각들을 담을 수 있는 빈 박스와 같습니다. 이 각각의 조각들은 구성요소(Componets)라 불립니다. (cf..스크립트도 구성요소로 볼수 있다는 점도 기억하시길 바랍니다. 스크립트 내에 모든 가변요소들은 게임 오브젝트의 인스펙터상에 편집이나 링크가 가능하구요....)
어떤 오브젝트를 만들고 싶은가에 따라 서로 다른 구성요소의 조합을 게임 오브젝트에 더 해 주게 됩니다. 게임 오브젝트를 하나의 빈 과자틀이라 가정하고 구성요소들을 게임이라는 과자를 굽는데 필요한 다양한 재료라고 생각하면 됩니다.
모든 게임 Object에는 Object Name, Tag, Layer, Transform Component의 구성요소를 가지고 있다.
이중에 Transform Component는 게임 오브젝트의 Position, Rotation , Scale ...필수적인 성질을 정의
Transform Compoonet는 유니티의 편집기능에 이용되는 페어런팅(Parenting - 상하위 관계를 형성하는 것을 의미)도 가능하게 합니다.
* Transform Component
http://unity3d.com/support/documentation/Components/class-Transform.html
** shift + Ctrl + N : Game Object 생성 단축키
4. Prefabs ( pre·fab 미국∙영국 [|pri:fӕb] 조립식 건물 )
http://unity3d.com/support/documentation/Manual/Prefabs.html
Prefabs은 씬에서 재사용될 수 있는 게임오브젝트와 구성요소의 집합체입니다.
몇 개의 동일한 오브젝트들이 하나의 Prefab에서 만들어질 수 있습니다. (이를 instancing이라 합니다.)
나무로 예를 들어 보겠습니다.
나무 Prefab을 만든다면 몇 개의 동일한 나무들을 복사하여(instance) 당신의 씬에 넣는 것입니다.
모든 나무들은 Prefab에 링크되어 있기 때문에 Prefab에 적용되는 모든 변화들은 자동적으로 모든 복사된 나무들에게도(tree instance) 적용이 됩니다.
그렇기 때문에 매시나 재질이나 기타 다른 사항들을 변경하기 원한다면 Prefab만 한 번 바꿔주면 됩니다.
반대로 복사된 오브젝트를 수정한 뒤 메인메뉴의 GameObject->Apply Changes to Prefab을 통해서도 가능합니다. 이 작업은 asset을 설정해주고 업데이트 하는데 많은 시간을 절약할 수 있게 해줍니다.
다수의 구성요소들과 하위게임오브젝트를 포함하는 게임오브젝트가 있다면 최상위의 게임오브젝트의 Prefab을 만들고 그 모든 집합체를 재사용할 수도 있습니다.
Prefab을 게임오브젝트의 구조에 대한 청사진으로 생각하십시오. 모든 Prefab의 복제는 청사진과 동일합니다. 그렇기 때문에 청사진이 업데이트 되면 Prefab의 복제도 마찬가지로 업데이트 됩니다. Prefab의 복제 중 하나를 변경하고 그 변경사항을 청사진에 적용함으로써 Prefab자체를 업데이트 할 수 있는 다양한 방법들이 있습니다.
5. Scene
게임의 오브젝트들을 포함( 배경,장애물 , 장식들) 배치
메인 메뉴를 만들거나, 개별 레벨을 만드는데 사용
6. Asset ( asset미국·영국 [|ӕset] : [명사]~ (to sb/sth)자산(이 되는 사람・물건) )
7. Asset 작업 과정
1) 3D 모델링 프로그램을 이용해서 asset 의 러프 버전(초기 모델의 의미) 제작
2) import : Unity Asset 폴더에 저장을 하면, 자동으로 임포트
3) import Setting
4) Scene에 Asset 추가 : Mesh 를 프로젝트 뷰에서 클릭하여 Hierarchy 나 Scene 뷰에 드래그 추가
5) 다른 Asset 함께 위치
- texture 는 material에 적용
- material은 Game Object에 적용 (with an Mesh Render Component)
- Animation은 Game Object에 적용(with an Animation Component)
- A sound file is applied to a Game Object (with an Audio Source Component)
6) Prefab 만들기
7) Assets Update
* Mesh Render 구성요소를 지닌 게임오브젝트를 만들고 있음을 의미
텍스쳐 나 사운드 파일로 작업 중이라면, 이미 씬이나 프로젝트에 존재하는 게임오브젝트에 그것을 추가해 줘야 함.
8. Script 호출 순서
http://unity3d.com/support/documentation/ScriptReference/MonoBehaviour.html
Awake => Start => Update
Awake : 이 스크립트를 사용하는 인스턴스들이 Start하기전에 무조건 딱한번 실행됩니다.
Start : 현재 인스턴스가 활성화될때 Update 바로 직전 딱한번 호출됩니다.
스크립트를 사용하는 인스턴스가 1,2 가 있다면
Awake1 - Awake2 - Start1 - Start2 (0)
Awake1 - Start1 - Awake2 - Start2 (x)
오늘은 여기까지
설정
트랙백
댓글
글
저작권 문제가 있지는 않을것 같지만.. 혹여나.. 문제가 된다면.. 말씀해주세용
해당글 : http://www.unity3dkorea.com/bbs/board.php?bo_table=m04_2&wr_id=13&page=7
http://www.willgoldstone.com/downloads/unity
해당 폴더에 강좌에 필요한 소스 파일이 있답니다. ^^
1. Sound & Object Collection 1탄
Sound를 적용하는 방법을 하는데
Audio > Audio Source 를 적용한다.
Loop 도 적용하구..
Volcano 쪽도 적용하는데, 적용하려는 원본 파일이...
3D 사운드..볼륨이 제한이 되어 있더군요..
Unity가 업그레이드 되면서.. 적용방법이 변경이 된것 같습니다.
2. Sound & Object Collection 2탄
우선 보석 먹기를 할것 같습니다.
하단에 글씨를 넣구요... GUI TEXT
그다음 아래와 같은 스크립트를 추가 해 줍시다.
var prefix = "Gems: ";
var suffix = "/3";
guiText.text = prefix + GemCollect.Count + suffix;
}
Gem 를 만들었답니다..(Cinema 4D에서 제작해서.. 이동)
3. Sound & Object Collection 3탄
그다음에는 Material 를 추가하지요... 색상도 넣고..
shader 는 FX > Glass > Stained BumpDistorted Specular 로 설정하는데.. 잉 사라지넹 ㅎ
그리고 Tag 도 지정해 줍시다.
4. Sound & Object Collection 4탄
자.. 이번에는 Particle System 를 추가 합니다.
Gem 에 다가 추가하고... Gem 이 돌아가게 스크립트도 추가 하고..
그럽시다..
var speed : float = 50.0;
function Update () {
var spinAmount = Time.deltaTime * speed;
transform.Rotate(0, spinAmount, 0);
}
Min Size : 폴리곤 최저 크기
Max Size : 폴리곤 최고 크기
(최저~최고로 랜덤으로 나온다.)
Min Energy : 내품었을때부터 사라지는데 걸리는 시간 (최저)
Max Energy : 내품었을때부터 사라지는데 걸리는 시간 (최고)
Min Emission : 초당 내뿜는 폴리곤 수 (최저)
Max Emission : 초당 내뿜는 폴리곤 수 (최고)
5. Sound & Object Collection 4탄
Gem를 Collection 하는 방법에 대해서 논의한다.
static var Count : int = 0;
var CollectSound : AudioClip;
function OnControllerColliderHit(hit:ControllerColliderHit){
if(hit.gameObject.tag == "gem"){
Destroy(hit.gameObject);
Count++;
audio.PlayOneShot(CollectSound);
}
}
걷는 스크립트 ...
var speed = 6.0;
var jumpSpeed = 8.0;
var gravity = 20.0;
private var moveDirection = Vector3.zero;
private var grounded : boolean = false;
function FixedUpdate() {
if (grounded) {
// We are grounded, so recalculate movedirection directly from axes
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
if (Input.GetButton ("Jump")) {
moveDirection.y = jumpSpeed * 10;
}
}
// Apply gravity
moveDirection.y -= gravity * Time.deltaTime;
// Move the controller
var controller : CharacterController = GetComponent(CharacterController);
var flags = controller.Move(moveDirection * Time.deltaTime);
grounded = (flags & CollisionFlags.CollidedBelow) != 0;
}
@script RequireComponent(CharacterController)
마우스를 통해 보는 스크립트
using UnityEngine;
using System.Collections;
/// MouseLook rotates the transform based on the mouse delta.
/// Minimum and Maximum values can be used to constrain the possible rotation
/// To make an FPS style character:
/// - Create a capsule.
/// - Add a rigid body to the capsule
/// - Add the MouseLook script to the capsule.
/// -> Set the mouse look to use LookX. (You want to only turn character but not tilt it)
/// - Add FPSWalker script to the capsule
/// - Create a camera. Make the camera a child of the capsule. Reset it's transform.
/// - Add a MouseLook script to the camera.
/// -> Set the mouse look to use LookY. (You want the camera to tilt up and down like a head. The character already turns.)
[AddComponentMenu("Camera-Control/Mouse Look")]
public class MouseLook : MonoBehaviour {
public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityX = 15F;
public float sensitivityY = 15F;
public float minimumX = -360F;
public float maximumX = 360F;
public float minimumY = -60F;
public float maximumY = 60F;
float rotationX = 0F;
float rotationY = 0F;
Quaternion originalRotation;
void Update ()
{
if (axes == RotationAxes.MouseXAndY)
{
// Read the mouse input axis
rotationX += Input.GetAxis("Mouse X") * sensitivityX;
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationX = ClampAngle (rotationX, minimumX, maximumX);
rotationY = ClampAngle (rotationY, minimumY, maximumY);
Quaternion xQuaternion = Quaternion.AngleAxis (rotationX, Vector3.up);
Quaternion yQuaternion = Quaternion.AngleAxis (rotationY, Vector3.left);
transform.localRotation = originalRotation * xQuaternion * yQuaternion;
}
else if (axes == RotationAxes.MouseX)
{
rotationX += Input.GetAxis("Mouse X") * sensitivityX;
rotationX = ClampAngle (rotationX, minimumX, maximumX);
Quaternion xQuaternion = Quaternion.AngleAxis (rotationX, Vector3.up);
transform.localRotation = originalRotation * xQuaternion;
}
else
{
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = ClampAngle (rotationY, minimumY, maximumY);
Quaternion yQuaternion = Quaternion.AngleAxis (rotationY, Vector3.left);
transform.localRotation = originalRotation * yQuaternion;
}
}
void Start ()
{
// Make the rigid body not change rotation
if (rigidbody)
rigidbody.freezeRotation = true;
originalRotation = transform.localRotation;
}
public static float ClampAngle (float angle, float min, float max)
{
if (angle < -360F)
angle += 360F;
if (angle > 360F)
angle -= 360F;
return Mathf.Clamp (angle, min, max);
}
}
음.. 조금씩 감이 잡혀 오는 듯한 느낌이요.. ^^
설정
트랙백
댓글
글
GUI 에 관련하여 동영상을 보면서 숙지 하였습니다.
본 자료는 용량이 좀 크네용;;; 어디서 얻은 자료인가 하면...
http://www.unity-tutorials.com/
이곳입니다.... 유료라서 모든 강좌를 습득하기는 어렵지만.. 간단한 개인정보를 입력하면,
무료강좌 2개를 제공해 주네요..
1. 스크립트 기초
기본적으로 카메라 화면 이동을 스크립트로 구현하여, 키보드를 이용해 움직이는 예제 입니다.
var moveSpeed : float = 10;
function Update(){
if(Input.GetKey(KeyCode.UpArrow)){
transform.Translate(Vector3(0,moveSpeed * Time.deltaTime, 0));
}else {
if(Input.GetKey(KeyCode.DownArrow)){
transform.Translate(Vector3(0, -moveSpeed * Time.deltaTime, 0));
}
}
if(Input.GetKey(KeyCode.RightArrow)){
transform.Translate(Vector3(moveSpeed*Time.deltaTime,0,0));
}else{
if(Input.GetKey(KeyCode.LeftArrow)){
transform.Translate(Vector3(-moveSpeed * Time.deltaTime, 0 ,0));
}
}
}
function Start()
{
while(true)
{
Debug.Log(transform.position.ToString());
yield;
}
}
2. GUI 관련
var mainMenu : boolean = false;
var options : boolean = false;
var backTexture : Texture;
var menuStyle : GUIStyle;
var silderTextStyle : GUIStyle;
var soundVolume : float = 0;
var musicVolume : float = 0;
var voiceVolume : float = 0;
function Start(){
soundVolume = PlayerPrefs.GetFloat("sound", 0);
musicVolume = PlayerPrefs.GetFloat("music", 0);
voiceVolume = PlayerPrefs.GetFloat("voice", 0);
}
function OnGUI()
{
if(mainMenu || options){
GUI.DrawTexture(Rect(0,0,Screen.width,Screen.height), backTexture);
if(mainMenu){
GUI.Button(Rect(Screen.width *.4 , Screen.height * .05 , Screen.width * .2 , Screen.height * .1), "Main Menu" , menuStyle);
if(GUI.Button(Rect(Screen.width * .4 , Screen.height * .4 , Screen.width *.2 , Screen.height * .1),"Play Game")){
mainMenu = false;
// gameManager.Play();
}
if(GUI.Button(Rect(Screen.width * .4 , Screen.height * .5 , Screen.width *.2 , Screen.height * .1),"Options")){
mainMenu = false;
options = true;
}
}else if(options){
GUI.Button(Rect(Screen.width *.4 , Screen.height * .05 , Screen.width * .2 , Screen.height * .1), "Options" , menuStyle);
if(GUI.Button(Rect(Screen.width * .4 , Screen.height * .8 , Screen.width *.2 , Screen.height * .1),"Back")){
mainMenu = true;
options = false;
PlayerPrefs.SetFloat("sound", soundVolume);
PlayerPrefs.SetFloat("music", musicVolume);
PlayerPrefs.SetFloat("voice", voiceVolume);
}
GUI.Window(0,Rect(Screen.width * .3 , Screen.height * .3 , Screen.width * .4 , Screen.height * .4), OptionsWindow, "");
}
}
}
function OptionsWindow(WindowID : int)
{
soundVolume = GUI.HorizontalSlider(Rect(Screen.width * .05 , Screen.height * .05 , Screen.width * .3 , Screen.height * .05 ) , soundVolume, 0 ,1);
GUI.Label(Rect(Screen.width * .05 , Screen.height * .015 , Screen.width * .3 , Screen.height * .04 ) , "Sound Volume" ,silderTextStyle);
musicVolume = GUI.HorizontalSlider(Rect(Screen.width * .05 , Screen.height * .15 , Screen.width * .3 , Screen.height * .05 ) , musicVolume, 0 ,1);
GUI.Label(Rect(Screen.width * .05 , Screen.height * .115 , Screen.width * .3 , Screen.height * .04 ) , "Music Volume" ,silderTextStyle);
voiceVolume = GUI.HorizontalSlider(Rect(Screen.width * .05 , Screen.height * .25 , Screen.width * .3 , Screen.height * .05 ) , voiceVolume, 0 ,1);
GUI.Label(Rect(Screen.width * .05 , Screen.height * .215 , Screen.width * .3 , Screen.height * .04 ) , "Voice Volume" ,silderTextStyle);
}
아래와 같이 메뉴가 구성이 됩니다.
음..게임 제작할때.. 유용하게 사용도될지, 아직 모르겠지만.. 그래도 알면 도움이 되지 않을까용?
좀더 찾아보니.. 상용 GUI 제품들을 쓰더군요.. 헐..
EZ GUI : http://www.anbsoft.com/middleware/ezgui/
(Quad UI)베타 버전 다운로드시 해당 패키지는 영문폴더에 저장후에 Import 해야 한다고 하니.. 함 적용을 해봐야 겠군요
설정
트랙백
댓글
글
유니티를 처음 접하기 전에.. 음.. 뭐라고 할까나??
Javascript 냐 C# 이나 선택의 귀로에 서게 되는데...
외국 강좌들을 몇가지 보다보니.. javascript 로 많이들 보여준당..
영어 공부도 좀 할겸해서 몽땅 옮겨 놓았다.
요 사람이 정리 해 놓은 거랍니다.. 저랑은 아무 상관이 없는 분이죠..URL : http://forum.unity3d.com/threads/34015-Newbie-guide-to-Unity-Javascript-(long)
** Text in RED applies to Unity iPhone users only
1. 변수 VARIABLES
Think of a variable as a container that holds something.
You can choose to name a variable anything you wish, as long as it contains no spaces, starts with a letter (preferably lower case), contains only letters, numbers, or underscores, and is not a reserved keyword.
Use the keyword 'var' to create a variable. Let's call our first one 'box'.
var box;
There you go, you've declared your first variable! If you're wondering about the semicolon at the end, statements (commands) in Javascript must end in a semicolon.
iPhone programmers, if you declare a variable without setting it to a value, you must state what type the variable is, in this case String. Common types include String, int, float, boolean, and Array. Note that proper capitalization is necessary!
var box : String;
Of course, our box is empty, so let's set it to a value by adding the following line:
box = "apple";
Now our box contains a text string (variable type), which happens to be "apple".
Note that you can declare your variable and set it to a value in the same statement:
var box = "apple";
But once it's declared, you can't declare it again.
You can, however, change it to another value (as long as the new value is the same type as the original).
box = "orange";
In addition to text strings, variables can hold numbers:
var number = 10;
This is an integer (int), which means whole numbers only... no decimal places.
But we could also do a floating point number (float), which has decimal places:
var myFloat = 10.5;
Variables can also contain booleans. A boolean is simply a true/false value:
var gameOver = true;
We'll discuss these more later.
Notice that a variable can normally only contain one thing at a time. But we can make a variable that contains multiple things, by creating an array:
var applePie = Array("apple", "brown sugar", "butter", "pie crust");
This variable contains everything you need to make an apple pie!
If we wanted to view the contents of applePie, we could output it to the Unity console using the Debug command. Add this line to the code above:
Debug.Log(applePie);
On play, the console should display:
apple,brown sugar,butter,pie crust
To access a single element (item) from an array, we can access it thru its index (position in array). This may seem confusing, but indexes start at 0. So index 0 is actually the first element in the array.
var applePie = Array("apple", "brown sugar", "butter", "pie crust");
var item1 = applePie[0];
Debug.Log(item1);
You can actually use indexing with Strings as well. The following code displays the first character of "hello", the letter 'h':
var myString = "hello";
Debug.Log(myString[0]);
Now lets alter our variables in other ways.
We can add variables:
var number1 = 10;
var number2 = 11;
var total = number1 + number2;
Debug.Log(total);
If you add an int (integer) to a float (floating point number) the result becomes a float:
var number1 = 100;
var total = number1 + 1.5;
Debug.Log(total);
Obviously, we can also subtract/divide/multiply ints and floats.
Less obvious, we can also 'add' strings. This merges them together:
var string1 = "apple";
var string2 = "cider";
var combo = string1 + string2;
Debug.Log(combo);
If we add a number to a string the result becomes a string.
We can also multiply strings.
var greeting = "howdy";
Debug.Log(greeting * 3);
Unfortunately, we can't divide or subtract strings. There are ways to split strings and remove parts of strings, but that is a more advanced topic.
Let's wrap up our discussion on variables with incrementing numbers (changing their value by a set amount).
First, declare a variable and set it to 1:
var number = 1;
We can increment numbers various ways.
number = number + 1;
The above adds 1 to our number, and it becomes 2.
But programmers are lazy, and decided this was too long. So they abbreviated it to:
number += 1;
This is simply shorthand for number = number + 1;
But guess what? Lazy programmers decided even THIS was to long, and shortened it to:
number ++;
Use whichever makes most sense to you, they all do the same thing! But note that if you choose to increment by a value other than 1, ++ won't work.
++ is shorthand for += 1 only.
You can also do the same with subtraction:
number --;
But for division and multiplication, you must use one of the longer forms:
number = number/2;
number *= 2;
Note that an asterisk means multiply, a slash means divide.
2. 조건문 IF STATEMENTS
If statements are conditional statements. If a condition evaluates as true, do something.
We can do a comparison of two values by using two equal signs, ==
"number == 10" evaluates as true if our number variable equals 10, otherwise it evaluates as false.
Note: it's important to remember to use two equal signs when comparing variables/values, but one equal sign when setting a variable to a value!
The following creates a variable and sets it to true, checks to see if the variable equals true, and if so prints a text string to the console:
var gameStarted = true;
if (gameStarted == true)
Debug.Log("Game has started");
The above is actually redundant, since our variable 'gameStarted' is a boolean. There is no reason to check "if true equals true", just check "if true":
var gameStarted = true;
if (gameStarted)
Debug.Log("Game has started");
If you're wondering why I didn't put a semicolon behind if (gameStarted), it's because technically it is only the first half of the statement. I could have written it like so:
if (gameStarted) Debug.Log("Game has started");
I could have also written it this way:
if (gameStarted){
Debug.Log("Game has started");
}
Those brackets represent a block of code, and tell the if statement to execute anything in between... if the condition is true!
When if contains only one statement to execute, the brackets are optional. But if it contains more than one statement, you MUST use the brackets! Note that semicolons are not needed after brackets.
var gameStarted = false;
If (gameStarted == false){
gameStarted = true;
Debug.Log("I just started the game");
}
Read the second line of code above. Remember those lazy programmers? They don't want to write
if (gameStarted == false)
When they can just write:
If (not gameStarted)
But you know what? Why write 'not' when I can shorten that too?
if (! gameStarted)
Yes, an exclamation point means 'not' to lazy programmers!
You can also combine this with equals, where it means "not equals":
var answer = 1;
if (answer != 42) Debug.Log("Wrong question!");
You can also check for greater than or less than:
var age = 18;
if (age > 18)
Debug.Log("old enough");
else if (age < 18)
Debug.Log("jailbait");
else
Debug.Log("exactly 18");
Notice the 'else if' and 'else' keywords? if the first if statement condition fails (evaluates as false), it then checks the condition under else if. If that one fails, it will check the next else if (if one is available), and finally if all conditions fail, it executes the statement under else. Again, if the 'if', 'else if', or 'else' statements contain more than one statement, each block of code must be separated by brackets.
You can also check for multiple conditions in a single statement:
if (age >= 21 && sex == "female")
buyDrink = true;
Above, we introduced greater than or equal to >= and the AND operator, which is two ampersand characters: &&. If both conditions are true, the statement is executed. If even one is false, the statement is not.
Note: if you want to run the above code, remember to create variables for age (int), sex (String), and buyDrink (boolean) first!
if (engine == "Unity" || developer == "friend")
buyGame = true;
Above, we used the OR operator, which is two pipe characters: ||. If either condition is true, the statement is executed. If both are false, the statement is not.
Note: if you want to run the above code, remember to create variables for engine (String), developer (String), and buyGame (boolean) first!
If can also be used with the keyword 'in'. This is generally used with Arrays:
var names = Array("max", "rick", "joe");
if ("joe" in names) Debug.Log("Found Joe!");
3. 순환문 LOOPING
Looping allows you to repeat commands a certain amount of times, usually until some condition is met.
What if you wanted to increment a number and display the results to the console?
You could do it this way:
var number = 0;
number += 1;
Debug.Log(number);
number += 1;
Debug.Log(number);
number += 1;
Debug.Log(number);
And so on... but this is redundant, and there is nothing lazy programmers hate more than rewriting the same code over and over!
So lets use a For Loop:
var number = 0;
for (i=1; i<=10; i++){
number += 1;
Debug.Log(number);
}
Okay, that for statement on the second line may look a little confusing. But it's pretty simple actually.
i=1 -created a temporary variable i and set it to 1. Note that you don't need to use var to declare it, it's implied.
i<=10 -how long to run the loop. In that case, continue to run while i is less than or equal to 10.
i++ -how to increment loop. In this case, we are incrementing by 1, so we use the i++, shorthand for i+=1
If we're just printing 1 thru 10, our code above could be shortened. We don't really need the number variable:
for (i=1; i<=10; i++)
Debug.Log(i);
Just like if statements, brackets are optional when there is only one statement to execute. Talk about beating a dead horse...
We can also count backwards:
for (i=10; i>0; i--)
Debug.Log(i);
Or print all even numbers between 1 and 10:
for (i=2; i<=10; i+=2)
Debug.Log(i);
We could also use a While loop, an alternative to For statements.
While executes repeatedly until a condition is true.
var number = 0;
while (number < 10){
number ++;
Debug.Log(number);
}
While loops are most useful when used with booleans. Just make sure the escape condition is eventually met, or you'll be stuck in an infinite loop and the game will most likely crash!
var playerJumping = true;
var counter = 0;
while (playerJumping){
//do jump stuff
counter += 1;
if (counter > 100) playerJumping = false;
}
Debug.Log("While loop ended");
Notice the fourth line of code above? The one that starts with two slashes? This means the text afterwards is a comment, and will not be executed. Comments are useful for noting how your code works for yourself or others, for putting in placeholder text to be replaced later (as above), or for commenting out sections of your code for debug purposes.
4. 함수 FUNCTIONS
If you thought loops were a time saver, wait until you find out about functions!
Functions allow you to execute a whole bunch of statements in a single command.
But lets keep things simple at first. Lets define (create) a function that simply displays "Hello world" on the console.
function SayHello(){
Debug.Log("Hello world");
}
To execute, or 'call' this function, simply type:
SayHello();
Note the parenthesis after our function. They are required, both when we define our function and call it. Also note that our function name is capitalized. It doesn't have to be, but capitalizing function names is the norm in Unity.
What if we wanted a function to say different things? We can pass a value, or argument, to the function:
function Say(text){
Debug.Log(text);
}
Above, text is the argument, a temporary variable that can be used within the function only.
iPhone programmers, you should also state what type the argument is, in this case String.
function Say(text : String){
Now when we call our function, we have to provide an argument:
Say("Functions are cool!");
We can also pass variables:
var mytext = "I want a pizza";
Say(mytext);
Another useful thing functions can do is return a value. The following function checks to see if a number is even and if so it returns true, else it returns false:
function EvenNumber(number){
//iPhone programmers, remember to add type to arg (number : int);
if (number % 2 == 0)
// NOTE: % is the mod operator. It gets the remainder of number divided by 2
return true;
else
return false;
}
var num = 10;
if ( EvenNumber(num) )
Debug.Log("Number " + num + " is even");
When the return command is executed in a function, the function is immediately exited (stops running). Returns don't have to return a value:
function Update(){
if (!gameStarted) return; //exit function
}
The Update() function above is one of the main functions in Unity. You do not have to call it manually, it gets called automatically every frame.
5. 오버로딩 OVERLOADING FUNCTIONS
Functions can be overloaded. Sounds complicated, but it's really quite simple. It means you can have multiple versions of a function that handles different types of arguments, or different numbers of arguments.
To handle different types of arguments, simply use the colon : to state the type of argument being passed. Common types include String, int, float, boolean, and Array. Note that proper capitalization is necessary!
Code:
function PrintType(item : String){
Debug.Log("I'm a string, type String");
}
function PrintType(item : int){
Debug.Log("I'm an integer, type int");
}
function PrintType(item : float){
Debug.Log("I'm a float, type float");
}
function PrintType(item : boolean){
Debug.Log("I'm a boolean, type boolean");
}
function PrintType(item : Array){
Debug.Log("I'm an array, type Array");
}
function PrintType(item: GameObject){ //catches everything else
Debug.Log("I'm something else");
}
function PrintType(){
Debug.Log("You forgot to supply an argument!");
}
PrintType();
PrintType("hello");
PrintType(true);
6. 클래스 CLASSES
So variables have different types, such as String and int. But what if you need a new type that does something different?
Classes are simply new types that YOU create.
class Person{
var name;
var career;
}
//Create objects of type Person
var john = Person();
john.name = "John Smith";
john.career = "doctor";
Debug.Log(john.name + " is a " + john.career);
The above class has two class variables, or properties, name and career. You access them by typing the name of the instance (in this case, John) followed by a period and the name of the property.
You can also pass arguments when creating instances of a class. You do this by creating a constructor, which is a special function that is automatically called whenever a new instance of your class is created. This function has the same name as your class, and is used to initialize the class:
class Animal{
var name;
function Animal(n : String){ //this is the constructor
name = n;
Debug.Log(name + " was born!");
}
}
cat = Animal("Whiskers"); //var keyword is optional when creating instances!
Classes can have regular functions as well. Class functions are sometimes called methods. Again, you access these by typing the name of your instance followed by a period and the function name (don't forget the parenthesis). This is useful for having instances interact with one another:
class Person{
var name : String;
function Person(n : String){
name = n;
}
function kiss(p : Person){
Debug.Log(name + " kissed " + p.name + "!");
}
}
jenni = Person("Jenni");
bob = Person("Bob");
jenni.kiss(bob);
7. 상속 INHERITANCE
Classes can inherit or extend (add functionality to) another class. The class that gets inherited from is usually called the base class or the parent class. The extended class is also called the child class or the derived class.
This will be our base class:
class Person{
var name : String;
function Person(n : String){ //constructor
name = n;
}
function Walk(){ //class function
Debug.Log(name + " is walking");
}
}
To extend this class, create a new class with the keyword 'extends':
class Woman extends Person{
var sex : String;
function Woman(n : String){ //constructor
super(n); //calls the original constructor and sets name
sex = "female"; //adds additional functionality to the extended class
}
function Walk(){
super.Walk(); //calls the original function
Debug.Log("And she is so sexy!"); //adds additional functionality to the extended class
}
}
Note that we can access the base/parent class properties and functions by using the keyword 'super'.
If we create an instance of Woman and call function Walk(), both the parent and child function are called:
amanda = Woman("Amanda");
amanda.Walk();
8 .BUILT IN TYPES AND PROPERTIES
Now you're probably wondering, "if classes, the types I create, can have properties and functions, why can't the built in types"?
They do, actually.
To convert an int to a String, use the built-in function ToString():
var number = 10;
var text = number.ToString();
To get the length of an Array (or a String), use the built-in property length:
var animals = Array("cat", "dog", "pig", "dolphin", "chimpanzee");
var total = animals.length;
You can use this in a for loop. Add the following two lines to the code above:
for (i=0; i<animals.length; i++){
Debug.Log(animals[i]);
}
This displays the contents of our array, one item at a time.
To add an item to an Array, use the function Add():
animals.Add("lemur");
To split a String into an array, use the function Split():
var sentence = "The quick brown fox jumped over the lazy dog";
var words = sentence.Split(" "[0]);
Debug.Log(Array(words));
To get a part of a String, use the function Substring(). Substring takes two arguments, the starting index and the ending index:
var sentence = "The quick brown fox jumped over the lazy dog";
var firstHalf = sentence.Substring(0, 19);
Debug.Log(firstHalf);
To capitalize a text string, use the function ToUpper();
var mission = "go make cool games!";
Debug.Log( mission.ToUpper() );
As you might expect, there is also a ToLower() function.
Debug.Log( ("THE END").ToLower() );
아래는 가이드 이고, 다운받아서 보시면 도움이 되지요~
Intro to the Unity Interface:
http://download.unity3d.com/support/...Essentials.pdf
Intro to Scripting with Unity - read sections labeled "Our first script", and "Attaching the script".
http://download.unity3d.com/support/...20Tutorial.pdf
설정
트랙백
댓글
글
Unity3DKorea 사이트에 있는 강좌를 이번주는 파고들어 볼 예정이다..
** 중요한것은 해당 동영상은 Unity3dKorea 에 가셔서 회원가입하시고 보시는 것이 좋을것 같습니다.
개인적인 의견으로는 아직 제가 익혀가는 단계이기 때문에... 본 강좌를 보면서 대충 흐름을 파악하기 위해서 보는 것이지, 완벽함을 추구하고자 보는 건 아닙니다.
(Unity 버전도 낮아서.. 싱크가 제대로 안맞네요... @.@, 특히 Cinema 4D까지 알아야 하니 @.@)
해당글 : http://www.unity3dkorea.com/bbs/board.php?bo_table=m04_2&wr_id=13&page=7
http://www.willgoldstone.com/downloads/unity
해당 폴더에 강좌에 필요한 소스 파일이 있답니다. ^^
1. Cinema4D Animation & Interaction 1탄
우선 Cinema 4D 를 다운 받으셔야 합니다.
저는 돈이 없는 관계로... 불법 다운로드를 한것은 아니고,
구글링을 통해 다운로드를 받았습니다.
42일간 프리웨어로써 사용가능함에 따라.. 42일만 사용하고.. 음 돈주고 살지?? 모르겠지만.
강좌 내용은 소스를 한번 열고, 폴더별로 구분해서 설명을 해주십니다.
그리고 Cinema4D 가 설치되어 있다는 가정하에..
Cinema4D에 대해서 화면 설명을 간략히 영어로 쫘~~~악 늘어 주십니다.
2. Cinema4D Animation & Interaction 2탄
Cinema 4D 에서 열심히 집을 만들어 보는 군요..
강좌에 설명이 아주 자세히 나오니.. 보고 따라하면 될것 같습니다.
오브젝트에서 합치고 빼고, 오브젝트 내에 모델링 boolean 도 연동해서 집틀과 문을 만드는데 까지 입니다.
3. Cinema4D Animation & Interaction 3탄
지붕으로 만들어 줍니다.
그리고 이제 각 오브젝트에 재질을 넣어 주길 시작하는 군요.
재질은 입혀주고, 또한 집틀안에 있는 바닥은 다른 재질로 적용하는 방법도 알려줍니다.
이렇게 재질을 입혀놓고 돌려보니,., 정말 3D 이군요 ㅎㅎㅎ
이렇게 한 뒤에 저장을 합니다...
자 이제 Unity 로 넘어 갑니다.
4. Cinema4D Animation & Interaction 4탄
문을 열고, 닫는 애니메이션을 Cinema4D에서 처리를 해줍니다.
그리고 나서 저장을 하고... Unity을 열면 자동으로 불러와져야 하는데..
몇가지 이상야릇한 점이 있네요...
다른 이름으로 저장을 안하고, import 하는 형태로 불러서 사용합니다.
우선 저같은 경우에는 3D MAX 로 했습니다.
애니메이션 처리도 넣어 줍니다.
쩝.. 중요한 것에 대해서만 체크 하고 넘어 가도록 합니다.
5. Cinema4D Animation & Interaction 5탄
house 에 대한 객체 설정, 집과 문 에 Tag 를 지정해주고
이동하는 주인공이 문과 충돌했을때.. 문이 열리도록 하는 스크립트를 추가 합니다.
문이 열릴때.. 소리도 넣어주시고..
닫을때도 마찬가지..이겠지용
어떻게 하는지에 대한 방법론을 배우는 자리라고 생각하면 좋을듯 싶습니다.
==> 여기서 부터는 괴롭겠지만.. lession 3 를 보는 것이 편리 하겠습니다. @.@
이 동영상의 원본을 찾으러 갔는데, 그 아저씨는 해당 동영상은 모두 없애고... Unity3DStudent 사이트로 가랍니다.
그 사이트를 만들고, 관리하는 분인듯 싶습니다... 그쪽 동영상 목소리가 똑같아;;;
var doorOpened : boolean = false;
var doorAudio : AudioClip;
var doorShut : AudioClip;
var timer : float = 0.0;
function OnControllerColliderHit(hit:ControllerColliderHit){
if((hit.gameObject.tag == "house1door") && (doorOpened == false)){
openDoor();
}
}
function Update(){
if(doorOpened){
timer += Time.deltaTime;
}
if(timer >= 5){
shutDoor();
}
}
function shutDoor(){
var theHouse = gameObject.FindWithTag("house1");
theHouse.animation.Play("doorshuts");
doorOpened = false;
audio.PlayOneShot(doorShut);
timer = 0;
}
function openDoor(){
doorOpened = true;
var theHouse = gameObject.FindWithTag("house1");
theHouse.animation.Play("dooropening");
audio.PlayOneShot(doorAudio);
}
6. Cinema4D Animation & Interaction 5탄
방안에 불을 넣어 줍니다. 밝게~ 해줘야지...
Layer로 적용해주고 있습니다.
아... 하루가 다 가버렸군요.. 몰라 여기까지...@.@
설정
트랙백
댓글
글
Intermediate(중간) 단계의 강좌들입니다.
요걸 다 보고 나니... 볼것이 없네요.. 다른 강좌들이 있는지 좀 찾아 봐야 할것 같습니다..
1. Raycasting
많이 들어 본것 같은데 Ray(x-ray 들어봤는데.. 빛인가??) 는 안보이는 선인것 같다.
나중에 좀더 보충해야지.. 가상의 선을 그어.. 그 선과 다른 객체와의 관계를 나타내고 있습니다.
function Update () {
var up = transform.TransformDirection(Vector3.up);
var hit : RaycastHit;
Debug.DrawRay(transform.position, -up * 10, Color.green);
if(Physics.Raycast(transform.position, -up, hit, 10)){
Debug.Log("Hit");
if(hit.collider.gameObject.name == "floor"){
Destroy(GetComponent(Rigidbody));
}
}
}
2. Basic Animation and Events
Animation 를 추가 해서.. 해당 시간에 해당 객체가 어떠한 이동/확대/회전 을 하느냐를 적용합니다.
또한 해당 이동시에 Flat 이라는 것을 적용해서 부드럽게 이동하도록 하는 효과도 주는 군요
애니메이션 과정중에 사운드도 집어 넣지요... 으하하핫
var blip : AudioClip;
function blipSounder () {
AudioSource.PlayClipAtPoint(blip, transform.position);
}
Unity3DStudent 와 함께 있는 LearnUnity3D 가 있군요.. 형제(자매) 사이트 인듯 싶은데... 이곳에도 튜토리얼이 있더군요.. 참고하면 좋을 싶습니다. (영어를 잘한다면.. 쉽게 접근가능 하겠습니다.)
http://learnunity3d.com/
설정
트랙백
댓글
글
Become a videogame developer 라는 부제를 가지고 있는 사이트입니다.
http://www.unity3dstudent.com/
교육 단계 모두 동영상으로 구성되어 있어서 , 공부하는데 정말 수월하게 진행 될수 있었습니다.
아래 내용은 제가 공부 하는데, 정리한 내용들이니.. 위에 사이트 가셔서 직접 공부하시는 것이 더더욱 도움이 많이 될것입니다. ^^
기본적으로 해당 강좌는 모두 javascript 로 구현되어져 있습니다.
Adding Mass / Gravity with Rigidbodies
해당 객체에 아래와같이 함수를 추가해주시고, 중력을 줍시다.
기본적으로 이렇게 중력을 추가하는 것이 가장 기본이고, 이게 너무 신기 했습니다.
1. Basic Collision Detection
충돌 탐지 : 해당 객체에 아래와 같이 함수를 추가해 보시면.. 아래와 같이 디버깅 창에 로그가 나타납니다. 충돌이 되는 순간을 알수 있다라는 것 알게 되었지요
function OnCollisionEnter(theCollision : Collision){
if(theCollision.gameObject.name == "Floor"){
Debug.Log("Hit the floor");
}else if(theCollision.gameObject.name == "Wall"){
Debug.Log("Hit the wall");
}
}
2. Detecting Input
입력값 탐지 : Update 함수는 Play가 되는 동안을 알수 있는 함수 있다.
스페이스바를 눌렀을때.. 로그가 나오는 거죠
function Update () {
if(Input.GetButtonUp("Jump")){
Debug.Log("We Have Hit the Space Bar!");
}
}
3. Prefabs
Prefabs – How to make them, what they are for, and why!
Hierarchy에서 생성한 객체를 Prefabs 로 생성해서 추가합니다.
그리고 맘대로 쓸수가 있군요.. 한번 만든것을 응용해서 사용하자는 거군요.
4. Destroying Objects
오브젝트를 삭제하는 것을 알려 줍니다.
타겟을 지정하고, 지연시간을 추가할수도 있지요.
function Start () {
Destroy(gameObject.Find("Cube"),2);
}
5.Instantiate to Create Objects
빈 객체(GameObject)에다가.. javascript로 객체 생성을 하고, prefab에다가... 기존에 만들어 놓은 BounyBox(prefab)를 추가하면.. 생성이 되지요
6.SImple Timer
타이머를 추가해서.. 이것저것 로그 찍어봅시다.
//A simple countdown timer
var myTimer : float = 5.0;
function Update () {
if(myTimer > 0){
myTimer -= Time.deltaTime;
}
if(myTimer <= 0){
Debug.Log("GAME OVER");
}
}
7. Basic Translate Movement
해당 객체를 이동시키는 거군요.. 간단 하면서..
//Basic movement of an object with Translate
var speed : float = 5.0;
function Update () {
transform.Translate(Vector3(0,0,speed) * Time.deltaTime);
}
8. Basic Force Movement
힘...해당축으로 밀어주는 힘을 말하는 군요..냐하하하
//Basic force to move a rigidbody object
var power : float = 500.0;
function Start () {
rigidbody.AddForce(Vector3(0,0,power));
}
9.Adding Materials
배경 입히는 것이군요..
10. Audio Basics
스크립트를 통해 사운드를 넣어주게 됩니다.
//Play an instance using attached AudioSource component
var myClip : AudioClip;
function Start () {
audio.PlayOneShot(myClip);
}
Using PlayClipAtPoint:
//Spawn a new object with AudioSource and Clip set, at a point in the 3D world
var myClip : AudioClip;
function Start () {
AudioSource.PlayClipAtPoint(myClip, transform.position);
}
11. Basic Joints
기본 관절... 헐..이음새 등을 이용하게 되는 군요.. 오홋 정말 신기합니다.
이음새를 연결하여 헐렁 헐렁...
12.Input with Axes
방향키로 객체를 조정하는 방법을 배워봅니다.
응용범위가 점점 넓어지는 군요
function Update () {
var horiz : float = Input.GetAxis("Horizontal");
Debug.Log(horiz);
transform.Translate(Vector3(horiz,0,0));
}
13. Trigger Collision Detection
Trigger를 체크 했을때, 객체가 통과가 되네요..
또한 통과했을때의 확인할수 있습니다.
function OnTriggerEnter (myTrigger : Collider) {
if(myTrigger.gameObject.name == "box"){
Debug.Log("Box went through!");
}
}
14. GUI Text and Counters
GUIText 객체를 사용하는 방법에 대해서 알아봅니다.
오홋 카운트도 넣을수가 있네요.. 이런 말도 안되는;;
var Counter : int = 0;
function Update () {
Counter++;
guiText.text = "Counter is: "+Counter;
}
15. Adding Componets via Script
스크립트를 사용해서 다른 객체에게 기능을 추가하는 요소
function OnCollisionEnter (myCollision : Collision) {
if(myCollision.gameObject.name == "Platform"){
if(!myCollision.gameObject.rigidbody){
myCollision.gameObject.AddComponent(Rigidbody);
}
}
}
16. Switching Scenes
화면 전환입니다.(Build Setting 를 사용할수도 있지요..)
플레이 화면과 결과 화면을 연동에 응용하면 좋을것 같습니다.
var myLevel : String;
function OnCollisionEnter (myCollision : Collision) {
if(myCollision.gameObject.name == "Floor"){
Application.LoadLevel(myLevel);
}
}
17. Tweaking Components via script
스크립트를 이용하여, 불을 켜다...
function OnCollisionEnter (myCollision : Collision) {
if(myCollision.gameObject.name == "Floor"){
var myLight : Light = gameObject.Find("Light").GetComponent(Light);
myLight.enabled = true;
myLight.intensity = 5;
}
}
18.Local vs World Direction
alt 키를 누르면 되고.. Local 과 World Direction은 좀더 찾아서 공부를 해봐야 할 것 같습니다.
function Update () {
//transform.Translate(Vector3(0,0,1) * Time.deltaTime);
var fwd = transform.forward * 100;
rigidbody.AddForce(fwd);
}
19. Following with LookAt()
카메라 이동 컷입니다. 오호홋.. 바로 이거야. 멋쪄브렁
var myTransform : Transform;
function Update () {
transform.LookAt(myTransform);
}
20. IF Statement and Booleans
boolean의 상태값 에 따라 변경하는 방법
var myCheck : boolean = true;
function Update () {
if(myCheck){
guiText.text = "Its on!";
}else{
guiText.text = "Its Off!";
}
if(Input.GetButtonUp("Jump") && myCheck){
myCheck = false;
}else if(Input.GetButtonUp("Jump") && myCheck == false){
myCheck = true;
}
}
21. Finding Distance with Vector3
떨어지는 객체에 대한 거리를 측정하여, 다양한 액션을 취하도록 합니다.
var box : Transform;
function Update () {
var dist : float = Vector3.Distance(box.position, transform.position);
Debug.Log(dist);
if(dist <= 10){
light.enabled = true;
}else{
light.enabled = false;
}
}
22. Pausing Scripts with WaitForSeconds()
몇초동안 멈추는듯 한데유..
더욱 신기한것은 Instantiate 함수 입니다.
계속 인스턴스를 생성하네요 @.@
var box : GameObject;
var readynow : boolean = true;
function Update () {
if(readynow){
MakeBox();
}
}
function MakeBox(){
readynow=false;
Instantiate(box, transform.position, transform.rotation);
yield WaitForSeconds(2);
readynow=true;
}
23. Particle Systems
파티클을 적용 해봅시다. 터지는 효과등에 사용하면 그만이겠군요!
var stars : ParticleEmitter;
function OnCollisionEnter (col : Collision) {
Instantiate(stars, transform.position, transform.rotation);
Destroy(gameObject);
}
24. For Loops
루프를 돌려 보자구용
var myPrefab : Rigidbody;
var distanceMultiplier : float = 2;
function Start(){
var i : int = 0;
var pos : Vector3 = transform.position;
for(i=0; i<=3; i++){
Instantiate(myPrefab, Vector3(pos.x+i*distanceMultiplier, pos.y, pos.z), transform.rotation);
yield WaitForSeconds(0.5);
Debug.Log("made ball "+i);
}
}
25. GUI Texture & mouse Event
드디어.. 버튼 롤오버.. 와 클릭 이벤트를 알아냈군요..
게임내 버튼을 만들면 되겠군요..요걸 가지고
var normalTex : Texture2D;
var hoverTex : Texture2D;
function OnMouseEnter () {
guiTexture.texture = hoverTex;
}
function OnMouseExit(){
guiTexture.texture = normalTex;
}
function OnMouseDown(){
Debug.Log("clicked");
}
26. Using Mathf.Clamp to restrict values
이동의 제한을 두는 방법입니다.
Clamp 자체가 꺽쇠 라는 뜻이라는 군요..
function Update () {
var xMove : float = Input.GetAxis("Horizontal") * Time.deltaTime * 20;
transform.Translate(Vector3(xMove,0,0));
transform.position.x = Mathf.Clamp(transform.position.x, -10, 10);
}
27.Using Time.timeScale to Pause
timeScale 를 이용한 일시정지..(스페이드바 키를 이용)
var paused : boolean = false;
function Update () {
if(Input.GetButtonUp("Jump")){
if(!paused){
Time.timeScale = 0;
paused=true;
}else{
Time.timeScale = 1;
paused=false;
}
}
}
28. SendMessage() to Call External Functions
자.. 그러니까.. 외부 함수를 SendMessage를 통해서 전달할수가 있다는 말이야.
var downTexture : Texture2D;
function React () {
renderer.material.mainTexture = downTexture;
yield WaitForSeconds(1);
gameObject.AddComponent(Rigidbody);
}
function OnCollisionEnter(col : Collision) {
if(col.gameObject.name == "Switch"){
gameObject.Find("Block").SendMessage("React");
}
}
Basic 단위에 대해서는 여기까지 였습니다.
자.. 다음 단계로 넘어가봅시다...
RECENT COMMENT