Name
date
Folder Path

project:\\서브컬쳐 AI NPC App 만들기 프로젝트 - 3 (감정이 있는 AI)

 

서브컬쳐 AI NPC App 만들기 프로젝트 3편.

부제는 감정이 있는 AI 만들기.​

이번에 공유할 Task는 아래 항목들이다.

이때 Task들이 가장 재미있었다!!!

  • VRM 표정 + 애니메이션 및 AI 응답 키워드 연동
  • 시스템 프롬프트 설정 기능 구현
  • UI 컴포넌트 깎기
  • 새채팅 기능 구현


 

1. VRM 표정 + 애니메이션과 / AI 응답 키워드 연동

이 작업이 뭐냐고 묻는다면,

나: 너 바보야!

AI: 네가 더 바보거든?! (분노 😡)

이 분노라는 감정 키워드와 일치하는 표정/애니메이션을 VRM 모델이 시각적으로 표현하게 만드는 것이다.

우선 VRM 모델과 애니메이션이 연동될 수 있도록 Animator Controller를 생성해 VRM 프리팹에 연결해주자.

그리고 급 의문.

감정을 어디까지 지원해줄까?

인간은 얼마나 복잡한가? 웃고, 울고, 슬퍼하고, 분노하는 것 외에도... 의기 양양, 증오, 조소.. 뭐 여러가지있다

하지만 디테일에 집착하면 빠르게 완성 못한다. 선택과 집중을 해야한다.

어떤 감정들이 대부분의 대화 케이스를 커버할 수 있을까?

핵심만 구현해보자.

별로 크게 참고는 안된다만 나무위키는 이렇다한다

나는 대부분의 대화를 커버할 수 있는 대표 감정+세부 감정으로 구성해볼거다

그리고 하나는 잡고 가고 싶었던 것...

기존 레퍼 앱들의 한계중 하나는,

유저가 채팅 입력하고 있는 중의 Case를 딱히 대응 안했다는 점이다.

우리에게 채팅창은 말을 전하고 있는 과정이 될 것이고 >

현실에 대응하자면, 내가 상대방에게 말하고 있는 순간일 것이다.

따라서 유저 입장에서 경청하고 있다는 느낌을 주게 하는, Think 도 넣어볼 것이다.

이 Think 는 유저가 inputfiled 를 활성화 했을 때부터 발동하게 할거다

물론 비활성화시 case도 고려해야겠다. 이게 default 모션이 될 것이다

내가 구현할 감정은 다음과 같다:

애니메이션은 총 5개 세팅하고, 표정은 6개로 세팅해서 돌려막을 것이다.

No.
감정 네임
표정 네임
(BlendShapePreset)
애니메이션 네임
1
Neutral
(Default)
Neutral
*Neutral_ani
2
Happy
Joy
Happy_ani
3
Sad
Sorrow
Sad_ani
4
Angry
Angry
Angry_ani
5
Surprised
Fun
*Neutral_ani
6
Shy
Sorrow
*Neutral_ani
7
Think
Neutral
Think_ani

마음같아선 Think 표정 🙄 이런 표정으로 커스텀 하고 싶고, 실제로 가능하긴하나.

커스텀 표정은 모든 VRM 모델에 적용되는 것이 아니고.

단일 모델에 있는 커스텀 표정을 불러오는 것이라.

로컬에서 유저가 어떤 모델이든 임포트 가능하게 염두해둔 기획 하에 이건 좋지 않은 세팅이기에 일단은 Pass다

 

 

적절한 애니메이션을 https://www.mixamo.com/ 라는 Free 에셋 사이트에서 다운해준다

이후 유니티에 임포트 > Inspector 에서 애니메이션 타입 휴머노이드로 해주고, Apply 하면!

이런식으로 만들어진다.

이걸 기본 모드로 설정해보고 잘 돌아가는지 테스트를 해본다.

캐릭터가 뒤를 봐서 이후 180도 회전해줬다

이렇게...

감정 시스템을 위해 스크립트 2개를 추가했다

- ChatManager (기존): 채팅 입출력 / 유저 입력 감지 / Gemini 응답 처리

- EmotionaPasar: 감정 추출해 이모션 타입 반환 (Gemini가 감정 추론하게 프롬을 짰다)

- EmotionPlayer: 추출된 감정에 따라 애니메이션/표정 재생

이렇게 감정별 애니메이션 노드도 간단히 짜준다

스크립트 잘 동작한다. 감정에 따라 지정한 모션으로 잘 넘어간다.

근데 이슈가 생겼다. [A 감정] > [B 감정] 으로 넘어갈 때 눈알이 없어진다.

