일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- eulerAngles
- 유니티 오브젝트 풀링
- git-lfs
- 유니티 리소스매니저
- Quaternion.Euler
- 알고스팟
- Mathf.Clamp
- 이진트리
- 소스코드 줄번호
- 유니티 머신러닝
- Raycast
- 너비 우선 탐색
- c++
- 유니티 ResourceManager
- 유니티
- c++ 문자열 자르기
- 유니티 InputManager
- 오브젝트 풀링
- LayerMask
- 깊이 우선 탐색
- ML-Agents
- 코드블럭 테마
- 유니티 시야 가림
- LookRotation
- LFS
- unity
- 유니티 Rotate
- 유니티 Collision
- InputManager
- 유니티 Vector3
- 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 |