ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스파르타) The Last Rollback (D-20, Node.js 게임 서버 최종 프로젝트)
    TIL 2024. 8. 7. 21:42


     > 과제 진행 간 완료한 사항 및 문제점과 해결 과정을 정리해보았다.

     

    학습 키워드: Unity, C#, Quaternion, Vector3, Post Processing

     

    과제 진행 사항

    1) 밤 낮 전환 연출 추가:

     

     완성해둔 낮 밤 라운드 기능에 실제 낮 밤 전환 연출이 없어서 post processing과 directional light를 이용하여 연출을 추가해줬다.

     

    using System.Collections;
    using UnityEngine;
    
    public class DirectionalLightController : MonoBehaviour {
        private static DirectionalLightController _instance = null;
        public static DirectionalLightController Instance => _instance;
        [Header("Values")]
        [SerializeField]
        private int dayTemperature = 3000;
        [SerializeField]
        private int nightTemperature = 15000;
        [SerializeField]
        private Vector3 defaultRot = new Vector3(44.4f, -102.8f, 0);
        private float shiftDuration = Constants.SHIFTING_DURATION;
        private Coroutine lightCoroutine;
    
        [Header("Components")]
        [SerializeField]
        private Light directionalLight;
    
        void Awake()
        {
            if (_instance == null)
            {
                _instance = this;
            }
            else if (_instance != this)
            {
                Destroy(gameObject);
                return;
            }
            DontDestroyOnLoad(gameObject);
            directionalLight = GetComponent<Light>();
        }
    
        public void ShiftToDay()
        {
            float temp = Mathf.Clamp(dayTemperature, 1500f, 20000f);
            ShiftLighting(defaultRot, new Vector3(defaultRot.x + 360, defaultRot.y, defaultRot.z), directionalLight.colorTemperature, temp, shiftDuration);
        }
    
        public void ShiftToNight()
        {
            float temp = Mathf.Clamp(nightTemperature, 1500f, 20000f);
            ShiftLighting(defaultRot, new Vector3(defaultRot.x + 360, defaultRot.y, defaultRot.z), directionalLight.colorTemperature, temp, shiftDuration);
        }
    
        private void ShiftLighting(Vector3 startRot, Vector3 endRot, float startTemp, float endTemp, float duration)
        {
            if (lightCoroutine != null) {
                StopCoroutine(lightCoroutine);
            }
            lightCoroutine = StartCoroutine(LerpLightTemperature(startRot, endRot, startTemp, endTemp, duration));
        }
    
        private IEnumerator LerpLightTemperature(Vector3 startRot, Vector3 endRot, float startTemp, float endTemp, float duration)
        {
            float elapsed = 0f;
            Vector3 prevRot = startRot;
            float prevTemp = startTemp;
            
            while (elapsed < duration) {
                float t = elapsed / duration;
                
                directionalLight.colorTemperature = Mathf.Lerp(prevTemp, endTemp, t);
                
                Vector3 curRot = Vector3.Lerp(prevRot, endRot, t);
                directionalLight.transform.rotation = Quaternion.Euler(curRot);
    
                elapsed += Time.deltaTime;
                prevRot = curRot;
                prevTemp = directionalLight.colorTemperature;
                yield return null;
            }
    
            directionalLight.colorTemperature = endTemp;
            directionalLight.transform.rotation = Quaternion.Euler(startRot);
    
        }
    }

     

    using UnityEngine;
    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    using System.Collections;
    
    public class PostProcessingController : MonoBehaviour 
    {
        private static PostProcessingController _instance = null;
        public static PostProcessingController Instance => _instance;
    
        [Header("Values")]
        [SerializeField]
        private float dayTemperature = 75f;
        [SerializeField]
        private float nightTemperature = -75f;
        private float shiftingTime = Constants.SHIFTING_DURATION;
    
        [Header("Components")]
        [SerializeField]
        private Volume volume;
        [SerializeField]
        private WhiteBalance wb;
        [SerializeField]
        private Bloom bloom;
        [SerializeField]
        private Vignette vignette;
        private Coroutine shiftCoroutine;
    
        void Awake()
        {
            if (_instance == null)
            {
                _instance = this;
            }
            else if (_instance != this)
            {
                Destroy(gameObject);
                return;
            }
            DontDestroyOnLoad(gameObject);
    
            volume = GetComponent<Volume>();
            volume.profile.TryGet(out wb);
            volume.profile.TryGet(out bloom);
            volume.profile.TryGet(out vignette);
        }
        // void Start()
        // {
        //     ShiftToDay();
        // }
    
        public void ShiftToDay()
        {
            ShiftTo(nightTemperature, dayTemperature, shiftingTime);
        }
    
        public void ShiftToNight()
        {
            ShiftTo(dayTemperature, nightTemperature, shiftingTime);
        }
    
        public void ShiftTo(float start, float end, float duration)
        {
            if (shiftCoroutine != null) {
                StopCoroutine(shiftCoroutine);
            }
            shiftCoroutine = StartCoroutine(LerpTemperature(start, end, duration));
        }
    
        private IEnumerator LerpTemperature(float startValue, float endValue, float duration)
        {
            float elapsed = 0f;
            float prevValue = startValue;
    
            while (elapsed < duration) {
                wb.temperature.value = Mathf.Lerp(prevValue, endValue, elapsed / duration);
                elapsed += Time.deltaTime;
                prevValue = wb.temperature.value;
                yield return null;
            }
            wb.temperature.value = endValue;
        }
    }

     

     당장은 하나의 DL과 PP를 사용하기 때문에 singleton으로 구현하여 쓰고있으나, 추후에 여러 곳에 적용할 가능성이 있으므로 바꿔줘야할 필요가 있다. Directional Light의 경우 360도 회전을 하려고 보니 Quaternion의 Lerp로는 최단 거리로 이동하기 때문에 회전을 하지 않아서 Vector3 값으로 lerp하고 해당 값을 Quaternion.Euler를 사용하여 Quaternion으로 치환 후 rotation에 직접 적용해주는 방식으로 구현했다. 또한, start 값에서 end값으로 lerp를 하니 너무 정직하게 시작하고 끝나서 부자연스러웠는데, start 대신 current 값에서 end 값으로 lerp하니 적절한 가속과 감속이 생겨서 부드러운 전환이 이루어졌다.

     

     현재는 DL이 한 바퀴를 돌면서 씬이 빛을 받지 않는 구간이 잠시 생기는데, 씬 자체에 여러 light source를 배치하여 개선하게 될 예정이다.

     

     

    --


    REFERENCES:

     

     

    GitHub - eliotjang/the-last-rollback-server: 액션 MORPG

    액션 MORPG. Contribute to eliotjang/the-last-rollback-server development by creating an account on GitHub.

    github.com

     > 프로젝트 repo

     

    728x90
Designed by Tistory.