카테고리 없음

Unity 본캠프 71일차

julesnow 2025. 7. 22. 05:08

📑 목차

⓵ Lighting
    𝟙 배치 예시
    𝟚 
    𝟛 Orthographic Size 
    	- 공식 사용 이유
        - Anchor & Pivot
        - Action Points
        
⓶ 모의 면접
    𝟙 면접 준비
    𝟚 피드백
    𝟛 알게된 점
    	- 멀티쓰레딩에서의 async

▪️Lighting 배치


▪️현황 및 목표

  • 플레이어가 방 입장 시 라이트가 켜지고, 방에서 나가면 꺼지도록,
  • 라이트 오브젝트를 코드에서 직접 On/Off 제어하고 싶음

핵심 구현

  • 판정: 각 방의 Trigger Collider를 이용해 플레이어의 출입을 감지
  • 조명 제어: Light2D 컴포넌트의 Intensity 값을 조절
  • 연출: DOTween을 활용하여 부드러운 페이드 인/아웃 효과 적용

 

▪️가능한 구현 방향

1. 라이트 오브젝트 활성/비활성화

방법 1 :  SetActive

플레이어가 해당 방에 입장하면 RoomLight.SetActive(true),
퇴장하면 SetActive(false)로 제어

예시

public class Room : MonoBehaviour 
{ 
	public GameObject roomLight; 
    
    public void OnPlayerEnter() 
    { 
    	roomLight.SetActive(true); 
    } 
    
    public void OnPlayerExit() 
    { 
    	roomLight.SetActive(false); 
    } 
}
  • 장점: Unity에서 렌더링 자체를 아예 차단하기 때문에 빠르고 확실함
  • 단점: 라이트가 꺼질 때 즉각적으로 사라짐(페이드 아웃 효과는 없음)

방법 2: 라이트 강도(Intensity) 조정 

라이트 오브젝트를 껐다 켜는 대신,
라이트 컴포넌트의 intensity를 0으로 만들거나 원래 값으로 복구

 

예시

using FunkyCode;

public class Room : MonoBehaviour 
{ 
    public Light2D roomLight; 
    
    private float originalIntensity; 
    
    void Awake() 
    { 
    	if (roomLight != null) 
        originalIntensity = roomLight.intensity; 
    } 
    
    public void OnPlayerEnter() 
    { 
    	if (roomLight != null) 
        roomLight.intensity = originalIntensity; 
    } 
    
    public void OnPlayerExit() 
    { 
    	if (roomLight != null) 
        roomLight.intensity = 0; 
    } 
}
 
  • 장점: 자연스러운 페이드 아웃, 라이트 객체가 씬에서 계속 유지
  • 단점: 라이트가 계속 씬에 남아 있어서 최적화에는 불리

2. 방 출입 판정 

  • 각 방마다 트리거(Trigger Collider)를 두고
  • 플레이어가 트리거에 들어오면 OnPlayerEnter() 호출, 나가면 OnPlayerExit() 호출
  • 플레이어 위치 기반 판정도 가능

 

예시

void OnTriggerEnter2D(Collider2D other) 
{ 
	if (other.CompareTag("Player")) 
    	OnPlayerEnter(); 
} 

void OnTriggerExit2D(Collider2D other) 
{ 
	if (other.CompareTag("Player")) 
    	OnPlayerExit(); 
}
  • 각 방마다 위와 같이 라이트를 켜고 끄면 됨

3. 라이트를 객체로 제어

  • 방 오브젝트에서 자식으로 라이트 오브젝트를 가져오거나
  • Room 스크립트에서 public/SerializedField로 직접 연결해서 쓰기
  • 동적으로 생성된 방도 Instantiate될 때 이 연결이 자동으로 유지됨

 

예시

[SerializeField] private Light2D[] roomLights;

public void SetRoomLights(bool on) 
{ 
	foreach (var light in roomLights) 
    	light.gameObject.SetActive(on); 
}
 

intensity로 컨트롤 시

[SerializeField] private Light2D[] roomLights; 
private float[] _defaultIntensity; 

