본문 바로가기

Unity/Unity 스파르타

10주차 - 개인 심화 3D(NavMeshAgent.path.corners, NavMeshSurface , Animation Curve)

728x90

 

1. 이동 로직 수정하기 (NavMeshAgent.path.corners)

2. 숨겨진 문 상호작용 만들기 (NavMeshSurface)

3. 횃불 상호작용 만들기 (AnimationCurve)


1. 이동 로직 수정하기

캐릭터가 목표 지점으로 이동할때,  이동하는 방향이 아닌 도착지점을 바라보고 이동하는 문제점이 있었습니다.

Navigation 으로 목표위치를 지정 해주고, 캐릭터의 방향을 단순히 목표위치에서 현재위치를 뺀 값을 노멀라이즈 해준 것으로 캐릭터의 방향을 결정 했기때문이었습니다.

또한 캐릭터의 행동을 UI를 통해 통제 할 것이기 때문에 마우스 클릭으로 목표위치를 정한뒤 바로 움직이는게 아닌 모든 행동이 끝났을때 사용자가 엔터키를 누르면 움직이게 만들 것 입니다 .

그래서 Navigation 에 목표위치를 정해주고, Navigation 이 목표위치까지 이동경로를 계산해주면,

'NavMeshAgent.path.corners' 으로 이동경로만 배열로 받아와 사용하는 것으로 로직을 수정했습니다.

 

순서

상호작용 UI 에서 Move 선택 -> StartDrawNavMeshAgentPath() :이동경로 그려주기 -> 마우스 오른쪽 클릭(왼쪽은 취소) -> SetNavMeshAgentPath(): 이동경로 확정 -> 엔터키 입력 -> PlayerMovePath() : 플레이어 이동

 

실질적으로 PlayerMovePath() 는 캐릭터가 이동할 위치만 업데이트 해주고, FixedUpdate 에서 위치가 업데이트 되면 해당위치로 캐릭터가 이동합니다.

 

 

2. 숨겨진 문 상호작용 만들기

간단한 맵을 만들고,  상호작용이 가능한 벽을 하나 만듭니다.

캐릭터가 해당 벽에 일정 거리만 큼 가까워 지면 상호작용키가 나오고, 상호작용 키를 누르면 문이 내려가는 애니메이션과 함께 숨겨진 방이 나타납니다.

기본적으로 상호작용 가능한 오브젝트에 사용될 변수와 함수를 정의한 InteractionBase 스크립트를 만들고 상속 시켜 사용했습니다.

Navigation을 사용해 캐릭터가 움직이고 있기 때문에 새로운 맵이 생성되거나 나타났을때 Bake를 해주지 않으면 캐릭터가 해당 지점으로 이동할 수가 없습니다. 'navMeshSurface.BuildNavMesh();' 를 사용해 런타임중 Bake를 할 수 있습니다.

 

* NavMeshSurface 네임스페이스는 using Unity.AI.Navigation; 에 있습니다.

* 런타임중 NavMeshSurface를 통해 Bake를 할경우 맵에 사용된 오브젝트의 메쉬가 Read/Write 가 체크되어 있는지 확인해야 합니다.

Read/Write는 메시 데이터를 보호하고 변경을 방지하기 위한 설정으로, NavMesh와 빌드 작업과 같은 작업을 수행할 때는 Read/Write를 활성화 해줘야 합니다.

3. 횃불 상호작용 만들기

횃불 상호작용은 위에서 만든 InteractionBase 상속 받아 만들 것 입니다.

LightController 스크립트를 만들어 'AnimationCurve' 사용해 빛의 밝기를 조절해 빛이 일렁이는 듯한 느낌을 주게 만들 것 입니다.

AnimationCurve 를 사용해 빛의 새기 뿐만 아니라 빛의 색 또한 Gradient 로 조절해 줄 것 입니다.

 

불이 꺼지기 전까지 계속해서 코루틴으로 빛의 새기와, 빛의 색을 업데이트 시켜줄 것입니다.

보간은 0 ~ 1까지의 값만 가짐으로 percent에 Time.deltaTime을 더하고 1을  나눈 나머지값을 구해줍니다.

실제 보간값은 대칭 함수를 통해 percent 가 0.5일때 최댓값, percent 가 1에 가까워질수록 최솟값을 가지게 만들어 줬습니다.

(하지만, 그냥 percent를 사용하는 것과 큰 차이가 없었습니다.. AnimationCurve를 왕복 하느냐 편도로 가느냐의 차이입니다.)

IEnumerator LightOnCo()
    {
        _light.enabled = true;
        float percent = 0;
        while (onLight)
        {
            percent += Time.deltaTime;
            percent %= 1;
            float interpolation = (-Mathf.Pow(percent, 2) + percent) * 4;
            _light.color = gradient.Evaluate(interpolation);
            _light.intensity = animationCurve.Evaluate(interpolation);

            yield return null;
        }
        _light.enabled = false;
    }

728x90