バーチャル3Dクリエイター神部まゆみです(*^_^*)
この記事はUnityで太陽を作り夜にしたり昼にしたりするサイクルを作った記事です。
動作確認した最新バージョンは Unity 6000.3.1 です。
やりたいこと:シーン内に太陽を作りゲーム内時間に沿って移動させ、昼夜サイクルを作りたい
太陽っていうかディレクショナルライトが太陽になる感じかな?
シーンの中心を元にディレクショナルライトを回転させればそれっぽくなるんじゃないかと思う。
ChatGPTパイセンに聞いてみる
彼に聞けばたちどころに解決してくれるに違いない…。


Unityでゲーム開発をしています。シーン内で時間経過で日が昇り夜になり朝になり…というサイクルを作りたいです。これって太陽となるライトを動かして作る感じなんでしょうか?これを作る場合ゲーム内の時間も作る必要があると思いますが、その作り方も教えてください。

いいテーマですね。日夜サイクルは“世界が生きてる感”を一気に出せるやつなので、作りがいあります。
結論から言うと 「太陽役のDirectional Lightを回す」+「ゲーム内時間を自前で管理する」 のが王道です。
① 日夜サイクルの基本的な考え方
はい、その理解で合ってます 👍
Unityでは普通、太陽=Directional Light です。
- X軸(または任意の軸)で回転させる
- 昼:上から照らす
- 夕方:斜め
- 夜:地面の下に行く(光が当たらない)
これだけで「日が昇って沈む」動きは作れます。
② ゲーム内時間の作り方(超重要)
現実時間とは切り離して、ゲーム用の時間を作ります。
例:
- 1日 = 24時間
- ゲーム内1時間 = 現実の10秒
→ 1日 = 240秒(4分)
シンプルな時間管理スクリプト例
using UnityEngine;
public class GameTime : MonoBehaviour
{
// ゲーム内の現在時刻(0〜24)
public float currentTime = 6f; // 朝6時スタート
public float dayLengthInSeconds = 240f; // 1日が240秒
void Update()
{
float timeSpeed = 24f / dayLengthInSeconds;
currentTime += Time.deltaTime * timeSpeed;
if (currentTime >= 24f)
{
currentTime -= 24f;
}
}
}
これで
currentTimeが 0〜24 をぐるぐる回る- 「今何時か」をゲーム全体で使えるようになります
③ 時間と太陽の回転をつなぐ
次に、この時間を使って太陽を回します。
using UnityEngine;
public class SunController : MonoBehaviour
{
public Light sunLight;
public GameTime gameTime;
void Update()
{
// 0時 → -90度、12時 → 90度、24時 → 270度
float sunAngle = (gameTime.currentTime / 24f) * 360f - 90f;
sunLight.transform.rotation = Quaternion.Euler(sunAngle, 170f, 0f);
}
}
これで
- 朝:太陽が昇る
- 昼:真上
- 夜:地面の下
という動きになります。
④ 夜っぽさを出す(ここからが楽しい)
1. 太陽の強さを時間で変える
sunLight.intensity = Mathf.Clamp01(
Mathf.Cos((gameTime.currentTime - 12f) / 24f * Mathf.PI * 2f)
);
→ 夜は暗く、昼は明るく。
2. 環境光(Ambient Light)も変える
RenderSettings.ambientIntensity = Mathf.Lerp(0.2f, 1.0f, sunLight.intensity);
3. 夜用ライト(月)
- もう1つDirectional Lightを作って「月」にする
- 夜だけ有効化すると雰囲気アップ 🌙
⑤ よくある設計のコツ
- 時間管理は1か所にまとめる
→ NPC、イベント、UI時計全部が同じ時間を見る - float時間(6.5 = 6時30分)で持つと楽
- 「朝になったらイベント発火」なども簡単になる
⑥ 最初はここまでできれば十分
最初のゴールとしては👇でOKです。
- Directional Lightを回す
- ゲーム内時間を作る
- 明るさが昼夜で変わる
そこから
- 季節
- 天気
- 夜だけ出る敵
…みたいにどんどん拡張できます。
そこまで難しくなさそうかなぁ。
まぁやってみます。
実際に実装してみる
本当に動くか実装してみます。
GameTime.csを作る
プロジェクトフォルダでGameTime.csってスクリプトを作り、これをコピペします。
using UnityEngine;
public class GameTime : MonoBehaviour
{
// ゲーム内の現在時刻(0〜24)
public float currentTime = 6f; // 朝6時スタート
public float dayLengthInSeconds = 240f; // 1日が240秒
void Update()
{
float timeSpeed = 24f / dayLengthInSeconds;
currentTime += Time.deltaTime * timeSpeed;
if (currentTime >= 24f)
{
currentTime -= 24f;
}
}
}

