'Unity3D/Project'에 해당되는 글 36건
- 2017.03.17 [Unity3D] UI - HP, MP 에너바 조절하기. [Part 2] 1
- 2017.03.16 [Unity3D] UI - HP, MP 에너바 조절하기. [Part 1] 1
- 2017.03.15 [Unity3D] UI - HP, MP 에너바 조절하기. [Part 0]
- 2017.03.13 [Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 2] 10
- 2017.03.10 [Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 1] 6
- 2017.03.08 [Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 4] 3
- 2017.03.08 [Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 3] 3
- 2017.03.07 [Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 2]
- 2017.03.06 [Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 1]
- 2017.03.02 [Unity3D] 캐릭터 움직임, 충돌체크, 물리엔진사용 X [Part 5]
[Unity3D] UI - HP, MP 에너바 조절하기. [Part 2]
※ 주의
이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.
Menu
0. 미리보기
1. HP,MP껍데기 및 기능 만들기.
2. HP,MP 조절을 위한 데미지, 리커버리 만들기.
2. HP,MP 조절을 위한 데미지, 리커버리 만들기.
에셋 스토어에서 무료 파티클을 받아서 하이러키창에 배치하자.
하나는 데미지 또 하나는 리커버리라고 명명하면 된다.
왼쪽이 데미지, 오른쪽이 리커버리 파티클이다.
두개의 오브젝트에 Rigidbody와 BoxColider를 부착하자.
※ 파티클 오브젝트 인스펙터창 정보.
각각에 오브젝트에 일어난 충돌들을 체크하여 플레이어에게 적용할 것이다.
충돌이 일어났을 때 플레이어가 가진 정보를 가져와서 그 정보를 이용하여 HP,MP에 영향을 준다.
충돌을 체크하는 방법에는 2가지가 있다.
OnCollision( 물리현상 O ) | OnTrigger( 물리현상 X ) | ||
OnCollisionEnter() | - 처음 한 번 충돌 시 한 번 호출. - 다시 호출 하려면 충돌 영역을 벗어난 뒤에 다시 부딪히면 된다. | OnTriggerEnter() | 기능은 같다. |
OnCollisionStay() | - 충돌 영역에 존재하는동안 게속 하여 호출한다. | OnTriggerStay() | 기능은 같다. |
OnCollisionExit() | - 충돌 영역에 들어온 후 그 영역을 벗어나면 호출된다. | OnTriggerExit() | 기능은 같다. |
OnCollision을 사용할 시에는 앞에 벽이 존재하는것처럼 충돌을 수행 하지만,
OnTrigger는 충돌만 체크할뿐 통과해 버린다.
이중 우리는 OnTrigger를 사용할 것이다.
OnTrigger를 사용하려면 각 오브젝트에 붙어있는 BoxCollider의 is Trigger를 체크해줘야 한다.
※ 충돌에 의한 움직임이나, 중력은 사용하지 않을 것이므로 Rigidbody에 Is Kinematic을 체크 하도록 하자.
각 기능이 다르기 때문에 2가지의 스크립트로 작성해 보도록 하자.
각각의 스크립트 이름은 Damage, Recover이다.
데미지 스크립트.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class Damage : MonoBehaviour { private PlayerInfo pInfo; // 플레이어의 스크립트가 저장될 변수. // 지속적으로 플레이어의 HP 감소. IEnumerator StartDamage() { while (true) { // 플레이어가 가지고 있는 UIUpdate호출. pInfo.UIUpdate("Damage", "HP", 0.1f); yield return null; } } // 충돌 했을 때. void OnTriggerEnter(Collider _Col) { if (_Col.transform.CompareTag("Player")) { // 플레이어의 스크립트 컴포넌트를 가져온다. pInfo = _Col.GetComponent<PlayerInfo>(); StartCoroutine("StartDamage"); } } // 충돌이 끝났을 때. void OnTriggerExit(Collider _Col) { if (_Col.transform.CompareTag("Player")) { // 코루틴을 멈춘다. StopCoroutine("StartDamage"); // 충돌이 끝난 후 정보를 플레이어의 정보를 게속 가지고 있을 필요가 // 없기 때문에 null로 초기화 해준다. pInfo = null; } } } | cs |
리커버리 스크립트.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class Recover : MonoBehaviour { private PlayerInfo pInfo; // 플레이어의 스크립트가 저장될 변수. // 지속적으로 플레이어의 HP회복. IEnumerator StartRecover() { while (true) { pInfo.UIUpdate("Recover", "HP", 0.1f); yield return null; } } // 충돌 했을 때. void OnTriggerEnter(Collider _Col) { if (_Col.transform.CompareTag("Player")) { pInfo = _Col.GetComponent<PlayerInfo>(); StartCoroutine("StartRecover"); } } // 충돌이 끝났을 때. void OnTriggerExit(Collider _Col) { if (_Col.transform.CompareTag("Player")) { // 코루틴을 멈춘다. StopCoroutine("StartRecover"); // 충돌이 끝난 후 정보를 플레이어의 정보를 게속 가지고 있을 필요가 // 없기 때문에 null로 초기화 해준다. pInfo = null; } } } | cs |
결과.
'Unity3D > Project' 카테고리의 다른 글
[Unity3D] 객체 미리 생성 후 재활용 - Memory pool [Part 1] (0) | 2017.03.20 |
---|---|
[Unity3D] 객체 미리 생성 후 재활용 - Memory pool [Part 0] (0) | 2017.03.20 |
[Unity3D] UI - HP, MP 에너바 조절하기. [Part 1] (1) | 2017.03.16 |
[Unity3D] UI - HP, MP 에너바 조절하기. [Part 0] (0) | 2017.03.15 |
[Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 2] (10) | 2017.03.13 |
[Unity3D] UI - HP, MP 에너바 조절하기. [Part 1]
※ 주의
이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.
Menu
0. 미리보기
1. HP,MP껍데기 및 기능 만들기.
2. HP,MP 조절을 위한 데미지, 리커버리 만들기.
1. HP, MP껍데기 및 기능 만들기.
- 배칭(드로우콜)을 줄이기 위해 유니티에서 제공하는 아틀라스 사용.
텍스쳐 타입 : sprite (2D and UI)
스프라이트 모드 : Multiple
패킹 태그 : UI
위의 셋팅이 끝난 뒤 스프라이트 에디터를 누른다.
Slice를 누면 밑에 창이 나오는데, 그 창에서 Slice를 누르면 이미지들이 자신의 크기에 맞게 잘린다.
이미지가 알맞게 잘렸으면 Apply를 눌러 빠져나온다.
메인 이미지에 붙어있는 ◀단추를 누르면 잘린 이미지들이 자식으로 들어가 있는것을 확인 할 수 있다.
※ 다른 이미지가 필요해졌을 때 패킹 태그를 똑같은 이름으로 지정하면 똑같은 스프라이트 팩에 들어가게 된다.
이러한 설정(아틀라스)을 하지 않으면, 캔버스에 이미지를 하나 만들어 쓸때마다 배치(Batches)가 증가하게 된다.
모바일 게임에 경우 이러한 배치수를 100개를 상한선으로 두고 있다.
※ 배치수가 너무 많다면 게임을 원할하게 돌아가게 할 수 없다.
스프라이트 팩에들어있는 이미지는 몇개를 꺼내쓰든 1개의 배치만을 소모한다.
게임창에 Stats를 누르면 배치수를 확인 할수 있는데, SkyBox 배치 1개, 이미지 배치수가 1개가 들어간 것을 볼 수 있다.
※ 사용한 이미지는 총 5개다.
여기서 아틀라스화 하지 않은 이미지를 쓰면 배치는 바로 증가하게 된다.
-------------------------------------------------------------------------------------------------------------------
- HP 및 MP를 눌러 이미지 타입을 Simple에서 Filled로 전환한다.
그 후
Fill Method : Horizontal
Fill Origin : Left
으로 전환한 뒤
Fill Amount를 마우스로 수동으로 조절해보면 밑의 그림처럼 변환되는것을 확인 할 수 있다.
Fill Amount의 값은 0 ~ 1의 값만을 가지고 있다.
실시간으로 변하는 체력을 표시하고 싶다면 Fill Amount = (현재체력 / 체력의 최대치)로 처리하여 넣으면 된다.
이제 코드로 플레이어의 체력을 변화시켜보도록 하자.
PlayerInfo스크립트를 만들어 플레이어 컴포넌트에 추가한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; // 이걸 using시켜줘야 Image의 자료형을 쓸수 있다. public class PlayerInfo : MonoBehaviour { // 공개 public GameObject[] Effect; public Image[] Img; // HP,MP이미지. public float MAX_HP; // HP 최대치. public float MAX_MP; // MP 최대치. public float p_HP; // 현재 HP. public float p_MP; // 현재 MP. // 플레이어 UI정보 갱신. // 인자 : (HP냐? MP냐?, 데미지냐? 체력회복이냐?, 데미지 혹은 체력회복의 수치는 얼마만큼이냐?) public void UIUpdate(string _Type, string _InfoType, float _Value) { float Type = 0; // HP또는 MP의 현재 수치. float MAXType = 0; // HP또는 MP의 최대치. int Index = 0; // HP또는 MP의 이미지 인덱스. switch (_InfoType) { case "HP": { Index = 0; Type = p_HP; MAXType = MAX_HP; // 리커버리면 회복 if (_Type == "Recover") p_HP += _Value; // 리커버리가 아니면 데미지. else p_HP -= _Value; break; } case "MP": { Index = 1; Type = p_MP; MAXType = MAX_MP; if (_Type == "Recover") p_MP += _Value; else p_MP -= _Value; break; } } // 인덱스 번째의 이미지를 갱신시킨다. // 만약, 변화시켜야 되는 이미지가 HP이고, 체력의 최대치가 100이라고 하자. // 20의 데미지를 받아 체력이 80남았다고 하자, 그러면 체력이 80이 남은것을 보여줘야 한다. // fillAmount의 값은 0 ~ 1가 끝이기 때문에 체력을 소수점으로 변환해줘야 표현이 가능해진다. // 80 / 100 = 0.8 요컨데 퍼센트로 바꿔서 표현한다 생각하면 된다. Img[Index].fillAmount = Type / MAXType; } } | cs |
플레이어의 인스펙터창 정보.
'Unity3D > Project' 카테고리의 다른 글
[Unity3D] 객체 미리 생성 후 재활용 - Memory pool [Part 0] (0) | 2017.03.20 |
---|---|
[Unity3D] UI - HP, MP 에너바 조절하기. [Part 2] (1) | 2017.03.17 |
[Unity3D] UI - HP, MP 에너바 조절하기. [Part 0] (0) | 2017.03.15 |
[Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 2] (10) | 2017.03.13 |
[Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 1] (6) | 2017.03.10 |
[Unity3D] UI - HP, MP 에너바 조절하기. [Part 0]
※ 주의
이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.
Menu
0. 미리보기
1. HP,MP껍데기 및 기능 만들기.
2. HP,MP 조절을 위한 데미지, 리커버리 만들기.
0. 미리보기
'Unity3D > Project' 카테고리의 다른 글
[Unity3D] UI - HP, MP 에너바 조절하기. [Part 2] (1) | 2017.03.17 |
---|---|
[Unity3D] UI - HP, MP 에너바 조절하기. [Part 1] (1) | 2017.03.16 |
[Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 2] (10) | 2017.03.13 |
[Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 1] (6) | 2017.03.10 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 4] (3) | 2017.03.08 |
[Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 2]
※ 주의
이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.
Menu
1. 조이스틱 만들기.
2. 조이스틱의 벡터를 받아 캐릭터를 회전 및 이동 시키기.
2. 조이스틱의 벡터를 받아 캐릭터를 회전 및 이동 시키기.
필요한 재료.
- 플레이어의 Trsnform 컴포넌트
- 움직임 플래그 값.
조이스틱을 만들었다면 움직이는것은 그다지 어렵지 않다.
조이스틱을 움직이기 위해서 구했던 벡터를 그대로 캐릭터를 회전 시키는데 쓰면 되기 때문이다.
물론 그 벡터를 그대로 갔다 쓰면 안되고 약간의 변경이 필요하다.
아크탄젠트를 사용해서 각도를 바꿔주고 그것을 디그리로 변경하면 되는데,
이러한 함수도 유니티에서 제공해주고 있다.
※ 삼각비,삼각함수,라디안,디그리 등은 블로그내에 게임수학 부분을 참고하기 바란다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class JoyStick : MonoBehaviour { // 공개 public Transform Player; // 플레이어. public Transform Stick; // 조이스틱. // 비공개 private Vector3 StickFirstPos; // 조이스틱의 처음 위치. private Vector3 JoyVec; // 조이스틱의 벡터(방향) private float Radius; // 조이스틱 배경의 반 지름. private bool MoveFlag; // 플레이어 움직임 스위치. void Start() { Radius = GetComponent<RectTransform>().sizeDelta.y * 0.5f; StickFirstPos = Stick.transform.position; // 캔버스 크기에대한 반지름 조절. float Can = transform.parent.GetComponent<RectTransform>().localScale.x; Radius *= Can; MoveFlag = false; } void Update() { if (MoveFlag) Player.transform.Translate(Vector3.forward * Time.deltaTime * 10f); } // 드래그 public void Drag(BaseEventData _Data) { MoveFlag = true; PointerEventData Data = _Data as PointerEventData; Vector3 Pos = Data.position; // 조이스틱을 이동시킬 방향을 구함.(오른쪽,왼쪽,위,아래) JoyVec = (Pos - StickFirstPos).normalized; // 조이스틱의 처음 위치와 현재 내가 터치하고있는 위치의 거리를 구한다. float Dis = Vector3.Distance(Pos, StickFirstPos); // 거리가 반지름보다 작으면 조이스틱을 현재 터치하고 있는 곳으로 이동. if (Dis < Radius) Stick.position = StickFirstPos + JoyVec * Dis; // 거리가 반지름보다 커지면 조이스틱을 반지름의 크기만큼만 이동. else Stick.position = StickFirstPos + JoyVec * Radius; Player.eulerAngles = new Vector3(0, Mathf.Atan2(JoyVec.x, JoyVec.y) * Mathf.Rad2Deg, 0); } // 드래그 끝. public void DragEnd() { Stick.position = StickFirstPos; // 스틱을 원래의 위치로. JoyVec = Vector3.zero; // 방향을 0으로. MoveFlag = false; } } | cs |
MoveFlag같은 경우 조이스틱을 드래그 할때만 true로 바뀌고 드래그가 끝난다면 곧바로 false로 돌아간다.
플래그 값이 true인 동안에만 transform.Translate를 통해 캐릭터가 움직인다.
플레이어를 움직이는 구문을 Drag함수 안에 놓으면 드래그 하는동안만 움직이지 않냐고 물을수도 있다.
맞다. 드.래.그 하는 동안만 움직인다. 조이스틱을 잡고 끝으로 땡겨놓고 가만히 있으면 조이스틱을 땡기는 동안만 움직이고
가만히 있을때에는 움직이지 않는다. 말 그대로 조이스틱을 잡고 움직이는 동안만 함수가 들어오는 것이다.
아무튼 움직이는 것은 지속적으로 체크가 가능한 Update함수에서 해야한다. (코루틴을 사용해도 좋다.)
플레이어를 어떤 축을 중심으로 회전시켜야 할까?
y축이다. y축을 원하는 방향으로 회전만 시킨다면 플레이어는 그 방향으로 나아가게 될 것이다.
그렇다면 그 방향을 어떻게 구할수 있을까?
바로 조이스틱의 벡터이다. 하지만 이 벡터는 바로 쓸수 없다.
쓰기 위해선 아크탄젠트를 통해 변환하고, 나온 라디안 값을 디그리로 변환해주고 나온 디그리 값으로
플레이어의 y축 회전에 쓰면된다.
아탄을 통해 각a를 구할수 있다.
하지만 이 값은 라디안 값이므로 디그리(각도)로 변환해 주어야 한다.
결과.
'Unity3D > Project' 카테고리의 다른 글
[Unity3D] UI - HP, MP 에너바 조절하기. [Part 1] (1) | 2017.03.16 |
---|---|
[Unity3D] UI - HP, MP 에너바 조절하기. [Part 0] (0) | 2017.03.15 |
[Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 1] (6) | 2017.03.10 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 4] (3) | 2017.03.08 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 3] (3) | 2017.03.08 |
[Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 1]
※ 주의
이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.
Menu
1. 조이스틱 만들기.
2. 조이스틱의 벡터를 받아 캐릭터를 회전 및 이동 시키기.
완성작 미리보기
1. 조이스틱 만들기.
1). 이미지 준비.
- 조이스틱의 배경 이미지.
- 조이스틱 이미지.
2). 캔버스 준비.
UI이미지를 따로 관리해주는 객체가 있다.
하이러키창에서 마우스 오른쪽버튼을 클릭해 보면 UI라는 메뉴가 있는데,
이 메뉴안에 있는 여러가지 목록들을 선택하면 목록에 있는 객체가 생성된다.
만약 하이러키창에 캔버스가 없으면 캔버스를 자동으로 생성시키고 캔버스의 자식으로
우리가 선택한 목록을 생성시킨다.
더불어 EventSystem이라는 객체도 생성시키는데, 이 객체는 각종 UI이벤트에 필요한 객체이다.
이객체는 우리가 따로 건드릴 필요는 없다.
이미지를 2개 생성시킨다.
첫 번째 이미지의 이름은 JoyStickBackGround
두 번째 이미지의 이름은 JoyStick
그리고 객체를 하나씩 선택해서 이미지를 넣자.
2개의 이미지를 겹쳐 한쪽 구석에 이쁘게 정리하도록 하자.
정리가 끝났으면
JoyStick을 배경의 자식으로 넣는다.
하이러키창에 조이스틱 객체를 누르고 Add Componenet를 누른다.
그리고 Event Trigger라고 검색하면 하나의 컴포넌트가 나온다.
추가하도록 하자.
이 컴포넌트에는 UI에 대하여 여러가지 이벤트를 수행할 수 있다.
그 중에서 우리가 사용할 것은 드래그와 끝 드래그 이다.
이러한 컴포넌트를 조이스틱 객체에다 만든 이유는
조이스틱객체를 터치하여 움직이게 할 것이기 때문이다.
드래그와 드래그 끝 2개를 추가시켜주자.
다음은 스크립트를 작성하도록 하자.
스크립트의 이름은 JoyStick이다.
이 스크립트는 JoyStickBackGround에 넣도록 하자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class JoyStick : MonoBehaviour { // 공개 public Transform Stick; // 조이스틱. // 비공개 private Vector3 StickFirstPos; // 조이스틱의 처음 위치. private Vector3 JoyVec; // 조이스틱의 벡터(방향) private float Radius; // 조이스틱 배경의 반 지름. void Start() { Radius = GetComponent<RectTransform>().sizeDelta.y * 0.5f; StickFirstPos = Stick.transform.position; // 캔버스 크기에대한 반지름 조절. float Can = transform.parent.GetComponent<RectTransform>().localScale.x; Radius *= Can; } // 드래그 public void Drag(BaseEventData _Data) { PointerEventData Data = _Data as PointerEventData; Vector3 Pos = Data.position; // 조이스틱을 이동시킬 방향을 구함.(오른쪽,왼쪽,위,아래) JoyVec = (Pos - StickFirstPos).normalized; // 조이스틱의 처음 위치와 현재 내가 터치하고있는 위치의 거리를 구한다. float Dis = Vector3.Distance(Pos, StickFirstPos); // 거리가 반지름보다 작으면 조이스틱을 현재 터치하고 있는곳으로 이동. if (Dis < Radius) Stick.position = StickFirstPos + JoyVec * Dis; // 거리가 반지름보다 커지면 조이스틱을 반지름의 크기만큼만 이동. else Stick.position = StickFirstPos + JoyVec * Radius; } // 드래그 끝. public void DragEnd() { Stick.position = StickFirstPos; // 스틱을 원래의 위치로. JoyVec = Vector3.zero; // 방향을 0으로. } } | cs |
Stick변수는 조이스틱을 움직이기 위해 필요하다.
StickFirstPos변수는 조이스틱의 처음 위치가 들어가 있는데,
조이스틱을 움직이기 위해서는 처음 위치에다가 움직일 거리를 더해줄 필요가 있다.
처음위치 + 방향 * 거리 방식으로 움직여야 한다.
그리고, 드래그하다가 터치를 땠을 때 조이스틱은 원래의 위치로 돌아갈 필요가 있는데,
그 원래에 위치로 돌려주기위한 위치 값 저장 이기도 하다.
JoyVec은 현재 조이스틱에 대한 방향을 저장해줄 벡터 변수이다.
Radius는 배경 그림에 대한 반지름의 크기를 넣을 것이다.
조이스틱이 배경 이미지 바깥으로 넘어가지 못하게 하기 위함이다.
다음은 Drag함수이다.
모든 UI이벤트는 사실 레이캐스트로 작동하고 있다.
그렇기 때문에 이미지에 존재하는 Raycast Tartget을 해제하면 터치 이벤트가 작동하지 않는다.
아무튼, 터치에 대한 정보는 EventSystem에 저장되는데, UI메뉴중 아무거나 생성시키면 같이 생성되는 이유는 그 때문이다.
이 EventSystem에는 터치 정보 말고도 여러가지 정보가 저장되어있다.
그렇기 때문에 그 정보를 꺼내 쓰기 위해서 유징해줄 필요가 있는데,
스크립트에 맵 위에 보면 UnityEngine.EventSystems;이 유징되어 있는것을 볼 수 있다.
조이스틱을 움직이기 위해서는 현재 터치되는 위치가 어디인지 알 필요가 있다.
그 위치에 대한 정보는 BaseEventData에 들어있는데, 이 자료형을 사용하려면 EventSystems가 유징되어있어야 한다.
이벤트 트리거에서 잘 보면 BaseEventData을 인자로 받는것을 볼 수 있다.
베이스 이벤트 데이터를 인자로 받아
그 데이터를 PointerEventData 변수에 형변환 시킨뒤 저장한다.
※ PointerEventData : 마우스 및 터치에 대한 이벤트.
BaseEventData을 이용하고 있기 때문에 터치 포인트에 대해서는 따로 쓰게 된다.
무슨말이냐면 쉽게 말해서 이러한 조이스틱말고 또 다른 버튼이벤트 같은것이 있을 경우
터치 포인터를 공유해서 쓰지않고 따로따로 쓴다는 말이다.
한 줄로 요약해서 멀티터치가 가능하다는 소리다.
나머지 구문들은 스크립트에 주석으로 설명이 되어있기 때문이 생략하겠다.
결과
'Unity3D > Project' 카테고리의 다른 글
[Unity3D] UI - HP, MP 에너바 조절하기. [Part 0] (0) | 2017.03.15 |
---|---|
[Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 2] (10) | 2017.03.13 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 4] (3) | 2017.03.08 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 3] (3) | 2017.03.08 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 2] (0) | 2017.03.07 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 4]
※ 주의
이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.
기능정리
1. 플레이어를 따라오는 카메라.
1.5. 플레이어의 움직임.
2. 마우스 휠 카메라 줌 인,아웃 기능.
3. 마우스 오른쪽 버튼 클릭 후 카메라 회전.
- x,y축 회전
- x축 회전의 한계치 설정.
3. 마우스 오른쪽 버튼 클릭 후 카메라 회전.
Input에는 마우스의 움직임에 대한 정보도 제공해 주고 있다.
"Mouse X" 는 마우스의 좌,우 움직임을,
"Mouse Y" 는 마우스의 상,항의 움직임에 대한 정보를 가지고있다.
마우스 오른쪽 버튼을 누르고 있을 때 카메라의 회전이 가능하게 만들어보자.
벡터변수 Gap을 만들어서 Gap.x값에 Mouse Y값을 축적해보도록 하자.
'Gap.x인데 Mouse X값이 아니냐?' 라고 묻는다면, 아니라고 답변해주고 싶다.
Mouse Y는 상,하에 대한 움직임을 감지한다. 즉, 마우스 오른쪽 버튼을 클릭한 채
위로 올리면 카메라는 밑을 바라보게 되고, 밑으로 내리면 위를 바라보게 해야한다.
이러한 경우를 봤을 때 회전을 이용하는건데, y축 회전이 아닌 x축으로 회전을 가하기 때문에
Gap.x에 Mouse Y값을 축적할 필요가 있다.
※ x축으로 회전하기 때문에 Gap.x에 Mouse Y를 축적시킬 필요가 있다.
Gap.x에 Mouse Y의 양수 값으로 축적하게 된다면 마우스를 위로 올려야지 카메라가 위에서 밑을 바라보는 상황이 될것이다.
그렇기 때문에 -1을 곱해주어 음수값으로 만든다면 마우스 오른쪽 버튼 클릭 후 밑으로 드래그 한다면 카메라가 위에서 밑을 바라보는 상활을 만들수 있다.
※ 반대로 Gap.y에는 Mouse X를 축적해야한다.
이 카메라도 마찬가지로 회전의 최소값과 최대값을 Mathf.Clamp함수를 이용하여 지정할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class Axis : MonoBehaviour { public Quaternion TargetRotation; // 최종적으로 축적된 Gap이 이 변수에 저장됨. public Transform CameraVector; public float RotationSpeed; // 회전 스피드. public float ZoomSpeed; // 줌 스피드. public float Distance; // 카메라와의 거리. private Vector3 AxisVec; // 축의 벡터. private Vector3 Gap; // 회전 축적 값. private Transform MainCamera; // 카메라 컴포넌트. void Start() { MainCamera = Camera.main.transform; } void Update() { Zoom(); CameraRotation(); } // 카메라 줌. void Zoom() { Distance += Input.GetAxis("Mouse ScrollWheel") * ZoomSpeed * -1; Distance = Mathf.Clamp(Distance, 5f, 20f); AxisVec = transform.forward * -1; AxisVec *= Distance; MainCamera.position = transform.position + AxisVec; } // 카메라 회전. void CameraRotation() { if (transform.rotation != TargetRotation) transform.rotation = Quaternion.Slerp(transform.rotation, TargetRotation, RotationSpeed * Time.deltaTime); if (Input.GetMouseButton(1)) { // 값을 축적. Gap.x += Input.GetAxis("Mouse Y") * RotationSpeed * -1; Gap.y += Input.GetAxis("Mouse X") * RotationSpeed; // 카메라 회전범위 제한. Gap.x = Mathf.Clamp(Gap.x, -5f, 85f); // 회전 값을 변수에 저장. TargetRotation = Quaternion.Euler(Gap); // 카메라벡터 객체에 Axis객체의 x,z회전 값을 제외한 y값만을 넘긴다. Quaternion q = TargetRotation; q.x = q.z = 0; CameraVector.transform.rotation = q; } } } | cs |
Axis객체 인스펙터 정보.
Quternion.Euler(Gap);
오일러를 통해 축적된 Gap을 넣는다.
이 쿼터니언에는 얼만큼 회전하느냐에 대한 회전 값이 들어있다.
이러한 회전값을 TargetRotation에 초기화 시킨다.
그리고 transform.rotation(Axis객체 자신의 회전 값)에 저장된 회전값을 대입해줘도 되지만,
그렇게 되면 카메라가 서서히 회전하는 효과를 느낄수 없으므로, 쿼터니언의 슬러프 함수를 써서 목표회전을 사용하여
값을 대입 해준다.
Quternion.Slerp(현재 자신의 회전 값, 목표 회전 값, 회전 스피드);
정도로 보면 된다.
목표 회전을 하지 않았을 경우. (Slerp함수를 사용하지 않았을 경우.)
transform.rotation = TargetRotation;
목표회전을 사용한 경우. (Slerp함수를 사용한 경우.)
transform.rotation = Quaternion.Slerp(transform.rotation, TargetRotation, RotationSpeed * Time.deltaTime);
1 2 3 4 5 | Quaternion q = TargetRotation; q.x = q.z = 0; CameraVector.transform.rotation = q; | cs |
새롭게 쿼터니언 변수q를 만들어서 TargetRotation을 대입한 이유는
TargetRotation값을 회손하면 안되기 때문이다.
※ TargetRotation는 카메라를 x,y축을 회적시키는데 필요한 값이다.
쿼터니언변수 q에 x,z값을 0으로 초기화 시킨다.
y값만을 사용할 건데, 잘 생각해보면 현재 이 쿼터니언 값을 카메라의 회전값이다.
카메라의 x,z값을 0으로 초기화 시키고 y값만을 쓴다면 어떻게 될까?
바로 이렇게 된다.
x,z값을 0으로 고정시켰기 때문에 y축에대한 회전을 한다.
지금 회전하는 이 객체는 맨 처음에 만들어 두었던 CameraVector객체이다.
이 객체를 y회전만 시키는 이유는 카메라가 회전했을 때 카메라가 보는 방향에서 플레이어를 자유롭게 조종하기 위함이다.
플레이어는 이 객체(CameraVector)에 벡터값을 가져와서 이동한다.
완성.
'Unity3D > Project' 카테고리의 다른 글
[Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 2] (10) | 2017.03.13 |
---|---|
[Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 1] (6) | 2017.03.10 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 3] (3) | 2017.03.08 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 2] (0) | 2017.03.07 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 1] (0) | 2017.03.06 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 3]
※ 주의
이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.
기능정리
1. 플레이어를 따라오는 카메라.
1.5. 플레이어의 움직임.
2. 마우스 휠 카메라 줌 인,아웃 기능.
3. 마우스 오른쪽 버튼 클릭 후 카메라 회전.
- x,y축 회전
- x축 회전의 한계치 설정.
2. 마우스 휠 카메라 줌 인,아웃
Input에는 마우스 휠에대한 반환값도 제공해주고있다.
Input.GetAxis("Mouse ScrollWheel");
반환값은 float로 반환되며 휠을 위로 굴릴경우 양수의 값이,
밑으로 굴릴경우 음수의 값이 반환된다.
이를활용하여 줌 인,아웃 기능을 수행할 것이다.
카메라맨과 카메라의 거리를 유지해주는 Distance라는 변수에
휠을 위로 굴릴경우 Distance를 감소시켜주어 줌 인 기능을 수행하고,
휠을 밑으로 굴릴경우 Distance를 증가시켜주어 줌 아웃 기능을 수행하여 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class Axis : MonoBehaviour { public float ZoomSpeed; // 줌 스피드. public float Distance; // 카메라와의 거리. private Vector3 AxisVec; // 축의 벡터. private Transform MainCamera; // 카메라 컴포넌트. void Start() { MainCamera = Camera.main.transform; } void Update() { Zoom(); } // 카메라 줌. void Zoom() { Distance += Input.GetAxis("Mouse ScrollWheel") * ZoomSpeed * -1; Distance = Mathf.Clamp(Distance, 5f, 20f); AxisVec = transform.forward * -1; AxisVec *= Distance; MainCamera.position = transform.position + AxisVec; } } | cs |
휠을 위로 굴렸을 때 줌 인 효과를 내고 싶다면 Distance에 값을 그대로 더해주면 안된다.
휠을 위로 굴리면 반환값이 양수 값이기 때문에 Distance는 자연히 커지게 되고
줌 인 효과가 아닌 줌 아웃 효과가 나타나게 된다.
그렇기 때문에 Distance += 휠 값 * 줌 스피드 * -1;
-1을 곱해줌으로써 음수 값으로 만들고 휠을 위로 굴렸을 때 Distance값이 감소하게 된다.
Mathf.Clamp함수는 값을 제한해주는 함수이다.
Mathf.Clamp(Value, Min, Max);
Value는 값을 제한해줄 값을 집어넣고, Min은 그 값의 최소값, Max는 그 값의 최대 값을 지정해 준다.
결과
'Unity3D > Project' 카테고리의 다른 글
[Unity3D] 조이스틱으로 캐릭터 조종하기. [Part 1] (6) | 2017.03.10 |
---|---|
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 4] (3) | 2017.03.08 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 2] (0) | 2017.03.07 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 1] (0) | 2017.03.06 |
[Unity3D] 캐릭터 움직임, 충돌체크, 물리엔진사용 X [Part 5] (0) | 2017.03.02 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 2]
※ 주의
이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.
기능정리
1. 플레이어를 따라오는 카메라.
1.5. 플레이어의 움직임.
2. 마우스 휠 카메라 줌 인,아웃 기능.
3. 마우스 오른쪽 버튼 클릭 후 카메라 회전.
- x,y축 회전
- x축 회전의 한계치 설정.
1.5 플레이어의 움직임.
플레이어부터 움직여 보도록 하자.
카메라가 잘 따라오는지 확인하려면 플레이어가 움직여야 되지 않는가?
Player스크립트를 하나 만들어준다.
이 스크립트에는 2가지 함수가 들어갈 것이다.
1. Run();
2. Rotation();
첫 번째 함수는 플레이어를 움직이게 만드는 함수이고,
두 번째 함수는 플레이어에게 회전을 주어서 원하는 방향으로 이동할수 있게 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class Player : MonoBehaviour { public float Speed; // 움직이는 스피드. private Transform Vec; // 카메라 벡터. private Vector3 MovePos; // 플레이어 움직임에 대한 변수. void Init() { MovePos = Vector3.zero; } void Start() { Vec = GameObject.Find("CameraVector").transform; Init(); } void Update () { Run(); } // 플레이어 움직임. void Run() { int ButtonDown = 0; if (Input.GetKey(KeyCode.LeftArrow)) ButtonDown = 1; if (Input.GetKey(KeyCode.RightArrow)) ButtonDown = 1; if (Input.GetKey(KeyCode.UpArrow)) ButtonDown = 1; if (Input.GetKey(KeyCode.DownArrow)) ButtonDown = 1; // 플레이어가 움직임. 버튼에서 손을 땠을 때 Horizontal, Vertical이 0으로 돌아감으로써 // 플레이어의 회전상태가 다시 원상태로 돌아가지 않게 하기 위해서. if (ButtonDown != 0) Rotation(); else return; transform.Translate(Vector3.forward * Time.deltaTime * Speed * ButtonDown); } // 플레이어 회전. void Rotation() { MovePos.Set(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); // 벡터 셋팅. Quaternion q = Quaternion.LookRotation(Vec.TransformDirection(MovePos)); // 회전 if (MovePos != Vector3.zero) transform.rotation = q; } } | cs |
1. float Speed; 플레이어가 움직이려면 힘이 필요하다. Speed변수를 하나 만들어준다.
2. Transform Vec; 카메라 벡터는, 카메라가 회전한다고 해서 플레이어의 벡터가 달라지는것이 아니므로, 카메라의 벡터를 이용하여 플레이어를 이동시켜주기 위한 변수이다.
3. Vector3 MovePos; 키의 입력을 받아서 플레이어의 벡터를 셋팅해줄 변수이다.
Run() 함수 안에 ButtonDown변수는 키 입력에 반응해 값을 대입 받는다.
키 입력을 받지 않으면 값이 0으로 들어가 플레이어는 움직일수 없게 된다.
반대로 키 입력을 받아 ButtonDown변수에 0이 아닌 값이 들어간다면 플레이어는 움직이게 된다.
그리고, 회전 함수도 함께 수행된다.
ButtonDown변수가 0이 아닐때에만 회전함수를 수행하는 이유는
MovePos에 Horizontal, Vertical로 값을 입력받기 때문이다.
Horizontal은 ←,→에 입력에 따라 -1 ~ +1 의 값이 들어간다.
(※ Vertical은 ↑,↓)
키(Horizontal)를 입력받지 않을 때에는 반환 값이 0으로 들어가는데, 이때 회전 함수가 키 입력(Input.GetKey)에 상관없이 수행된다면 Horizontal에 반환 값 0을 입력받아 플레이어가 다시 원래의 벡터 방향으로 회전하게 된다.
이것을 방지해 주기 위한 처리이다.
1 2 3 4 5 6 7 8 9 10 11 12 | void Run() { int ButtonDown = 0; if (Input.GetKey(KeyCode.LeftArrow)) ButtonDown = 1; if (Input.GetKey(KeyCode.RightArrow)) ButtonDown = 1; if (Input.GetKey(KeyCode.UpArrow)) ButtonDown = 1; if (Input.GetKey(KeyCode.DownArrow)) ButtonDown = 1; Rotation(); transform.Translate(Vector3.forward * Time.deltaTime * Speed * ButtonDown); } | cs |
회전 함수를 예외처리 없이 수행했을 경우.
대각선으로 이동하다가 키에 손을 때면 게속 정면을 바라보게 된다.
다음은 회전함수를 살펴보도록 하자.
MovePos.Set을 활용하여 Horizontal과 Vertical의 입력 값을 셋팅한다.
그리고 쿼터니언(Quaternion)을 활용하여 플레이어에게 회전값을 줄것이다.
Quaternion.LookRotation( Vector3 ); - 이 함수는 인자에 들어온 벡터의 방향으로 물체를 회전시켜준다.
만약 A라는 물체가 B라는 물체를 바라보고 싶을때 B까지의 벡터를 구해 이 함수의 인자로 넣어주면
A는 B를 바라보도록 회전시켜준다.
TransformDirection( Vector3 ); - 이 함수는 인자로 들어온 값을 로컬공간에서 월드공간으로 방향을 변환해준다.
인자로 MovePos를 넣어, CameraVector오브젝트의 벡터를 현재 플레이어의 벡터로 활용하는 것이다.
그뒤 transform.rotation에 회전 값 q를 넣어서 적용시켜주면 적절히 회전하게 된다.
'Unity3D > Project' 카테고리의 다른 글
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 4] (3) | 2017.03.08 |
---|---|
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 3] (3) | 2017.03.08 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 1] (0) | 2017.03.06 |
[Unity3D] 캐릭터 움직임, 충돌체크, 물리엔진사용 X [Part 5] (0) | 2017.03.02 |
[Unity3D] 캐릭터 움직임, 충돌체크, 물리엔진사용 X [Part 4] (0) | 2017.03.02 |
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 1]
※ 주의
이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.
기능정리
1. 플레이어를 따라오는 카메라.
1.5. 플레이어의 움직임.
2. 마우스 휠 카메라 줌 인,아웃 기능.
3. 마우스 오른쪽 버튼 클릭 후 카메라 회전.
- x,y축 회전
- x축 회전의 한계치 설정.
완성작 미리보기.
1. 플레이어를 따라오는 카메라.
카메라가 플레이어와 아에 멀리 떨어져 있어도 따라오는 카메라를 만들어야 한다.
카메라가 직접 플레이어를 따라가게 만들지 않을것이다.
카메라맨이라는 빈 객체를 만들어서 이 객체가 플레이어를 직접적으로 따라갈 것이고,
카메라는 카메라맨과 일정 거리를 유지한체 따라다닐 것이다.
이러한 번거로운 작업을 할 필요 없이 '카메라를 플레이어의 자식으로 두면 되는거 아닌가요?' 라고 묻는다면
그냥 따라다니기만 할거라면 그렇게 해도 되지만, 우리는 줌 인/아웃 또는 카메라를 회전시킬 것이기 때문에
이러한 과정이 필요하다고 말해두겠다.
물론 이렇게 넣는다고 해서 이러한 과정이 불 가능해 지는것은 아니지만, 매우 귀찮은 코딩이 필요해 지기 때문에
그러한 과정은 피하도록 하겠다.
1. 빈 오브젝트를 만든다. - 이름은 CameraMan
2. 또다시 빈 오브젝트를 만든다. - 이름은 CameraVector
3. 또다시 빈 오브젝트를 만든다. - 이름은 Axis
4. CameraMan에 자식으로 CameraVector를 넣는다.
5. CameraMan에 자식으로 Axis를 넣는다.
6. Axis의 자식으로 Camera를 넣는다. (이 카메라는 메인카메라이다.)
재료를 만들었으니 이제 스크립트를 작성해 보자.
스크립트의 이름은 CameraMan이다.
이 스크립트는 CameraMan오브젝트에 넣으면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraMan : MonoBehaviour {
// 공개
public float MoveSpeed; // 플레이어를 따라오는 카메라 맨의 스피드.
// 비공개
private Transform Target; // 플레이어의 트랜스 폼.
private Vector3 Pos; // 자신의 위치.
void Start()
{
// Player라는 태그를 가진 오브젝트의 transform을 가져온다.
Target = GameObject.FindGameObjectWithTag("Player").transform;
}
// 플레이어를 따라다님.
void Update ()
{
Pos = transform.position;
transform.position += (Target.position - Pos) * MoveSpeed;
}
}
|
cs |
(플레이어의 위치 - 자신의 위치)를 빼주면 현재 카메라맨의 위치에서 플레이어의 벡터(방향)가 구해진다.
그 벡터를 향해 값을 플러스(+) 해주면 카메라맨은 플레이어를 쫓아가게 된다.
* MoveSpeed는 카메라맨이 플레이어를 쫓아가는 스피드다.
※ 플레이어의 Transform을 가져오기위한 설정.
플레이어는 그냥 큐브를 하나 만들어주고 이름을 Player로 바꿔주고,
태그를 Player로 바꿔주면 된다.
그 뒤 실행을 해보면
※ CameraMan스크립트 컴포넌트에서 MoveSpeed를 설정해주지 않으면 카메라맨이 움직이지 않는다.
카메라맨이 플레이어를 따라가지만, 카메라에 비치지 않는것을 확인 할 수 있다.
이것은 당연한 것이다. 우리는 아직 카메라맨과 카메라와의 유지거리를 설정해주지 않았기 때문이다!
카메라의 유지거리를 설정하기 위한 스크립트를 짜보도록 하자.
Axis스크립트.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Axis : MonoBehaviour {
// 공개
public float Distance; // 카메라와의 거리.
// 비공개
private Vector3 AxisVec; // 축의 벡터.
private Transform MainCamera; // 카메라 컴포넌트.
void Start()
{
MainCamera = Camera.main.transform;
}
void Update()
{
DisCamera();
}
void DisCamera()
{
AxisVec = transform.forward * -1;
AxisVec *= Distance;
MainCamera.position = transform.position + AxisVec;
}
}
|
cs |
현재 플레이어의 Position == CameraMan의 Position == Axis의 Position은 같다.
왜냐하면 CameraMan이 플레이어를 추적하기 때문이다.
Axis가 같은 이유는 CameraMan의 자식이기 때문이다.
그렇기 때문에 Axis의 전방벡터 (transform.forward)는 플레이어의 전방벡터 이기도 하다.
이러한 전방벡터에 -1을 곱한다는것은 플레이어의 후방벡터의 방향을 뜻한다.
플레이어가 보고있는 방향의 반대 방향으로 Distance 변수의 거리만큼 카메라를 벌려주면
카메라가 멀리서 플레이어를 바라보는것처럼 만들수 있다.
결과
'Unity3D > Project' 카테고리의 다른 글
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 3] (3) | 2017.03.08 |
---|---|
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 2] (0) | 2017.03.07 |
[Unity3D] 캐릭터 움직임, 충돌체크, 물리엔진사용 X [Part 5] (0) | 2017.03.02 |
[Unity3D] 캐릭터 움직임, 충돌체크, 물리엔진사용 X [Part 4] (0) | 2017.03.02 |
[Unity3D] 캐릭터 움직임, 충돌체크, 물리엔진사용 X [Part 3] (1) | 2017.03.02 |
[Unity3D] 캐릭터 움직임, 충돌체크, 물리엔진사용 X [Part 5]
※ 주의
이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.
메뉴
1. 움직임 적용.
- Horizontal을 이용한 움직임.
2. 중력 적용.
- 점프에 의한 중력.
- 낙하에 의한 중력.
3. 충돌 적용. (레이 캐스트로 충돌체크.)
- 점프로 인한 위쪽블록과의 충돌.
- 낙하로 인한 블록과의 충돌.
- 오른쪽, 혹은 왼쪽으로 움직일때에 벽과 충돌.
4. 점프
- 점프로 인한 충돌체크 및 중력적용.
5. 좌,우 충돌체크.
4. 좌,우 충돌체크.
별로 어려운건 없다.
기존에 만들어두었던 RayCastFire함수를 이용하면 된다.
하지만 몇 가지 추가하거나 바꿔줄 필요는 있다.
현재 x방향으로 레이캐스트를 3개를 쏘고있다.
그리고 이제 할 좌,우 충돌에 대해서도 마찬가지로 3개의 레이캐스트를 쏠 것이다.
for문을 하나 더 만들어서 함수를 호출해버리면 아무래도 프로그램에 부담이걸려 돌아오는 반응에 공백이 생길수
있으므로, for문을 RayCastFire함수 안으로 넣으려고 한다.
그리고 전체적인 구성을 조금 바꿀 것이다.
결과
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour {
// 공개
public float Speed; // 좌, 우로 움직이는 스피드.
public float JumpSpeed; // 점프 할때에 힘.
public float Gravity; // 작용하는 중력.
// 디버그
public float RayTime; // 그려준 레이 지속시간.
public bool isDrawX; // 좌,우 쏘는 레이캐스트 보기.
public bool isDrawY; // 위,아래로 쏘는 레이캐스트 보기.
public Color ColorX; // 레이의 색깔.
public Color ColorY; // 레이의 색깔.
// 비공개
private Vector2 Pos; // 플레이어가 실직적으로 움직일 좌, 우 벡터.
private Vector2 Dir; // 점프 및 낙하 여부의 벡터.
private Vector2 Radius; // 플레이어의 x,y의 반지름.
private float H; // Horizontal.
private bool isGround; // 현재 땅이냐? true 땅이 아니냐? false
// 각종 값 초기화.
void Init()
{
ColorX = Color.blue;
ColorY = Color.red;
Pos = Vector2.zero;
Dir = Vector2.down;
Radius = new Vector2(transform.localScale.x * 0.5f, transform.localScale.y * 0.5f);
H = 0;
isGround = false;
}
void Start()
{
Init();
}
void Update()
{
H = Input.GetAxis("Horizontal");
if (Input.GetButtonDown("Jump") && isGround)
{
Pos.y = JumpSpeed;
Dir = Vector2.up;
}
CollisionCheck();
Move();
}
// 좌, 우 움직임.
void Move()
{
Pos.Set(H * Speed, Pos.y);
transform.Translate(Pos * Time.deltaTime);
}
// 충돌 체크를 위한 레이 캐스트.
void CollisionCheck()
{
RayCastFire(Dir, Radius.y + 0.1f, Color.blue); // 위,아래
RayCastFire(DirX(), Radius.x + 0.1f, Color.yellow); // 좌, 우.
}
// 플레이어 방향 벡터를 결정해 준다. (좌, 우)
Vector2 DirX()
{
if (H < 0)
return Vector2.left;
else if (H > 0)
return Vector2.right;
return Vector2.zero;
}
// 레이캐스트를 발사한다.
void RayCastFire(Vector2 _Dir, float _length, Color _color )
{
if (_Dir == Vector2.zero)
return;
RaycastHit Hit;
for (int i = -1; i < 2; i++)
{
Vector2 MyPos = transform.position;
// 레이 발사위치를 정하는 구문.
if (_Dir == Vector2.right || _Dir == Vector2.left)
MyPos = new Vector2(MyPos.x, MyPos.y + (Radius.y * i)); // 좌,우 충돌 레이.
else
MyPos = new Vector2(MyPos.x + (Radius.x * i), MyPos.y); // 위,아래 충돌 레이.
// 레이를 그려주는 함수.
DrawRay(MyPos, _Dir, _length, _color);
if (Physics.Raycast(MyPos, _Dir, out Hit, _length))
{
// Ray를 발사 했는데 땅에 맞았음.
if (Hit.transform.gameObject.layer == 8)
{
if (_Dir == Vector2.right || _Dir == Vector2.left)
{
H = 0;
return;
}
// 플레이어가 땅에 있으면 함수 종료.
if (isGround)
return;
Transform Target = Hit.transform;
if (_Dir == Vector2.down)
{
// 충돌한 블럭의 위에 정착.
transform.position = new Vector2(transform.position.x, Target.position.y + (Target.localScale.y * 0.5f) + _length);
Pos.y = 0; // 중력이 작용했던 값에 대해 0으로 초기화.
isGround = true; // 이제 땅에 있다고 표시.
return;
}
// 충돌한 블럭 밑으로 이동.
transform.position = new Vector2(transform.position.x, Target.position.y - (Target.localScale.y * 0.5f) - _length);
Pos.y = 0;
break;
}
}
}
if (_Dir == Vector2.right || _Dir == Vector2.left)
return;
// Ray를 발사 했는데 땅에 맞지 않았음.
isGround = false;
Pos.y -= Gravity * Time.deltaTime;
if (Pos.y <= 0)
Dir = Vector2.down;
}
// 레이를 그려준다.
void DrawRay(Vector2 _MyPos, Vector2 _Dir, float _length, Color _color)
{
if (_Dir == Vector2.left || _Dir == Vector2.right)
{
if (isDrawX)
Debug.DrawRay(_MyPos, _Dir * _length, ColorX, RayTime);
}
else
{
if (isDrawY)
Debug.DrawRay(_MyPos, _Dir * _length, ColorY, RayTime);
}
}
}
|
cs |
'Unity3D > Project' 카테고리의 다른 글
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 2] (0) | 2017.03.07 |
---|---|
[Unity3D] RPG게임 카메라 - 줌 인/아웃, 카메라 회전. [Part 1] (0) | 2017.03.06 |
[Unity3D] 캐릭터 움직임, 충돌체크, 물리엔진사용 X [Part 4] (0) | 2017.03.02 |
[Unity3D] 캐릭터 움직임, 충돌체크, 물리엔진사용 X [Part 3] (1) | 2017.03.02 |
[Unity3D] 캐릭터 움직임, 충돌체크, 물리엔진사용 X [Part 2] (0) | 2017.03.02 |