Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
Tags
- static_cast
- std::unordered_map
- rookiss
- 트리
- 알고리즘
- 프래그멘테이션
- 기술면접
- 해쉬맵
- Queue
- 큐
- 멀티쓰레드
- thread
- list
- 스택
- MonoBehaviour
- vector
- 리스트
- 힙영역
- map
- 객체지향
- 자료구조
- 스택영역
- 차이점
- 배열
- 벡터
- 공부
- 반복문
- c#
- 인프런
- std::map
Archives
- Today
- Total
호빵의 IT 개발소
[MMO RPG] RayCast를 이용한 마우스 이동 및 벽에서 카메라 줌인 본문
지금 까지 사용했던 문법을 응용하여 쉽게 구현할 수 있습니다.
InputManager.cs
-InputManager를 통해 마우스가 눌렸을 때 이벤트를 받습니다.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InputManager
{
public Action<Define.MouseEvent> MouseAction = null;
bool _Pressed = false; //마우스 누른 상태는 기본값 false
public void OnUpdate()
{
if (MouseAction != null) //press와 click
{
if (Input.GetMouseButton(0)) //마우스 좌클릭
{
MouseAction.Invoke(Define.MouseEvent.Press);
_Pressed = true;
}
else
{
if (_Pressed)
MouseAction.Invoke(Define.MouseEvent.Click);
_Pressed = false;
}
}
}
}
Define.cs
-마우스 이벤트를 추가하여 관리합니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Define
{
public enum CameraMode //카메라 모드
{
QuarterView,
}
public enum MouseEvent //마우스 이벤트
{
Press, //누르고있는 상태
Click, //한번 짧게 누른 상태
}
}
CameraController.cs
-카메라 이벤트에서는 플레이어가 벽(Layer : "Wall")에 가려졌을 때 확대하여 플레이어가 보일 수 있도록 코드를 작성하였습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
[SerializeField]
Define.CameraMode _mode = Define.CameraMode.QuarterView; //Define에서 쿼터뷰 정의를 가져옴
[SerializeField]
Vector3 _delta = new Vector3(0.0f, 7.0f, -6.0f); //_delta 방향 벡터
[SerializeField]
GameObject _player; //카메라가 따라갈 플레이어를 유니티에서 드로그드롭으로 설정
void LateUpdate() //플레이어의 움직임 다음으로 update문이 실행되도록 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; //벽에서 0.8f 띄운 거리
transform.position = _player.transform.position + _delta.normalized * dist;
}
else
{
transform.position = _player.transform.position + _delta; //플레이어의 좌표를 가져와서 우리가 설정한 _delta라는 방향 벡터를 더해준다
transform.LookAt(_player.transform); //카메라가 무조건 플레이어의 좌표를 주시한다.
}
}
}
}
PlayerController.cs
-여기서는 Raycast를 이용하여 "Wall" layer인 경우 마우스클릭하였을 때 그 방향으로 이동하도록 설정하였습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField]
float _speed = 10.0f;
bool _moveToDest = false;
Vector3 _destPos;
void Start()
{
Managers.Input.MouseAction -= OnMouseClicked; //다른 곳에서 구독신청 되어있으면 끊어주고
Managers.Input.MouseAction += OnMouseClicked; //InputManager에게 마우스가 눌리면 이 함수를 실행해주세요
}
void Update()
{
if (_moveToDest)
{
Vector3 dir = _destPos - transform.position; //destPos에서 Player위치를 빼주면 방향벡터가 나온다.
if (dir.magnitude < 0.0001f) //목적지에 도착했다면 (방향벡터에 오차범위 때문에 아주 작은 값을 적어줍니다.)
{
_moveToDest = false; //움직임 멈춤
}
else //도착하지 않았으니 조금 더 움직여야 한다.
{
float moveDist = Mathf.Clamp(_speed * Time.deltaTime, 0, dir.magnitude); //_speed * Time.deltaTime는 min(0)과 max(dir.magnitude) 사이의 값을 보장해야 한다.(캐릭터 떨림 현상)
transform.position = transform.position + dir.normalized * moveDist; //dir이 지금 방향벡터이지만 크기가 1로 바꾼 상태가 아니므로 normalized를 통해 크기가 1짜리인 하지만 방향은 똑같은 방향벡터가 나옴 그래서 moveDist 만큼을 방향벡터로 이동
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(dir), 10 * Time.deltaTime); //slerp를 통해 플레이어 좌표, 내가 바라보는 방향, 적당한 회전 수치 순서로 부드럽게 회전 구현
transform.LookAt(_destPos); //플레이어가 _destPos 방향을 보면서 이동
}
}
}
void OnMouseClicked(Define.MouseEvent evt)
{
if (evt != Define.MouseEvent.Click)
return;
//RayCasting
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;
}
}
}
벽 뒤에 플레이어가 있을 때

벽이 없는 곳으로 이동했을 때

※벽과 바닥은 Layer가 꼭 "Wall"로 되어있어야 합니다!
---------------------------------------------------------------------------------------------------------------------------
참고 : [인프런] Rookiss님의 [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진
'C#, 유니티 > MMO RPG 만들기 기초(클라이언트)' 카테고리의 다른 글
| [MMO RPG] 간단한 점수 UI 만들기 (0) | 2022.01.27 |
|---|---|
| [MMO RPG] Animator (0) | 2022.01.27 |
| [MMO RPG] Camera 설정(Quater View) (0) | 2022.01.24 |
| [MMO RPG] Raycasting (0) | 2022.01.23 |
| [MMO RPG] Trigger (0) | 2022.01.21 |
Comments