SunController.csを作る
これもコピペして作ります。
using UnityEngine;
public class SunController : MonoBehaviour
{
public Light sunLight;
public GameTime gameTime;
void Update()
{
// 0時 → -90度、12時 → 90度、24時 → 270度
float sunAngle = (gameTime.currentTime / 24f) * 360f - 90f;
sunLight.transform.rotation = Quaternion.Euler(sunAngle, 170f, 0f);
}
}

空のオブジェクトを作り、GameTimeとSunControllerをアタッチして設定
SunControllerコンポーネントにディレクショナルライト、GameTimeコンポーネントを指定します。
これで動いた!
これだけでちゃんと動きました!
ディレクショナルライト動かすだけでそれっぽくなるのか…。
しかし日没後も照らされてるのは気になるか…
日が沈んだ後も横から照らされてしまってる感じなのでここは気になるかな…。

ChatGPT氏の言うように日没後は太陽役のディレクショナルライトは光を弱くして、代わりに月でうっすら青く照らすみたいにすると良いかな?
月も追加して改良してみる
青っぽい感じの月を追加して夜だけ出るようにし、時間帯によって太陽と月の光を調節するとそれっぽくなると思います。

SunController.csを書き換える
以下のように書き換えます。
using UnityEngine;
public class SunController : MonoBehaviour
{
public Light sunLight;
public Light moonLight;
public GameTime gameTime;
[Header("Intensity")]
public float sunMaxIntensity = 1.2f;
public float moonMaxIntensity = 0.3f;
[Header("Ambient")]
public float dayAmbient = 1.0f;
public float nightAmbient = 0.2f;
void Update()
{
float time01 = gameTime.currentTime / 24f; // 0〜1
// ===== 太陽の回転 =====
float sunAngle = time01 * 360f - 90f;
sunLight.transform.rotation = Quaternion.Euler(sunAngle, 170f, 0f);
// ===== 太陽の明るさ =====
float sunIntensity = Mathf.Clamp01(
Mathf.Cos((gameTime.currentTime - 12f) / 24f * Mathf.PI * 2f)
);
sunLight.intensity = sunIntensity * sunMaxIntensity;
// ===== 月の回転(太陽の反対側) =====
moonLight.transform.rotation = Quaternion.Euler(sunAngle + 180f, 170f, 0f);
// ===== 月の明るさ(夜だけ) =====
float moonIntensity = 1f - sunIntensity;
moonLight.intensity = moonIntensity * moonMaxIntensity;
// ===== 環境光 =====
RenderSettings.ambientIntensity =
Mathf.Lerp(nightAmbient, dayAmbient, sunIntensity);
}
}
月のディレクショナルライトを追加して青っぽくする
色は #AFCBFF くらいの薄い青で影なしにする。
これで良くなった!
おお、これで夜も昼も実装できましたね(*^_^*)
月はスカイボックスに描くか、丸いオブジェクトをEmissionで発光させるしかないっぽい?
しかしディレクショナルライトだけで表現する場合、夜は暗くすることで表現しているから、月自体は見えないっぽい。
なぜなら明るくすると昼になってしまい太陽のディレクショナルライトと同じになってしまうから。
ChatGPT氏に聞いてみたけどスカイボックスに描くか、丸いオブジェクトをEmissionで発光させる感じかな…。


方法Aでやってみたけど、月の位置がおかしくなってハマった(^_^;)
まぁとりあえずここまでできたから後でやるか…。
おわりに
案外手軽に実装できて良かった。
空の表現は雲とかも配置したいし、その時に月なども配置してみたいかな?
また何かあれば追記します(*^_^*)



