티스토리 뷰

1월 26일

1) Git 작업 흐름

  • develop 브랜치 최신 내용 가져오기 (pull)
  • 로컬에 develop 브랜치 생성/체크아웃
  • 시야 시스템 작업용 기능 브랜치 생성
    • feat/sight-system
  • 이후 모든 작업은 feat/sight-system 브랜치에서 진행

 

2) 렌더 파이프라인 세팅(UniversalRP) & 테스트씬 생성

  • Edit → project settings → graphics → set default render pipeline asset 에 UniversalRP 세팅

 

  • 2D Light & Shadow 사용을 위해 Universal Render Pipeline(URP) 적용
  • Universal RP Asset 생성 및 프로젝트에 적용
  • 2D Renderer 사용 설정
  • 이후 Light 2D, Shadow Caster 2D 컴포넌트 사용 가능해짐
  • 기존 씬을 기반으로 테스트용 씬 생성
    • test_scene_sy 복제
    • (내 테스트 환경에서 시야/조명 시스템만 빠르게 검증하기 위함.

 

3) 플레이어 시야용 Light2D 세팅

  • 플레이어 프리팹에 시야 조명용 오브젝트 추가
    • 빈 오브젝트 생성: VisionLight
    • VisionLight에 Light 2D 컴포넌트 추가
    • Shadows 옵션 체크 (그림자 투영 활성화)
  • Global Light 2D 로 인해 어두워지지 않으므로 추후 스크립트로 조절하는 작업 필요함.

 

4) 벽(장애물) 그림자 캐스팅 세팅

  • 씬에 벽 역할 오브젝트 생성 (임시 벽)
    • 빈 오브젝트(벽): Wall (또는 벽 역할 오브젝트)
    • Shadow Caster 2D 컴포넌트 추가
    • (빛이 벽에 막히면서 벽 뒤 시야가 차단되도록 준비)

1월 28일

1) SightSystemController.cs 구현

  • 목적: 게임 state에 따라 시야 연출을 자동으로 전환하고, 닉네임 표시 제어 위한 컨트롤러 작성
  • 구현 내용
    • 플레이어의 VisionLight 조절
      • 범위 축소/확대, 강도 조절
    • 닉네임 가리기 로직 연결
      • 내 닉네임은 유지, 다른 플레이어 닉네임은 숨김
    • 위 기능들을 프리팹에 추가하지 않고, 코드로 각각의 오브젝트(visionlight, 닉네임 canvas) 찾아서 연결하도록 했다.
  • SightSystemController.cs 코드
SightSystemController.cs 코드 보기

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Experimental.Rendering.Universal;//2d renderer 조명 사용
using Photon.Pun;//PhotonView.IsMine 사용

//GameStateManager의 상태 변경에 반응해서
//암전(시야 축소 + global light 어둡게 + 흑백 + 닉네임 숨김) 토글 스크립트
public class SightSystemController : MonoBehaviour
{
    [Header("설정")]

    [Tooltip("플레이어 프리팹 안의 VisionLight")]
    //플레이어 주변 시야를 밝히는 VisionLight(플레이어 자식 Light2D)
    [SerializeField] private Light2D visionLight;

    [Tooltip("흑백 필터용 Volume")]
    [SerializeField] private Volume grayscaleVolume;


    [Header("조명 설정")]

    [Tooltip("평소 VisionLight 밝기 (보통 0)")]
    [SerializeField] private float visionIntensity_Normal = 0f;

    [Tooltip("암전 시 VisionLight 밝기")]
    [SerializeField] private float visionIntensity_OffLight = 1f;

    [Tooltip("평소 visionLight의 시야 반경")] 
    [SerializeField] private float visionRadius_Normal = 10f;

    [Tooltip("암전 시 visionlight 시야 반경")]
    [SerializeField] private float visionRadius_OffLight = 3.5f;

    [Header("닉네임 숨기기")]
    [Tooltip("플레이어 프리팹 내 닉네임 UI 루트(캔버스) 오브젝트 이름")]
    [SerializeField] private string nicknameRootName = "Canvas";

    [Header("GameState")]
    [Tooltip("암전이 적용되는 게임 상태")]
    [SerializeField] private GameState offLightState = GameState.Playing_OffLight;

    //내부 상태 (중복 호출 방지 위해)
    private bool isBlackout;//현재 암전 켜져있는지 저장

