기본은 포스트 하단 참고 문헌의 유튜브 영상을 토대로 만들었습니다.
3D로 제작할 때는 해당 영상을 시청하는 편이 더 낫다고 생각합니다.
하지만 참고 영상은 SkinnedMeshRenderer를 사용하기에
MeshRenderer 사용이 강제된 스켈레톤 애니메이션에서는 그대로 사용이 불가능했습니다.
그래서 코드를 분석해보니 SkinnedMeshRenderer의 장면 하나하나의 오브젝트 생김새(메시)를 따서 출력해준다 라는 느낌으로 이해했습니다.
MeshRenderer 혹은 연관된 컴포넌트에서 화면에 출력할 메시를 찾아서 이를 복제하여 캐릭터 뒤에 뿌려준다면?
아주 간단히 완성이 되는 것이겠지요.
가설에 따라 메뉴얼들을 참고해보니 MeshFilter에서 우리가 원하던 메시를 가져올 수 있겠다는 생각이 들었습니다.
코드를 아래와 같이 수정하고
using System.Collections;
using UnityEngine;
public class MeshTrail : MonoBehaviour
{
public float activeTime = 0.2f;
[Header("Mesh Related")]
public float meshRefreshRate = 0.1f;
public float meshDestroyDelay = 0.2f;
public Transform positionToSpawn;
[Header("Shader Related")]
public Material mat;
bool isTrailActive = false;
// 스켈레톤 애니메이션 > 메터리얼 파츠를 조합 > 각 움직임을 매시 필터에 매시로 임시 저장
MeshFilter skeletonMeshFilter;
// Start is called before the first frame update
void Start()
{
//skinnedMeshRenderers = GetComponentsInChildren<SkinnedMeshRenderer>();
skeletonMeshFilter = GetComponent<MeshFilter>();
}
// Update is called once per frame
void Update()
{
if(GameManager.instance.GetChargeReady && !isTrailActive)
{
isTrailActive = true;
StartCoroutine(ActivateTrail(activeTime));
}
}
IEnumerator ActivateTrail(float timeActive)
{
while (timeActive > 0)
{
timeActive -= meshRefreshRate;
GameObject temp = new GameObject();
// 플레이어의 위치, 회전과 동일
temp.transform.SetPositionAndRotation(positionToSpawn.position, positionToSpawn.rotation);
// 플레이어 크기에 맞게 스케일 조정
temp.transform.localScale = Vector3.one * 0.5f;
// 잔영에 사용할 메시 랜더러, 필터
MeshRenderer mr = temp.AddComponent<MeshRenderer>();
// 제대로 표시되도록 소팅 레이어를 지정
mr.sortingLayerID = SortingLayer.NameToID("Middleground");
MeshFilter mf = temp.AddComponent<MeshFilter>();
// 생성 후 왼쪽으로 이동하게끔 지시하는 스크립트 부착
// 플레이어는 가만히 있고 플랫폼, 배경이 움직이는 게임 구조 상 그림자도 움직여야 함
temp.AddComponent<Shadow_Player>();
// 메터리얼은 조각조각으로 쪼개진 스파인 메터리얼
mr.material = mat;
// 스파인 메터리얼을 조합한 잔상 1장
Mesh mesh = new Mesh();
mesh = skeletonMeshFilter.mesh;
mf.mesh = mesh;
// 잠시 후 파괴 예약
Destroy(temp, meshDestroyDelay);
yield return new WaitForSeconds(meshRefreshRate);
}
isTrailActive = false;
}
}
인스펙터에 각 항목을 넣어주면
아래와 같이 동작합니다.
캐릭터의 원래 색상대로 잔상이 나오게 하는 데에는 성공했지만 저걸 그대로 보기엔 눈이 아픕니다.
참고 영상처럼 셰이더 그래프를 이용해서 이펙트로 만들어주는 방법도 있겠지만
여기서는 아주 간단하게 스파인 기본 제공 셰이더를 이용해 반투명 처리해 보겠습니다.
캐릭터 머티리얼을 복사 > 복사한 머티리얼의 인스펙터 > Shader > SkeletonGhost > Texture Fade Out을 원하는 값으로 조정해두고
MeshTrail.cs 를 부착한 오브젝트의 mat에 캐릭터 머티리얼 대신 집어넣어 줍니다.
반투명한 잔상이 생기는 것을 확인할 수 있습니다.
< 참고 문헌 >
https://www.youtube.com/watch?v=7vvycc2iX6E
https://docs.unity3d.com/kr/2021.2/Manual/class-MeshRenderer.html
메시 렌더러 - Unity 매뉴얼
메시 렌더러는 메시 필터에서 지오메트리를 가져와 게임 오브젝트의 Transform 컴포넌트에서 정의된 위치에서 렌더링합니다.
docs.unity3d.com
https://docs.unity3d.com/kr/530/Manual/class-MeshFilter.html
메시 필터 - Unity 매뉴얼
메시 필터(Mesh Filter) 는 에셋에서 메시를 가져와 화면에 렌더링하기 위해 메시 렌더러에 전달합니다.
docs.unity3d.com
https://docs.unity3d.com/kr/2020.3/Manual/class-SkinnedMeshRenderer.html
스킨드 메시 렌더러 - Unity 매뉴얼
Unity는 메시의 모양이 애니메이션화된 뼈대에 따라 변형되는 Bone 애니메이션의 렌더링을 위해 Skinned Mesh Renderer 컴포넌트를 사용합니다. 캐릭터뿐만 아니라 (조인트가 힌지처럼 기능하는 기계와
docs.unity3d.com
'기능 구현 방법 정리' 카테고리의 다른 글
~초 동안 무적 및 깜빡거림으로 무적 상태 알림 (0) | 2024.09.13 |
---|---|
스크립트로 스파인 스킨 변경 (0) | 2024.08.31 |
유니티) 일시 정지 상태의 게임에서 무언가 진행되도록 하고 싶다면? (0) | 2024.04.12 |
유니티) 불필요한 설명을 너무 줄인 직렬화 기본 (0) | 2023.09.03 |
비활성화 상태 오브젝트에 접근 방법 (0) | 2023.04.24 |