질문글 : http://gall.dcinside.com/mgallery/board/view/?id=game_dev&no=13203&page=1


// 어느정도 수준으로 글을 써야하는지 몰라서

// 최적화나 그런거 신경안쓰고 최대한 이해하기 쉽게 구현했어



viewimage.php?id=2abcdd23dad63db0&no=29bcc427bd8777a16fb3dab004c86b6fe0f25512895f218fe4112c1029e51c1473504281c34c82dbc1d19a0fa54c4023b650235ef6e6351a7590

이걸 원한게 맞겠지?


일단 코드랑 에디터 모습 보여주고 설명할게


코드

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


에디터

viewimage.php?id=2abcdd23dad63db0&no=29bcc427bd8777a16fb3dab004c86b6fe0f25512895f218fe4112c1029e51c14735042c5911defd8c2d59f0da4244128313e3042a06c2dc62314bb7c4cd6



설명은 코드에 써놨는데 이해하기 힘들 수도 있는 부분들을 아래에 적어줄게


벡터나 벡터의 연산은 내가 설명하는 것보다 이해하기 쉽게 쓴 글을 본적있어서 링크로 대체할게
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번 호출되나 같은 거리 이동을 하거든

viewimage.php?id=2abcdd23dad63db0&no=29bcc427bd8777a16fb3dab004c86b6fe0f25512895f218fe4112c1029e51c14735042c5911defd8c2d59f0da4244128313e3f42f53d2a982346bb7c4cd6

FPS가 1초간 프레임수니까 프레임 수 만큼 사이 시간(deltaTime)과 speed를 곱하고 더하면 당연히 1초에 speed만큼 움직이는 거  

ㅋㅋㅋ 당연한건데 더 이해하기 쉽게 참고 자료(?)라고 생각해둬


다른거 이해안가는거 있으면 댓글 달아줘