팀프로젝트/R&D

2020.06.15. 조명 + 낮, 밤 Cycle 만들기

dev_sr 2020. 6. 16. 00:17

소중한 시간 절약을 위해 10초 주기로 낮 밤이 바뀌게 했습니다

실제 인게임에서는 30초 주기로 구현할 예정입니다

 

 

 

먼저 10초 주기로 낮->밤, 밤, 밤->낮, 낮 ....싸이클을 코루틴으로 만들어보았음

그리고 각각 밤과 낮에 진입할 때 각 오브젝트의 메테리얼에 접근해서 조명을 켜주고 꺼줬음

 

 

그다음 하늘 바꾸기

 

PolyCity를 만든 제작사에서 무료 에셋인 simple sky를 다운받으면 안에 SkyDome 이 있음

 

열어보면 해랑 달, 별들이 붙어있는 커다란 반구가 나옴. (구름은 안붙어 있음)

그걸 구조물 위에 얹고 쉐이더를 standard로 바꿔줌

이 반구는 Vector3.up(수직)을 기준으로 빙글빙글 돌려줄거임 

 

여기서 Offset에 접근해서 시간의 흐름에 따라 색상을 바꿔줄거임(이러면 노을이 생김)

 

 

코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
 
public class Background : MonoBehaviour
{
    public GameObject[] arrGameObjects;
    private Material[] arrMaterials;
 
    //버튼 테스트
    public Button btn;          //누를때마다 낮밤이 바뀜
    private bool isNight;       //밤인가?
 
 
    //시간 테스트
    public Text text;        //test 시간 찍어보기 용
    public Text state;       //무슨 상태인가 
    private float elpasedTime;  //경과시간
    private float r = 1f;       //r,g,b 색깔들
    private float g = 1f;
    private float b = 1f;  
 
    public GameObject skyDome;  //빙글빙글 돌 스카이돔
    private Material skyDomeMaterial;   //스카이돔의 메테리얼
    private float offsetValueX = 0;
 
    void Start()
    {
        this.skyDomeMaterial = this.skyDome.GetComponent<Renderer>().material; 
        //스카이돔 메테리얼의 오프셋에 접근하는 방법
        //오프셋에서 접근해서 색을 바꿔줄거임
        this.skyDomeMaterial.SetTextureOffset("_MainTex"new Vector2(this.offsetValueX,0));
 
        this.isNight = false;
        this.arrMaterials = new Material[this.arrGameObjects.Length];
 
        int index1 = 0;
        for (int i = 0; i < this.arrGameObjects.Length; i++)
        {
            index1 = i;
            this.arrMaterials[index1] = this.arrGameObjects[index1].GetComponent<Renderer>().material;
            this.arrMaterials[index1].EnableKeyword("_EMISSION");
            this.arrMaterials[index1].globalIlluminationFlags = MaterialGlobalIlluminationFlags.RealtimeEmissive;
 
        }
 
        //버튼 테스트
        this.btn.onClick.AddListener(() =>
        {
            int index2 = 0;
 
            if (!this.isNight)
            {
                for (int i = 0; i < this.arrMaterials.Length; i++)
                {
                    index2 = i;
                    this.arrMaterials[index2].SetColor("_EmissionColor", Color.white);  //건물 안 조명키기
                    RenderSettings.ambientLight = Color.black;  //씬 전체 라이트렌더링 어둡게 하기
 
                }
                this.isNight = true;
            }
            else
            {
                for (int i = 0; i < this.arrMaterials.Length; i++)
                {
                    index2 = i;
                    this.arrMaterials[index2].SetColor("_EmissionColor", Color.black);  //건물 안 조명 끄기
                    RenderSettings.ambientLight = Color.white;  //씬 전체 라이트렌더링 밝게 하기
                }
                this.isNight = false;
 
            }
 
        });
 
        //시간테스트 코루틴 시작
        if (!this.isNight)
        {
            this.StartCoroutine(this.DayToNightImpl());
        }
 
    }
 
