✅ 기능
MMORPG나 FPS의 장르를 가르지 않고 플레이어가 어느 위치로 이동하기 위해서는 직접 이동해야하는 경우가 있습니다. 이럴 때 플레이어가 스스로 찾아가는것도 좋지만, 부담을 줄이기 위해 자신이 가야할 위치에 대해 경로를 시각적으로 보여주는 네비게이션을 제공해주면 만족도가 더욱 높아질 수 있습니다.
✅ 응용 기능
유니티에서 기본적으로 제공하고, 많이 사용하는 내비메시(NavMesh)를 이용하였습니다.
유니티의 기본 기능인 라인렌더러를 이용하여 경로까지의 라인을 그려 시각화를 구현하였습니다.
✅ 흐름도
✅ 사용 예시
✅ 구현
using System.Collections;
using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(LineRenderer))]
[RequireComponent(typeof(NavMeshAgent))]
public class NaviManager : MonoBehaviour
{
// 컴포넌트
private LineRenderer mLineRenderer; //라인 렌더러
private NavMeshAgent mNavAgent; //네브 에이전트
// 네브 타겟 위치
private Vector3 mTargetPos; //네브 타겟의 위치
private Transform mOriginTransform; //네브의 시작점 위치
public void InitNaviManager(Transform trans, Vector3 pos, float updateDelay)
{
SetOriginTransform(trans);
SetDestination(pos);
mLineRenderer = GetComponent<LineRenderer>();
mLineRenderer.startWidth = 0.5f;
mLineRenderer.endWidth = 0.5f;
mLineRenderer.positionCount = 0;
Material mat = new Material(Shader.Find("Shader Graphs/SampleTwinkle"));
mat.SetColor("_BaseColor", Color.green);
mLineRenderer.material = mat;
mNavAgent = GetComponent<NavMeshAgent>();
mNavAgent.isStopped = true;
mNavAgent.radius = 1.0f;
mNavAgent.height = 1.0f;
StartCoroutine(UpdateNavi(updateDelay));
}
private IEnumerator UpdateNavi(float updateDelay)
{
WaitForSeconds delay = new WaitForSeconds(updateDelay);
while (true)
{
//타겟 위치 설정
transform.position = mOriginTransform.position;
mNavAgent.SetDestination(mTargetPos);
//패스 그리기
DrawPath();
yield return delay;
}
}
public void SetDestination(Vector3 pos)
{
mTargetPos = pos;
}
public void SetOriginTransform(Transform trans)
{
mOriginTransform = trans;
transform.position = mOriginTransform.position;
}
private void DrawPath()
{
mLineRenderer.positionCount = mNavAgent.path.corners.Length;
mLineRenderer.SetPosition(0, transform.position);
if (mNavAgent.path.corners.Length < 2)
{
return;
}
for (int i = 1; i < mNavAgent.path.corners.Length; ++i)
{
mLineRenderer.SetPosition(i, mNavAgent.path.corners[i]);
}
}
}
|
cs |
private LineRenderer mLineRenderer;
- 라인 렌더러를 이용하여 현재 위치부터 목적지까지의 경로를 시각화하도록 한다.
- [RequireComponent(typeof(LineRenderer))]를 이용하여 해당 스크립트 클래스가 생성되는경우, 자동으로 라인렌더러 컴포넌트가 추가되도록 구현하였다.
private NavMeshAgent mNavAgent; //네브 에이전트
private Vector3 mTargetPos; //네브 타겟의 위치
private Transform mOriginTransform; //네브의 시작점 위치
- 내비메시를 사용하기에, 내브메시에이전트를 가지고, 해당 경로상에서 현재 위치와 도착점 위치에 대한 트랜스폼을 지정하는 변수를 선언한다.
public void InitNaviManager(Transform trans, Vector3 pos, float updateDelay)
- 외부에서 호출하며, trans는 경로의 시작점인 mOriginTransform. pos는 네브 타겟의 위치인 mTargetPos, updateDelay는 딜레이초마다 갱신하는 시간이다.
private IEnumerator UpdateNavi(float updateDelay)
- updateDelay초 마다 현재 위치를 기점으로 네비를 다시 갱신하고, 라인 렌더러를 이용하여 생성된 패스를 다시 그린다.
private void DrawPath()
- 핵심이 되는 함수로, mNavAgent.path.corners.Length; 에서 내비메시에는 해당 경로로 가는 path.coners에 대한 위치 정보가 있다.
- 이것이 내비메시에서 꺾이는 점마다 추가되는 벡터값으로, 이 경로를 이용하여 라인을 렌더링 하도록 한다.
- 라인을 그릴 path(노드)가 1개 이하인경우에는, 그릴 필요가 없기에 그리지 않도록 한다.
✅ 사용(외부에서 호출)
//PlayerController의 Start()에서 호출
NaviManager path = new GameObject().AddComponent<NaviManager>(); path.InitNaviManager(transform, mDestinationPos.position, 0.01f);
|
cs |
- 내비메시는 플레이어 오브젝트에 붙지 않는다. 그 이유는 네비메시가 붙으면 네비메시가 움직임을 제어하기때문에, 별개의 새로운 게임오브젝트를 사용하도록 한다.
- 게임 오브젝트를 생성한 후 해당 오브젝트에 네비메니저(비게이션 기능)을 추가하고, 자신의 트랜스폼(transform), 목적지(mDestinationPos.position), 마지막으로 업데이트 딜레이시간을 넣어서 사용한다.
'unity game modules' 카테고리의 다른 글
[유니티] 애니메이션 랜덤으로 재생하기(StateMachineBehaviour) (0) | 2022.11.23 |
---|---|
[유니티] 편리하게 소리를 담당하는 사운드 매니저 구현 (0) | 2022.11.21 |
[유니티] 파일브라우저(FileExplorer)를 이용하여 로컬 파일 저장/읽기 (SimpleFileBrowser) (0) | 2022.10.22 |
[유니티] 지정한 위치에 직선 형태로 여러 발을 소환하여 공격하기 (0) | 2022.09.26 |
[유니티] 낙하 감지(Fall Detection) 및 낙하 연출 (0) | 2022.09.01 |