void Awake() 
{ 
	_defaultIntensity = new float[roomLights.Length]; 
    for(int i=0; i<roomLights.Length; i++) 
    	_defaultIntensity[i] = roomLights[i].intensity; 
} 

public void SetRoomLights(bool on) 
{ 
	for(int i=0; i<roomLights.Length; i++) 
    	roomLights[i].intensity = on ? _defaultIntensity[i] : 0f; 
}

4. 라이트 여러 개일 때 

  • 배열로 관리하기
  • 켜질 때 모두 켜고, 꺼질 때 모두 끔

5. Action Points

  1. Room 스크립트에서 라이트 오브젝트 참조 →
  2. OnTriggerEnter/Exit에서 라이트 on/off 또는 intensity 조절
  3. 필요시 페이드 인/아웃 등 DOTween 활용 가능
DOTween.To(() => roomLight.intensity, x => roomLight.intensity = x, targetIntensity, 0.5f);

 

 


추가로,

  • 시네머신/카메라 이동에 맞춰서 연출하고 싶으면,
    카메라가 해당 방을 클리어하게 볼 때 켜도 됨

 

카메라가 완전히 방 내부를 비췄을 때 라이트를 켜기!

  • 카메라의 이동/위치값을 체크해서 방의 중심과 sufficiently 가까워졌을 때 SetRoomLights(true)
  • 카메라를 담당하는 스크립트에서
    • Update()에서 현재 카메라 위치와 방 중심 거리 체크
    • 카메라와 방 중심 거리가 activeDistance 미만이면 즉,
    • 일정 거리 이내면 해당 방의 SetRoomLights(true) 호출
    • 불필요하게 On/Off 되지 않게 상태 플래그로 중복 호출 방지

 


▪️구현하기

RoomLightController.cs

  • SetActive
  • Intensity 조절
  • Trigger 제어
using System.Collections;
using UnityEngine;
using DG.Tweening;
using UnityEngine.Rendering.Universal;

public class RoomLightController : MonoBehaviour
{
    [SerializeField] private Light2D[] roomLights; 
    private float[] _defaultIntensity;
    private Tween[] _fadeTweens;

    private void Awake()
    {
        _defaultIntensity = new float[roomLights.Length];
        _fadeTweens = new Tween[roomLights.Length];
        
        for (int i = 0; i < roomLights.Length; i++)
        {
        	if (roomLights[i] != null)
            {
            	_defaultIntensity[i] = roomLights[i].intensity;
            }
        }
    }

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            SetRoomLights(true);
        }
    }

    private void OnTriggerExit2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            SetRoomLights(false);
        }
    }

    private void SetRoomLights(bool on)
    {
        for (int i = 0; i < roomLights.Length; i++)
        {
        	if (_fadeTweens[i] !=  null && _fadeTwenns[i].IsActive())
            {
            	_fadeTwenns[i].Kill();
            }
            // 페이드 인/아웃
            float targetIntensity = on ? _dafaultIntensity[i] : 0f;
            _fadeTweens[i] = roomLights[i].DoIntensity(targetIntensity, 0.4f);
        }
    }
}

 

방마다 연결시키기

 

CameraLightController.cs

public class CameraLightController : MonoBehaviour
{
    public Transform cameraTransform;
    public float activationDistance = 10f;

    void Update()
    {
        // RoomManager를 통해 모든 방의 목록을 가져오기
        foreach (var room in RoomManager.Instance.AllRooms) 
        {
            float distance = Vector3.Distance(cameraTransform.position, room.transform.position);

            if (distance < activationDistance)
            {
                if (!room.IsLit) 
                {
                    room.SetLights(true); 
                }
            }
            else
            {
                if (room.IsLit) 
                {
                    room.SetLights(false);
                }
            }
        }
    }
}

▪️기타 이슈

  • Unity 강제 종료됨
    • RoomLightController.cs Awake() 내에 조건 추가해서 해결
 if (!Application.isPlaying)
            return;
  • 몇몇 Lighting Prefab이 정신 못차리고 날아다님
  • 초기 Bloom 값 갑자기 발광함