[Unity] 오브젝트반투명 처리하기
오브젝트반투명 처리한 움짤입니다
구현 코드 내용입니다
public struct St_ObstacleRendererInfo
{
public int InstanceId;
public MeshRenderer Mesh_Renderer;
public Shader OrinShader;
}
private Dictionary<int, St_ObstacleRendererInfo> Dic_SavedObstaclesRendererInfo = new Dictionary<int, St_ObstacleRendererInfo>();
private List<St_ObstacleRendererInfo> Lst_TransparentedRenderer = new List<St_ObstacleRendererInfo>();
private Color ColorTransparent = new Color(1f, 1f, 1f, 0.2f);
private Color ColorOrin = new Color(1f, 1f, 1f, 1f);
private string ShaderColorParamName = "_Color";
private Shader TransparentShader;
private RaycastHit[] TransparentHits;
private LayerMask TransparentRayLayer;
void Init()
{
TransparentRayLayer = 1<<LayerMask.NameToLayer(DefineKey.LayerObstacle);
TransparentShader = Shader.Find("Legacy Shaders/Transparent/Diffuse");
}
void Update()
{
Camera_TransparentProcess_Operation();
}
void Camera_TransparentProcess_Operation()
{
if (MY_Char_Transform == null) return;
// 반투명했던거 다시 월래 쉐이더로 복귀
if (Lst_TransparentedRenderer.Count > 0)
{
for (int i = 0; i < Lst_TransparentedRenderer.Count; i++)
{
Lst_TransparentedRenderer[i].Mesh_Renderer.material.shader = Lst_TransparentedRenderer[i].OrinShader;
}
Lst_TransparentedRenderer.Clear();
}
Vector3 CharPos = MY_Char_Transform.position + MY_Char_Transform.TransformDirection(0, 1.5f, 0);
float Distance = (Camera_Move_OJ.position - CharPos).magnitude;
Vector3 DirToCam = (Camera_Move_OJ.position - CharPos).normalized;
Vector3 DirToCharbehind = -MY_Char_Transform.forward;
//플레이어몸에서 몸뒤 체크해서 걸리는오브젝트 반투명
HitRayTransparentObject(CharPos, DirToCharbehind, Distance);
//플레이어 몸에어 카메라까지 체크해서 걸리는오브젝트 반투명
HitRayTransparentObject(CharPos, DirToCam, Distance);
}
void HitRayTransparentObject(Vector3 start, Vector3 direction, float distance)
{
TransparentHits = Physics.RaycastAll(start, direction, distance, TransparentRayLayer);
for (int i = 0; i < TransparentHits.Length; i++)
{
int instanceid = TransparentHits[i].collider.GetInstanceID();
//레이에 걸린 장애물이 컬렉션에 없으면 저장하기
if (!Dic_SavedObstaclesRendererInfo.ContainsKey(instanceid))
{
MeshRenderer obsRenderer = TransparentHits[i].collider.gameObject.GetComponent<MeshRenderer>();
St_ObstacleRendererInfo rendererInfo = new St_ObstacleRendererInfo();
rendererInfo.InstanceId = instanceid; // 고유 인스턴스아이디
rendererInfo.Mesh_Renderer = obsRenderer; // 메시렌더러
rendererInfo.OrinShader = obsRenderer.material.shader; // 장애물의쉐이더
Dic_SavedObstaclesRendererInfo[instanceid] = rendererInfo;
}
// 쉐이더 반투명으로 변경
Dic_SavedObstaclesRendererInfo[instanceid].Mesh_Renderer.material.shader = TransparentShader;
//알파값 줄인 쉐이더 색 변경
Dic_SavedObstaclesRendererInfo[instanceid].Mesh_Renderer.material.SetColor(ShaderColorParamName, ColorTransparent);
Lst_TransparentedRenderer.Add(Dic_SavedObstaclesRendererInfo[instanceid]);
}
}
- Init 함수
TransparentRayLayer = 1<<LayerMask.NameToLayer(DefineKey.LayerObstacle); //레이캐스트 시 장애물 오브젝트만 감지하기 위해 레이어설정
TransparentShader = Shader.Find("Legacy Shaders/Transparent/Diffuse"); // 반투명쉐이더로 교체할 쉐이더
(사용한 쉐이더는 유니티 기본 쉐이더이더 입니다, Transparent가 있는 다른 쉐이더로 사용하셔도 됩니다)
- Camera_TransparentProcess_Operation 함수
반투명을 했엇던 오브젝트를 담은 리스트 (Lst_TransparentedRenderer) 를 다 검사하여 원래 쉐이더로 바꿔줍니다.
두군데를 레이를 쏠 준비를 합니다. 첫번쨰는 몸뒤에 오브젝트가 걸리는지 확인하기위해 몸뒤 방향, 거리 , 캐릭터위치 를 구합니다,
두번쨰는 캐릭터에서부터 카메라까지 걸리는 오브젝트가 있는지 확인하기 위해 캐릭터에서 카메라의 방향, 거리, 캐릭터 위치를 구합니다
- HitRayTransparentObject 함수
시작위치, 방향, 거리 를 변수를 가지고 Physics.RaycastAll 를 사용하여 해당방향에 걸리는 장애물오브젝트를 다 가져옵니다.
ray 에 걸린 정보로 오브젝트의 인스턴스Id, renderer 정보를 찾아 구조체에 담아
오브젝트 인스턴스Id 키값으로 컬렉션에 담아둡니다(Dic_SavedObstaclesRendererInfo)
컬렉션(Dic_SavedObstaclesRendererInfo)에 담아두는 이유는 매프레임마다 같은오브젝트가 레이에 걸리게 된다면
같은 오브젝트의 정보를 계속 찾고 구조체에 담아 두고하는일이 비용적으로 크고 부담이기 때문에
컬렉션에 담아 다음프레임에 같은 오브젝트가 걸리더라도 컬렉션에 담은 거가지고 활용하기위해서 입니다
결론적으로 부하를 줄이기위함입니다.
렌더정보를 찾으 장애물 오브젝트의 쉐이더를 반투명쉐이더로 바꾸고 반투명쉐이더의 _Color파라미터의 색 alpha 값을 을 변경해줍니다.
* 쉐이더마다 선언된 color 파라미터 이름이 다를수 있습니다. 사용하실 쉐이더 Properties를 확인하여 주세요
변경된 오브젝트의 구조체정보를 리스트에 담습니다
이상 오브젝트반투명 처리였습니다