씬에서 비가 오는 상황에서 전역적으로 반짝이게하여 번개가 치는 느낌을 구현할 수 있다.

 

실제 게임 내에서 소리가 포함되어 보여지는 비 오는 느낌의 씬

 

구현 아이디어?

번개가 치는 상황에서 전역적으로 밝아지는것을 만들때는 현 씬 자체가 어두운 상태(밤)이 대부분이다. 이 점을 이용하여 단순히 씬에서 사용하는 Directional Light를 밝게 한다.

안개가 껴 있는 상황에서는 주변이 밝아져도 안개때문에 밝은 상태가 멀리 못가기에 잠시동안 안개를 맑게 했다 다시 돌려놓는 방향으로 구현하였다.

 

 

//ThunderManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ThunderManager : MonoBehaviour
{
    //디렉셔널 라이트의 Light 컴포넌트
    [SerializeField] private Light mDirLight;
    //씬의 음향효과를 관장하는 사운드 매니저
    private SoundManager mSoundManager;
    //반짝이는 기능을 담당하는 mThunderCoroutine과 잠시 후 번개 소리를 출력을 담당하는 mSoundCoroutine
    private Coroutine mThunderCoroutine, mSoundCoroutine;
    //번개 효과를 시작하기 직전의 디렉셔널 라이트의 색상을 담는다
    private Color mPrevLightColor;
    //번개 효과를 시작하기 직전의 디렉셔널 라이트의 광도를 담는다
    private float mPrevLightIntensity;
    //번개 효과를 시작하기 직전의 안개 농도를 담는다
    private float mPrevFogDensity;
    
    //번개 효과를 자동으로 시작할 때 번개를 칠 때마다 딜레이 시간을 담는다
    private float mOriginTimer;
    //번개 효과를 자동으로 시작할때 다음 번개까지 남은 시간을 담는다
    private float mCurrentTimer;
    //번개 효과를 자동으로 치게할지 설정하는 변수
    private bool mIsAuto = false;
    
    //씬이 로드되면 사운드 매니저를 찾는다
    void Start()
    {
        mSoundManager = FindObjectOfType<SoundManager>();
    }   
    //timer 초마다 번개를 자동으로 치게 하는 함수
    public void StartAutoThunder(float Timer = 60)
    {
        mOriginTimer = Timer;
        mCurrentTimer = mOriginTimer;
        mIsAuto = true;
    }
    //StartAutoThunder로 인해 자동으로 번개를 치는것을 중지하는 함수
    public void StopAutoThunder()
    {
        mIsAuto = false;
    }
    //mIsAuto가 참인경우 지정된 시간초마다 번개를 치게한다
    private void Update()
    {
        if(!mIsAuto) return;
        mCurrentTimer -= Time.deltaTime;
        if(mCurrentTimer < 0)
        {
            mCurrentTimer = mOriginTimer;
            RunThunder(0, Random.Range(210));
        }
    }
    //실제로 번개를 치는 효과를 실행하는 함수
    public void RunThunder(float delayTime = 0float soundDelayTime = 0
    {
        if(mThunderCoroutine != null)
        {
            mDirLight.color = mPrevLightColor;
            mDirLight.intensity = mPrevLightIntensity;
            RenderSettings.fogDensity = mPrevFogDensity;
            StopCoroutine(mThunderCoroutine);
        } 
            
        if(mSoundCoroutine != null)
        {
            StopCoroutine(mSoundCoroutine);
        } 
        mPrevLightColor = mDirLight.color;
        mPrevLightIntensity = mDirLight.intensity;
        mPrevFogDensity = RenderSettings.fogDensity;
 
        mThunderCoroutine = StartCoroutine("ThunderCor", delayTime);
        mSoundCoroutine   = StartCoroutine("ThunderSoundCor", soundDelayTime);
    }
    //순간 반짝이도록 빛과 안개를 잠깐동안 설정했다가 되돌리는 코루틴 함수
    IEnumerator ThunderCor(float delayTime)
    {
        bool isFogActived = RenderSettings.fog;
        yield return new WaitForSeconds(delayTime);
        mDirLight.color = Color.white;
        mDirLight.intensity = 1f;
        if(isFogActived)
        {
            RenderSettings.fogDensity = mPrevFogDensity * 0.5f;
        }
        
        yield return new WaitForSeconds(0.05f);
        
        mDirLight.color = mPrevLightColor;
        mDirLight.intensity = mPrevLightIntensity;
        
        if(isFogActived)
        {
            RenderSettings.fogDensity = mPrevFogDensity;
        }
    }
    //번개가 친 후에 잠시 후 번개소리가 나도록 하는 코루틴 함수
    IEnumerator ThunderSoundCor(float soundDelayTime)
    {
        yield return new WaitForSeconds(soundDelayTime);
        mSoundManager.PlayThunderSound();
    }
}
cs

카메라를 흔들리게하는 카메라 매니저와 같이 씬 내에 하나의 매니저가 존재하며 해당 매니저에서 public 함수를 호출하는 방식으로 구현하였다.

 

[SerializeField] private Light mDirLight;

  • 씬에서 사용하는 디렉셔널 라이트 오브젝트의 Light 컴포넌트를 담는다.
  • 인스펙터에서 직접 넣어서 사용하도록 구현하였다.

 

private SoundManager mSoundManager;

  • 번개소리를 출력하기 위해 씬 내의 모든 사운드를 관장하는 사운드 매니저이다.

 

private Coroutine mThunderCoroutine, mSoundCoroutine;

  • 반짝이는 기능을 담당하고 번개 소리 출력을 담당하는 코루틴을 담는 변수들이다.
  • 의도하지 않은 반복적인 호출에 버그가 나는것을 방지하기위해 코루틴을 저장하는 변수를 사용한다.

 

private Color mPrevLightColor;

private float mPrevLightIntensity;

private float mPrevFogDensity;

  • 번개를 치는 함수를 호출할 때 디렉셔널 라이트와 안개에 대한 설정이 바뀌기 직전의 값을 각 변수에서 저장한다.
  • 번개를 친 후 변경된 설정에서 다시 되돌아오기 위해 사용한다.
  • 코루틴의 중복 실행 시 코루틴들을 초기화하고 새로운 코루틴을 실행하기 전에 설정들을 다시 되돌리는데 사용한다.

 

private float mOriginTimer;

  • StartAutoThunder()함수가 실행되어 자동으로 일정 시간마다 번개를 칠 때 번개치는 함수의 간격에 대한 시간값을 저장하는 변수이다.


private float mCurrentTimer;

  • StartAutoThunder()함수가 실행되어 자동으로 번개를 칠 때 다음 번개까지 남은 시간을 저장하는 변수이다.

 

private bool mIsAuto = false;

  • StartAutoThunder()로 인해 mIsAuto 가 참이 되는데, mIsAuto가 참이면 Update()함수가 돌면서 mCurrentTimer를 감소시키고 번개를 치도록 한다.

 

void Start()

  • 사운드 매니저를 찾아서 mSoundManager 변수에 저장한다.

 

public void StartAutoThunder(float Timer = 60)

  • 외부에서 호출되며 기본 매개변수인 60은 60초마다 번개가 내리치도록 한다.
  • mIsAuto를 참으로 하여 Update()의 내부가 프레임마다 실행되도록 한다.

 

public void StopAutoThunder()

  • 외부에서 호출되며 단순히 mIsAuto를 거짓으로 만들어 Update()의 내부가 더 이상 실행되지 않도록 한다.

 

private void Update()

  • StartAutoThunder()에 의해 mIsAuto가 참인경우에만 내부가 실행된다.
  • mCurrentTimer가 감소하며 0보다 작아지는경우 RunThunder()함수를 호출한다.

 

public void RunThunder(float delayTime = 0, float soundDelayTime = 0) 

  • 번개의 효과를 시작하는 함수이다.
  • delayTime은 변수의 값 초 후에 번쩍이게 하도록한다.
  • soundDelayTime은 변수의 값 초 후에 번개소리를 출력하도록 한다.
  • 외부에서 독립적으로 호출될 수 있으며, mIsAuto에 의한 자동 번개와 별개로 RunThunder의 매개변수인 delayTime초 후에 단독적으로 번개를 치도록 한다. 예시로 날씨가 아닌 번개속성의 공격으로 인한 의도한 번개 연출을 낼 수 있다.
  • 이미 이전의 코루틴이 실행되고 있으면 해당 코루틴을 제거하고 변경된 빛과 안개 속성을 되돌려 놓은 후 다시 반짝이는 효과 코루틴과 소리출력 코루틴을 실행하도록 한다. 이 과정으로 비 정상적으로 동시다발적으로 번개가 내리쳐도 버그를 방지할 수 있다.

 

IEnumerator ThunderCor(float delayTime)

  • 번개로 인한 전역적으로 반짝이는 효과를 담당하는 코루틴 함수이다.
  • delayTime초 만큼 기다렸다가 디렉셔널 라이트의 광도는 1, 색상은 Color.white로 잠시동안 바꾼다. 동시에 안개가 켜져 있는 상태라면 안개의 농도를 반 줄인다.
  • 애초부터 안개가 꺼져있다면 isFogActived가 거짓이 되는데, 거짓이라면 RenderSettings.fogDensity를 수정해서는 안된다.
  • yield return new WaitForSeconds(0.05f); 코드와 그 이후는 0.05초 후에 다시 이전의 속성으로 돌려놓는다.

 

IEnumerator ThunderSoundCor(float soundDelayTime)

  • 번개가 친 후에 soundDelayTime초 후 번개소리가 나도록 하는 코루틴 함수이다.
bonnate