이유는? VRM에서 표정을 덧씌웠기 때문이다.

따라서 감정이 전환될 때마다 표정 초기화를 해주는 코드를 추가해줬다.

2. 시스템 프롬프트 설정 기능 구현

다음은 시스템 프롬프트를 유저가 설정 가능한 환경 만들기다.

GPTs의 '지침'과 동일한 역할이다.

'너는 츤데레 성격을 가진 러시안 블루 고양이야. 말 끝마다 '냥'을 붙여서 나와 티키타카 해줘'

이런 지침들을 자동으로 수행하게 한다.

UI는 이 두가지면 된다.

- 인풋 필드 (프롬프트 작성용)

- Apply (프롬프트 적용용)

원리는 다음과 같다:

인풋 필드에 유저가 시스템 프롬프트를 작성하고, Apply를 누르면

다음번 첫 메시지에서 Gemini API에 찌를 때 함께 포함되게 할 것.

유저가 채팅 인풋 던질 때 마다 이 시스템 프롬프트가 히스토리에 포함되어 있어,

Gemini는 자연스럽게 시스템 프롬프트 기억하고 응답할 것이다.

짜잔! 구현 완료.

츤데레 프롬프트 적용이 아주 잘 된다.

3. UI 컴포넌트 깎기 (feat. 아트 강화.. 카메라 업글)

리프레시를 위해 디자인/아트를 하자

 

포근한 침실 배경이 눈에 들어오면 좋겠다.

유니티 에셋 스토어에서 멋진 에셋을 다운받아서 세팅해줬다.

 

스카이 박스도 바꿔줬다. 감성적으로 변했다.

테스트하다보니, 뷰가 답답하게 느껴졌다. 카메라 뷰를 요리조리 움직일 수 있으면 좋겠다.

 

스크립트 하나 더 파서, Target (VRM 모델 얼굴) 기준으로 회전/스크롤 가능하도록 만들어줬다.

그리고 UI를 좀더 멋지게 만들어주자

이건 figma 로 작업한 시안. ChatVRM을 레퍼런스로 삼았다.

 

근데 인게임에 UI만 세팅하고 보니,

하단 살색 바가 답답해 보이길래 뺐다.

뚝딱뚝딱 수리를 해주자.

입력창, 프롬프트 버튼 (클릭시 모달) 부터 먼저 만들어줬다.

Prompt 버튼을 클릭하면 모달 하나가 뜨게 해서,

이쪽에서 시스템 프롬 작성할 수 있게 구현한다.

이제 채팅로그 버튼도 구현해주자.

구현 완료! 이쪽도 모달로 해줬다.

그럼 실시간 응답 (1개) 도 볼 수 있게 해줘야 한다.

로그와는 성격이 다르다.

UI 틀과 기능은 구현 완료다.

실시간 대화 UI도 깎아준다.

뚝딱뚝딱...

응답이 흘러넘치는데, 이때 해결 방법은 다음과 같다:

1. 응답은 채팅창 UI 밖으로 벗어나지 않게 리밋 건다.

2. 이후, 흘러넘치는 응답에 대해서는 페이지네이션이 가능하게 해주자.

구현완료!

이전버튼, 다음버튼을 만들어줬다.

그리고 한 가지 더.

애초에 Gemini가 응답을 너무 길게 하는 것이 원인이다.

따라서, 아예 Gemini가 응답 자체를 5줄 이하로! 짧게! 답변할 수 있도록 지원하는

개발자용 숨겨진 프롬프트를 만들어 반영했다.

4. 새채팅 기능 구현

이번엔 새채팅 기능을 구현할 것이다.

GPT의 새채팅 기능과 유사하다.

이전 히스토리를 다 잊고, 다시 시작할 수 있는 기능!

UI 뚝딱뚝딱

이미 만들어둔 컴포넌트를 잘 활용해서 구워준다.

이제 클릭 이벤트가 발생했을때 > 백엔드에서 gemini 채팅을 초기화 해주는 기능이 동작하도록 붙여준다.

유저가 등록한 시스템 프롬프트도 초기화 되게 할 거다.

완료!

테스트 해보자.

우선 시스템 프롬프트에 말 끝마다 냥냥을 붙이라고 했다.

이제 [New chat]을 누르고 대화를 다시 시도하면?

채팅 로그도 한번 비워지고,

다 초기화 된 상태로 답한다.

이전 내용도 AI가 모른다.

+ 하는김에

폰트도 안깨지게 최적화 해줬다.

이제 데모버전이라고 할 수 있는 레벨이 되었다!