    //낮 -> 밤
    IEnumerator DayToNightImpl()
    {
        while (true)
        {
            this.elpasedTime += Time.deltaTime;
            this.text.text = this.elpasedTime.ToString();
            this.state.text = "낮->밤";
            RenderSettings.ambientLight = new Color(this.r, this.g, this.b, 1);
            this.r -= r / 1000;
            this.g -= g / 1000;
            this.b -= b / 1000;
 
            if (this.r <= 0 || this.g <= 0 || this.b <= 0)
            {
                this.r = 0;
                this.g = 0;
                this.b = 0;
            }
 
            this.offsetValueX += 0.05f * Time.deltaTime;
            this.skyDomeMaterial.SetTextureOffset("_MainTex"new Vector2(this.offsetValueX, 0));
 
            if (this.elpasedTime >= 10)
            {
                this.offsetValueX = 0.5f;
                this.elpasedTime = 0;
                this.text.text = this.elpasedTime.ToString();
                this.StartCoroutine(this.NightImpl());
                break;
            }
 
            yield return null;
        }
  
 
    }
 
    //밤
    IEnumerator NightImpl()
    {
        this.skyDomeMaterial.SetTextureOffset("_MainTex"new Vector2(this.offsetValueX, 0));
 
        for (int i = 0; i < this.arrMaterials.Length; i++)
        {
            this.arrMaterials[i].SetColor("_EmissionColor", Color.white);
 
        }
 
        while (true)
        {
            this.elpasedTime += Time.deltaTime;
            this.text.text = this.elpasedTime.ToString();
            this.state.text = "밤";
            
 
            if (this.elpasedTime>=10)
            {
                this.elpasedTime = 0;
                this.StartCoroutine(this.NightToDayImpl());
                break;
            }
 
            yield return null;
        }
 
    }
 
    //밤 -> 낮
    IEnumerator NightToDayImpl()
    {
        
 
        while (true)
        {
            this.elpasedTime += Time.deltaTime;
            this.text.text = this.elpasedTime.ToString();
            this.state.text = "밤->낮";
            RenderSettings.ambientLight = new Color(this.r, this.g, this.b, 1);
            this.r += r / 1000;
            this.g += g / 1000;
            this.b += b / 1000;
 
            if (this.r >= 1 || this.g >= 1 || this.b >= 1)
            {
                this.r = 1;
                this.g = 1;
                this.b = 1;
            }
 
            this.offsetValueX -= 0.05f*Time.deltaTime;
            this.skyDomeMaterial.SetTextureOffset("_MainTex"new Vector2(this.offsetValueX, 0));
 
            if (this.elpasedTime >= 10)
            {
                this.offsetValueX = 0;
                this.elpasedTime = 0;
                this.text.text = this.elpasedTime.ToString();
                this.StartCoroutine(this.DayImpl());
                break;
            }
 
            yield return null;
        }
        
 
    }
 
    //낮
    IEnumerator DayImpl()
    {
        this.skyDomeMaterial.SetTextureOffset("_MainTex"new Vector2(this.offsetValueX, 0));
 
 
        for (int i = 0; i < this.arrMaterials.Length; i++)
        {
            this.arrMaterials[i].SetColor("_EmissionColor", Color.black);
        }
 
        while (true)
        {
            this.elpasedTime += Time.deltaTime;
            this.text.text = this.elpasedTime.ToString();
            this.state.text = "낮";
 
 
            if (this.elpasedTime >= 10)
            {
                this.StopAllCoroutines();
                this.elpasedTime = 0;
                this.StartCoroutine(this.DayToNightImpl());
                break;
            }
 
            yield return null;
        }
 
        
    }
 
    private void Update()
    {
        //스카이돔 돌아라
        this.skyDome.transform.Rotate(Vector3.up* 3* Time.deltaTime);
    }
}

 

 

 

 

 

 

미적인 부분은 조금씩 더 개선해가야할 듯..

 

 

참고 - 메테리얼 오프셋에 스크립트로 접근하기

 

Unity - Scripting API: Material.SetTextureOffset

Success! Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable. Close

docs.unity3d.com