    private void OnEnable()
    {
        //씬에 GameStateManager 싱글톤 존재하는지 확인
        if(GameStateManager.instance != null)
        {
            //gamestatemanager의 상태 변경 이벤트를 구독 (바뀌면 HandleGameStateChanaged 호출)
            GameStateManager.instance.OnGameStateChanged += HandleGameStateChanged;

            //시작 시점에 로컬 플레이어 visionLight 자동 연결
            TryBindLocalVisionLightByName();

            // 시작 시 현재 상태 반영
            HandleGameStateChanged(GameStateManager.instance.currentState);
        }
        else
        {
            // GameStateManager가 없으면 구독 불가 → 경고 로그로 원인 추적 가능하게 함
            Debug.LogWarning("[SightSystemController] GameStateManager.instance is null. 씬에 GameStateManager가 있는지 확인!");
        }
    }
    

    //비활시 자동 호출
    private void OnDisable()
    {
        //싱글톤 확인하고
        if(GameStateManager.instance != null)
        {
            //이벤트 구독 해제
            GameStateManager.instance.OnGameStateChanged -= HandleGameStateChanged;
        }
    }

    //visionLight가 연결 안 됐으면 계속 연결 시도 (성공하면 더 이상 안 함)
    private void Update()
    {
        if (visionLight == null)
            TryBindLocalVisionLightByName();
    }

    //"VisionLight" 이름을 가진 자식 Light2D를 로컬 플레이어에서 자동으로 찾아 연결
    private void TryBindLocalVisionLightByName()
    {
        //씬에 있는 PhotonView 훑어서 IsMine 플레이어 찾음
        PhotonView[] views = FindObjectsByType(FindObjectsSortMode.None);
        foreach(var pv in views)
        {
            if(!pv.IsMine) continue;

            //자식 이름이 정확인 VisionLight인 Transform 찾기
            Transform t = pv.transform.Find("VisionLight");
            if(t== null) continue;

            Light2D found = t.GetComponent();
            if(found == null) continue;

            visionLight = found;

            //연결되자마자 평소 상태 기본값 세팅
            visionLight.intensity = visionIntensity_Normal;
            SetLightRadius(visionLight, visionRadius_Normal);

            Debug.Log("[SightSystemController] Bound VisionLight (visionlight) from local player.");
            return; // 한 번 찾으면 끝
        }
    }

    //닉네임 숨기기 함수
    //암전 여부 따라 닉네임 숨기거나 보여줌
    private void HideOtherNicknames(bool isBlackout)
    {
        //씬에 있는 tag가 player인 오브젝트 배열로 가져옴.(Player 프리팹 tag: player 설정해야함..)
        var players = GameObject.FindGameObjectsWithTag("Player");

        foreach(var p in players)
        {
            var pv = p.GetComponent();
            if(pv==null) continue;

            //플레이어 프리팹 내부에서 canvas 이름의 자식 오브젝트 찾음
            Transform nicknameCanvas = p.transform.Find(nicknameRootName);
            if(nicknameCanvas == null) continue;
            //이 플레이어가 내 로컬 플레이어인지 확인
            if (pv.IsMine)
            {
                //내 닉네임 ui는 항상 보이게 유지
                nicknameCanvas.gameObject.SetActive(true);
            }
            //타인 캐릭터면
            else
            {
                //암전이면 숨김, 해제면 다시 표시
                nicknameCanvas.gameObject.SetActive(!isBlackout);
                //isBlackout이 true면 !isBlackout = false -> Canvas 꺼짐(닉네임 숨김)

            }
        }
    }

    //GameStateManager에서 상태가 바뀌면 이벤트로 호출되는 함수
    private void HandleGameStateChanged(GameState state)
    {
        // 새 상태가 '암전 상태(Playing_OffLight)'면 암전 연출 켜기
        if(state == offLightState) EnableBlackout();
        //그 외 암전 연출 끔
        else DisableBlackout();
    }


    //암전 연출 ON: 전체 어둡게 + 시야 축소 + 흑백 켜기
    public void EnableBlackout()
    {
        //이미 암전일 때
        if (isBlackout) return;

        //암전 상태로 기록
        isBlackout = true; 

        //1) VisionLight 시야 축소
        //visionlight 참조가 연결됐나 확인
        if(visionLight != null)
        {
            //visionLight 켜기
            visionLight.intensity = visionIntensity_OffLight;
            //플레이어 주변 빛 반경 줄여서 내 주변만 보이도록 만듦
            SetLightRadius(visionLight, visionRadius_OffLight);   
        }

        //2) 흑백 필터 ON(Volume 켜기)
        //인스펙터 연결 확인
        if(grayscaleVolume != null)
            //볼륨 켜서 흑백 효과 적용
            grayscaleVolume.enabled = true;

        //3) 닉네임 숨김
        HideOtherNicknames(true);
        // (추후 Photon에서 내 것만 남기고 다른 사람 닉네임 끄는 로직을 여기에 넣을 수 있음)

        // 디버그용 로그(상태 토글이 실제로 호출됐는지 확인 가능)
        Debug.Log("[SightSystemController] Blackout ENABLED"); 
    }

