일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 유니티 ResourceManager
- 소스코드 줄번호
- 오브젝트 풀링
- 유니티 InputManager
- InputManager
- LayerMask
- ML-Agents
- 유니티 리소스매니저
- LFS
- c++
- eulerAngles
- LookRotation
- 유니티 머신러닝
- 유니티 시야 가림
- unity
- 깊이 우선 탐색
- 너비 우선 탐색
- 유니티 Vector3
- 유니티
- Raycast
- 이진트리
- 알고스팟
- c++ 문자열 자르기
- git-lfs
- Quaternion.Euler
- 유니티 오브젝트 풀링
- 유니티 Collision
- 유니티 Rotate
- 코드블럭 테마
- Mathf.Clamp
- Today
- Total
무민은귀여워
[유니티] 시야를 가리는 물체 판별 및 카메라 이동 본문
좌클릭 시 플레이어를 이동시키고, 카메라와 플레이어 사이 시야를 가리는 물체가 있으면 카메라를 물체 앞으로 옮겨준다.
1. Define
public class Define { public enum MouseEvent { Press, Click, } public enum CameraMode { QuarterView, } }
2. CameraController
_delta : 카메라의 기준 위치
_player : 플레이어. 툴 내에서 사용할 캐릭터 오브젝트를 지정
LateUpdate()
플레이어 이동 시 깜빡거리는 현상은, 플레이어 키입력에 따른 update()와 카메라 update() 중 어느것을 먼저 실행할지 정해지지 않아서이다.
LateUpdate()로 카메라의 업데이트를 나중에 실행하도록해서 깜빡임을 없앤다.
Raycast
레이캐스트로 플레이어로부터 카메라까지의 경로중 막히는 물체가 있는지 검사한다. 막히는 물체가 있다면, 시야를 가리는 물체이므로 카메라를 그 물체 앞으로 이동시킨다.
* transform.LookAt(_player.transform) : 카메라가 플레이어를 바라보도록 회전
public class CameraController : MonoBehaviour { [SerializeField] Define.CameraMode _mode = Define.CameraMode.QuarterView; [SerializeField] Vector3 _delta = new Vector3(0.0f, 6.0f, -5.0f); [SerializeField] GameObject _player = null; void Start() { } void LateUpdate() { if (_mode == Define.CameraMode.QuarterView) { RaycastHit hit; if (Physics.Raycast(_player.transform.position, _delta, out 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); } } } public void SetQuarterView(Vector3 delta) { _mode = Define.CameraMode.QuarterView; _delta = delta; } }
3. InputManager
InputManager에 마우스 Action 추가
public class InputManager { public Action KeyAction = null; public Action<Define.MouseEvent> MouseAction = null; bool _pressed = false; public void OnUpdate() { if (Input.anyKey && KeyAction != null) KeyAction.Invoke(); if (MouseAction != null) { if (Input.GetMouseButton(0)) { MouseAction.Invoke(Define.MouseEvent.Press); _pressed = true; } else { if (_pressed) MouseAction.Invoke(Define.MouseEvent.Click); _pressed = false; } } } }
4. PlayerController
_moveToDest : 클릭 시 이동가능여부
_destPos : 이동위치
MouseAction에 OnMouseClicked()을 등록한다
클릭 이동일 경우, Update()에서 플레이어 위치를 이동시킨다
OnMouseClicked()
void OnMouseClicked(Define.MouseEvent evt) { if (evt != Define.MouseEvent.Click) return; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); Debug.DrawRay(Camera.main.transform.position, ray.direction * 100.0f, Color.red, 1.0f); RaycastHit hit; if (Physics.Raycast(ray, out hit, 100.0f, LayerMask.GetMask("Wall"))) { _destPos = hit.point; _moveToDest = true; } }
이동
잘못된 예
Update() 내에서 이동거리를 아래처럼 _speed * Time.deltaTime 를 직접사용하면, 이동거리가 dir.magnitude보다 큰 경우가 생길 수 있어 캐릭터가 왔다갔다 거리는 문제가 생긴다.
// 수정필요 예시 - 이동완료 직전 캐릭터 왔다갔다 Vector3 dir = _destPos - transform.position; if (dir.magnitude < 0.0001f) { _moveToDest = false; } else { transform.position += dir.normalized * _speed * Time.deltaTime; transform.LookAt(_destPos); }
수정된 예
Mathf.Clamp()를 이용해서 이동거리를 dir.magnitude 범위 내로 조정한다.
* Mathf.Clamp(value, min, max) : value가 최소값보다 작으면 최소값을, 최대값보다 크면 최대값을 반환
플레이어 방향은 Quaternion.Slerp() 와 Quaternion.LookRotation()으로 자연스럽게 바뀌게 한다
if (_moveToDest) { Vector3 dir = _destPos - transform.position; if (dir.magnitude < 0.0001f) { _moveToDest = false; } else { float moveDist = Mathf.Clamp(_speed * Time.deltaTime, 0, dir.magnitude); transform.position += dir.normalized * moveDist; transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(dir), 20 * Time.deltaTime); } }
5. 실행
재생 전 시야를 막는 물체가 있는 경우

재생 후 시야를 막는 물체 앞으로 카메라를 이동시킨 경우

'IT > Unity' 카테고리의 다른 글
[유니티] 오브젝트 풀링 (0) | 2022.05.24 |
---|---|
[유니티] 충돌 Collision / Trigger / Raycast / LayerMask (0) | 2022.05.17 |
[유니티] ResourceManager (0) | 2022.05.17 |
[유니티] InputManager (0) | 2022.05.17 |
[유니티] 회전 rotation (0) | 2022.05.16 |