섹션5. Camera
위 글은 인프런에 있는 Rookiss님의 [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진 강의를 듣고 남긴 필기입니다.
쿼터뷰 형태의 인게임 카메라를 구성
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
public class CameraController : MonoBehaviour
{
[SerializeField]
public Define.CameraMode _mode = Define.CameraMode.QuarterView;
[SerializeField]
public Vector3 _delta = new Vector3(0,6.0f,-5.0f);
[SerializeField]
private GameObject _player = null;
// Update에서하면 화면에 덜덜거리는 현상이 발생_왜?
// => 이동을 담당하는 Managers.Update()안의 _input.OnUpdate();보다 먼저할지 뒤에할지 미정이기 때문에, 순서가 매번 일정하지 않아서.
private void LateUpdate()
{
if (_mode == Define.CameraMode.QuarterView)
{
if (Physics.Raycast(_player.transform.position, _delta, out var hit, _delta.magnitude, LayerMask.GetMask("Wall")))
{
float dist = (hit.point - _player.transform.position).magnitude * 0.8f;
transform.position = _player.transform.position + _delta.normalized * dist;
}
else
{
// 플레이어를 따라가도록
transform.position = _player.transform.position + _delta;
// 플레이어를 주시하도록
transform.LookAt(_player.transform.position);
}
}
}
public void SetQuarterView(Vector3 delta)
{
_mode = Define.CameraMode.QuarterView;
_delta = delta;
}
}
InputManager도 수정. 마우스 클릭을 통한 이동을 구현
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
public class InputManager
{
public Action KeyAction = null;
public Action<Define.MouseEvent> MouseAction = null;
private bool _pressed = false;
public void OnUpdate()
{
// 어떠한 입력이라도 있고, KeyAction이 비어있지 않다면,
if (Input.anyKey && KeyAction != null)
KeyAction.Invoke();
if (MouseAction != null)
{
if (Input.GetMouseButton(0)) // 마우스가 눌린다면,
{
MouseAction.Invoke(Define.MouseEvent.Press); // (1)일단 Press에 해당하는 이벤트를 Invoke
_pressed = true; // (2)눌렸다가,
}
else
{
if(_pressed) MouseAction.Invoke(Define.MouseEvent.Click); // 떨어질 때, Click 이벤트를 Invoke
_pressed = false;
}
}
}
}
덩달아 PlayerController도 수정
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
public class PlayerController : MonoBehaviour
{
[SerializeField]
private float _speed = 10.0f;
private bool _moveToDest = false;
private Vector3 _destPos;
void Start()
{
// InputManager에서 Event 함수를 실행하도록 맡긴다.
Managers.Input.KeyAction -= OnKeyboard;
Managers.Input.KeyAction += OnKeyboard;
Managers.Input.MouseAction -= OnMouseClicked;
Managers.Input.MouseAction += OnMouseClicked;
}
private void Update()
{
if (_moveToDest)
{
Vector3 dir = _destPos - transform.position;
if (dir.magnitude < 0.0001f) { _moveToDest = false; } // 거리는 float, 이렇게 매우 적은 오차에 든다면 도착한것으로 간주.
else // 그렇지 않다면, 아직 도착하지 않은것이니 이동하도록.
{
float moveDest = Mathf.Clamp(_speed * Time.deltaTime, 0, dir.magnitude);
transform.position += dir.normalized * moveDest;
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(dir), 10 * Time.deltaTime); // 도착지를 바라보도록.
}
}
}
private float _slerp = 0.2f;
void OnKeyboard()
{
if (Input.GetKey(KeyCode.W))
{
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Vector3.forward), _slerp);
transform.position += Vector3.forward * (Time.deltaTime * _speed);
}
if (Input.GetKey(KeyCode.A))
{
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Vector3.left), _slerp);
transform.position += Vector3.left * (Time.deltaTime * _speed);
}
if (Input.GetKey(KeyCode.S))
{
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Vector3.back), _slerp);
transform.position += Vector3.back * (Time.deltaTime * _speed);
}
if (Input.GetKey(KeyCode.D))
{
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Vector3.right), _slerp);
transform.position += Vector3.right * (Time.deltaTime * _speed);
}
_moveToDest = false;
}
void OnMouseClicked(Define.MouseEvent mouseEvent)
{
if (mouseEvent != Define.MouseEvent.Click) return; // Define.MouseEvent.Click이 아닌 MouseEvent라면 무시하도록.
#region Moving By Raycasting
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(Camera.main.transform.position, ray.direction * 100.0f, Color.red,1.0f);
if (Physics.Raycast(ray, out var hit, 100.0f, LayerMask.GetMask("Wall")))
{
//Debug.Log($"Raycast Camera @ {hit.collider.gameObject.tag}");
_destPos = hit.point;
_moveToDest = true;
}
#endregion
}
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.