    public void DisableBlackout()
    {
        //암전 연출 OFF: 조명/시야/필터 원상복구
        // 이미 암전이 꺼져 있으면 또 실행하지 않음
        if (!isBlackout) return; 

        // 암전 해제 상태로 기록
        isBlackout = false; 

        if (visionLight != null) // visionLight가 연결되어 있으면
        {
            //visionlight 끄기
            visionLight.intensity = visionIntensity_Normal;
            //시야 반경을 평소 값으로 복구(넓게)
            SetLightRadius(visionLight, visionRadius_Normal);    
        }
            

        if (grayscaleVolume != null) // 흑백 볼륨이 연결되어 있으면
            // 흑백 효과 끄기(원래 색으로)
            grayscaleVolume.enabled = false; 
            
        HideOtherNicknames(false);
        // 다른 사람 닉네임도 다시 켜기

        Debug.Log("[SightSystemController] Blackout DISABLED"); 
        // 디버그용 로그
    }

    //VisionLight 반경 값 바꾸는 함수
    private void SetLightRadius(Light2D light2D, float radius)
    {
        light2D.pointLightOuterRadius = radius;
    }



}

  
  • 씬에 SightSystem 오브젝트 만들었음.

  • global light 2d 를 테스트를 위해 암전 시 0f가 되도록 바꿈 - gamestatemanager.cs

 

2) GameStateManager 수정: 큰 수정 없이 이벤트 구독 구조로 연동

  • 기존 GameStateManager 구조를 크게 건드리지 않고, 외부 시스템이 상태 변경을 구독해서 따라가도록 구조화.
  • 추가한 것
    • 상태 변경 알림 이벤트 1줄 추가
      • OnGameStateChanged 같은 형태로 “상태 바뀜”을 브로드캐스트
    • SightSystemController는 해당 이벤트를 구독(Subscribe) 해서 상태 변경 시 자동 반응

  • rpc_setgamestate() 내부에서 상태 변경 시 → OnGameStateChanged 발사 1줄 추가

  • OnPhotonSerializeView에서 동기화로 상태가 바뀐 경우에도 → 동일하게 OnGameStateChanged 발사되도록 추가 처리

 

3) 흑백 필터: Global Volume 오브젝트 추가

  • 암전 시 “채도 제거(흑백)” 연출을 위해 Post-processing 기반 구성 시작
  • 씬에 Global Volume 오브젝트를 추가해 흑백 필터 적용

 

4) 플레이어 프리팹 이름 바꿔서 저장했음 - Player(vision)


1월 29일

  • 타이틀씬 + 접속씬 수정
  • [x] Text ⇒ TMP로 수정하기
  • [x] 스프라이트(아트) PPU 48로 바꾸기
  • [x] 방 생성 시 팝업 창 버튼 아트 적용시키기

1) Text→TMP로 수정함

2) 적용된 스프라이트들만 일단 PPU 48로 바꿈

3) connect씬 팝업창 버튼 아트로 바꿈


1월 30일

Connect / Title UI TMP 전환 & 버튼 리소스 정리

작업 목적

  • UGUI(Text / InputField) 기반 UI를 TMP(TextMeshPro) 기준으로 통일
  • Connect / Title UI 구조를 정리하고,
  • 버튼 스프라이트 해상도 기준(PPU)을 통일해 UI 개선

1) UI 프리팹 수정 및 인스펙터 재연결

  1. Connect UI
  • ConnectUIRoot
    • TMP 전환에 맞춰 하위 UI 컴포넌트 교체
    • InputField / Text → TMP_InputField / TextMeshProUGUI

  • ConnectSceneManager

  • CREATEROOMPOPUP
    • 방 이름 입력, 안내 텍스트, 버튼 UI TMP로 교체
    • ScrollView / Viewport 내부 배치 구조 정리

2. Room List UI

  • ROOMITEM 프리팹
    • 방 이름 / 인원 수 표시 텍스트를 TMP로 변경
    • Join 버튼 및 UI 바인딩 재연결

 

3. InputField vs Button

글자 들어있는 버튼은 단순히 Text(legacy) → TMP 로 설정 그대로 유지해서 바꾸기만 하면됨.

  • InputField는 TMP로 바꾸면서 Text Viewport, Text Component, Font Asset, Placeholder 부분을 채워야 함.
  • NickNameInput

  • RoomNameInput

2) 스크립트 수정 (TMP 대응)

