질문글 : http://gall.dcinside.com/mgallery/board/view/?id=game_dev&no=13203&page=1
// 어느정도 수준으로 글을 써야하는지 몰라서
// 최적화나 그런거 신경안쓰고 최대한 이해하기 쉽게 구현했어
이걸 원한게 맞겠지?
일단 코드랑 에디터 모습 보여주고 설명할게
코드
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 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class Player : MonoBehaviour { public GameObject Origin; public GameObject Controller; public float Speed; private Transform _transform; private GameObject _originObj; private GameObject _controllerObj; private Vector3 _originPos; // Use this for initialization void Start () { _transform = this.transform; } // Update is called once per frame void Update () { Move(); } private void Move() { // 첫 클릭 : 조이스틱 생성 // 이후 클릭 : 이동 // 클릭 끝 : 조이스틱 제거 // 첫 클릭 = Input.GetMouseButtonDown(0) : 클릭 처음 했을때 한번 호출 // 이후 클릭 = Input.GetMouseButton(0) : 클릭하는 중에 호출됨 (클릭 끝나지 않으면 계속 호출) // 클릭 끝 = Input.GetMouseButtonUp(0) : 클릭 끝나면 호출됨 (손 떼면 호출) if (Input.GetMouseButtonDown(0)) { // 첫 클릭 // 1. 클릭된 좌표를 기준 좌표로 설정 // 2. 조이스틱 이미지 생성 // 1. 클릭된 좌표를 기준 좌표로 설정 // 기준 좌표 = 메인카메라 기준으로 마우스 위치를 스크린 좌표를 월드 좌표로 변환 // ScreenToWorldPoint = 스크린 좌표계 -> 월드 좌표계 변환 // Input.mousePosition = 현재 마우스 위치(스크린 좌표계) _originPos = Camera.main.ScreenToWorldPoint(Input.mousePosition); // 2. 클릭된 좌표에 조이스틱 생성 _originObj = Instantiate(Origin, _originPos - (Vector3.forward * _originPos.z), Quaternion.identity); _controllerObj = Instantiate(Controller, _originPos, Quaternion.identity); } else if (Input.GetMouseButton(0)) { // 이후 클릭 // 1. 컨트롤러 현재 클릭 위치로 이동 // 2. 기준 좌표와 이동한 마우스 위치의 방향을 계산 // 3. 해당 방향으로 캐릭터 이동 // 1. 컨트롤러 현재 클릭 위치로 이동 _controllerObj.transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition); _controllerObj.transform.position -= (Vector3.forward * _controllerObj.transform.position.z); // 2. 기준 좌표와 이동한 마우스의 위치의 방향을 계산 // 벡터의 개념을 알고있으면 A-B = B가 A를 보는 방향 // 즉 이동한 마우스 위치 벡터 - 기준 좌표 벡터 = 기준좌표에서 이동한 마우스 위치를 보는 방향 // 방향 = 현재 마우스 위치 (월드 좌표계) - 기준 좌표 Vector3 dir = Camera.main.ScreenToWorldPoint(Input.mousePosition) - _originPos; // dir 벡터의 크기를 1로 만든다 (Normalize) dir.Normalize(); // 3. 해당 방향으로 캐릭터 이동 _transform.position += dir * Speed * Time.deltaTime; } else if (Input.GetMouseButtonUp(0)) { // 클릭 끝 // 1. 조이스틱 제거 Destroy(_originObj); Destroy(_controllerObj); } } } | cs |
에디터
설명은 코드에 써놨는데 이해하기 힘들 수도 있는 부분들을 아래에 적어줄게
벡터나 벡터의 연산은 내가 설명하는 것보다 이해하기 쉽게 쓴 글을 본적있어서 링크로 대체할게
http://lab.gamecodi.com/board/zboard.php?id=GAMECODILAB_Lecture_series&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no=122
http://lab.gamecodi.com/board/zboard.php?id=GAMECODILAB_Lecture_series&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no=123
두 글을 읽었거나 벡터에 대한 개념이 있다면
70번째 줄에서 dir을 Normalize (벡터의 크기를 1로 만든다)를 한 이유를 눈치챘을 수도 있어
그 이유는 내가 원하는 속도로 이동하기를 원하기 때문이야
만약 Normalize를 하지않는다면 니가 기준좌표(하얀색 원, 첫 클릭 위치)에서 컨트롤러(회색 원, 현재 클릭 위치)를 최대한 멀리하면
엄청 빨리 움직이고 최대한 붙이면 엄청 천천히 움직이는거야
어? 나는 그렇게 속도 조절하는게 좋은데?라고 생각하면 Normalize를 하지않고 적절한 보정을 해주고 사용하면 되는거구
Time.deltaTime에 대해서 설명하자면 프레임과 프레임간의 시간이야
이걸 곱해주는 이유를 설명할게
FPS(Frame per second) 즉 1초에 몇 프레임이냐라는 거잖아
그런데 우리가 만든 게임을 플레이하는 사람마다 성능이 다른 모바일 기기, PC를 사용하잖아
갤럭시s3 쓸수도 있고 갤럭시노트8 쓸수도 있고
갤럭시s3는 FPS가 20이라 Move 함수가 30번 호출되고 갤럭시노트8는 FPS가 120이라 Move가 120번 호출된다고 생각해봐
싱글 플레이 게임이면 밸런스 맞추기 힘들 테고 멀티 플레이면 갤럭시s3 입장에서는 갤럭시노트8이 스피드 핵처럼 보일꺼야
그래서 Time.deltaTime을 곱해서 이동하면 1초에 speed 만큼 이동하게 만드는거야
이렇게 되면 30번 호출되나 120번 호출되나 같은 거리 이동을 하거든
FPS가 1초간 프레임수니까 프레임 수 만큼 사이 시간(deltaTime)과 speed를 곱하고 더하면 당연히 1초에 speed만큼 움직이는 거
ㅋㅋㅋ 당연한건데 더 이해하기 쉽게 참고 자료(?)라고 생각해둬
다른거 이해안가는거 있으면 댓글 달아줘
친절추
우와오.... 정독하고 올께! 고마워! 근데 내가 아무것도 모르는 초짜라 많이 답답할수도 있어
이싸카 // 모르면 그냥 넘어가지말고 꼭 물어봐 내가 설명할 수 있는거면 최대한 쉽게 설명해줄게
난 유니티애셋에서 돈주고 유명한 터치시스템 샀는데 그게 혹시나 유튜브보고 따라만는것이 성능이 낮으면 어쩌나 싶어서... 모바일게임 안그래도 조이스틱 조작이 구리다고 생각하거든... 어떻게 생각해?
카피독 // 조작감이 모바일 기기상의 불편함이 아니라 내가 잘못만들어서 불편을 준다면 사람들의 의견을 들어보고 개선 할 수있으니까 상관없다구 본다. 나같은 경우는 에셋을 잘 안사지만 사게될때는 시간적 이득이나 내가 못하는 것에 대해서만 사는 편이라
감사합니다. 저도 필요했던건데...