수정 대상

  • ConnectSceneManager
  • ConnectUIBinder
  • RoomItemUI

주요 변경 내용

  • using TMPro; 추가하기
  • Text → TextMeshProUGUI
  • InputField → TMP_InputField

3) TMP로 바꾼 후 paralsync로 테스트까지 완료함.


2월 2일

(URP 세팅 ~ 시야/암전 시스템)


1. URP(Universal Render Pipeline) 세팅

  • 프로젝트에 URP 적용
    • Universal RP Asset 생성
    • Project Settings → Graphics에서 Default Render Pipeline으로 설정
  • 2D Renderer 사용 설정
    • 2D Light & Shadow 기능 사용 가능하도록 구성
  • 테스트용 씬에서 URP 정상 작동 확인

2. 2D 조명 시스템 구축

Global Light 2D

  • 씬 전체 기본 밝기 담당
  • 상태에 따라 밝기 제어하도록 GameStateManager에 연결
    • 평상시(OnLight) → Intensity 1
    • 암전(OffLight) → Intensity 0

Vision Light (플레이어 시야등)

  • 플레이어 자식 오브젝트로 Light2D 추가
  • Light Type: Spot
  • 플레이어 주변만 밝히는 역할

설정:

  • 평상시
    • Intensity = 0
    • Radius 넓게
  • 암전 시
    • Intensity = 1
    • Radius 축소

→ 암전 시 “내 주변만 보이는” 효과 구현


3. SightSystemController 구현

 

GameState 변화에 따라 자동으로:

  • VisionLight 반경 조절
  • VisionLight 밝기 조절
  • 흑백 필터 ON/OFF
  • 타인 닉네임 숨김 처리

핵심 구현

  • GameStateManager.OnGameStateChanged 이벤트 구독
  • 로컬 플레이어 VisionLight 자동 바인딩
    • PhotonView.IsMine 기준 탐색
  • 상태 변경 시:
    • EnableBlackout()
    • DisableBlackout() 실행

4. 흑백(Post Processing) 시스템 추가

Global Volume 생성

  • Global Volume 오브젝트 생성
  • Volume Profile 추가

Color Adjustments 설정

  • Saturation = -100
  • → 흑백 효과 구현

SightSystemController 연결

  • grayscaleVolume 필드에 Global Volume 연결
  • 암전 시 Volume 활성화
  • 해제 시 비활성화

5. Shadow 시스템 구축

벽 오브젝트에 Shadow Caster 2D 추가

  • Sprite Renderer 기반 Shadow 생성
  • Cast Shadow 활성화

그림자 품질 조정

VisionLight:

  • Shadow Strength = 1
  • Shadow Softness = 0

6. 문제 해결 과정 (디버깅)

VisionLight가 안 켜지던 문제

원인:

  • Sprite Sorting Layer 설정 문제
  • Player(main) 프리팹 설정 불일치

해결:

  • Player(vision) 기준으로 SpriteRenderer 설정 통일

암전 시 플레이어가 검게 보이던 문제

원인:

  • Global Light 영향
  • Material/Light 상호작용 문제

해결:

  • Global Light 강도 조정
  • VisionLight 중심 조명으로 수정

흑백 효과가 항상 적용되던 문제

원인:

  • 카메라 Post Processing 항상 ON
  • Volume 제어가 이유를 모르겠지만 스크립트 상으로 enable, disable로 작동되지 않음.

해결:

  • Volume을 스크립트로 intensity 적용해서 제어
  • 그러다보니 처음 화면이 흑백이라 당황할 수 있지만 작업할 땐 global volume을 끄고 하는 것을 추천한다….

 

작업 흐름

처음에 메인씬에 기본셋팅(sightsystem 복제하고 스크립트 붙였을 때)만 하고 플레이하니 암전시 visionlight이 작동되지 않아 매우 당황했음.

→ 근데 urp 세팅이 불완전해서 그런거여서 settings 들어가서 해결

 

urp 세팅을 온전히 하고 나니 이런 문제가 발생…

알고보니 프리팹 복사를 하는 과정에서 player controller 부분의 sprite renderer 인스펙터 연결이 깨진 것을 발견. 다시 붙이니 해결됨.

 

Player에 붙어있는 visionlight 의 sorting layer가 unknown 으로 돼있어서 문제가 됐음. 이를 everything으로 놓음.

 

이후로는 global volume(흑백처리) 적용, 카메라 post processing 체크, 벽 각각에다가 shadow caster 2d 컴포넌트 적용했음.

대각선 부분들 그림자가 조금 이상해져서 따로 editor로 모양 잡아서 설정함.

가구에는 shadow 안붙였음.

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2026/03   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함