初めてu1wに参加するんだけど、初心者でも大丈夫かな?
大丈夫、できるだけ時短できるように、
参加してみて分かった使いそうなTIPSをまとめたよ!
初めてのunity1weekで使えそうな小ネタ集
タイトルシーンを設定する、シーンを移動する
まずは、期限ギリに回して困りがちなタイトルシーンとシーン移動です。
シーンを移動するにはSceneManagerを使います。
Title.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Title : MonoBehaviour
{
const string first_level = "Stage1";
public void FirstStage()
{
SceneManager.LoadScene(first_level);
}
}
このスクリプトをどこかにアタッチします。
ボタンのOnClickにシーン移動のメソッドを登録します。
忘れがちなのですが、タイトルシーンとStage1シーンをビルドに含めます。
File→ Build Settingsを開いて、シーンをドラッグ&ドロップします。
順番は0をタイトルにします。マウスで入れ替えられます。
スタートを押すと・・・
なお、かっこよくシーン移動したいならnaichi様の部品を使いましょう。
見慣れた晴天を変更する(Skybox)
Window→ Rendering→ LightingのEnvironmentタブにあるSkybox Material
スカイボックス自体はアセットストアから無料のものをもらってくるとよいです。
あるいは単色でいいなら、MainCameraのClear FlagsをSolid Colorにすればいいです。
画面サイズの設定
Edit→ Project Settings→ Player→ Resolution and Presentation
あと、UIのCanvas Scalerを設定したサイズと同じにしておきましょう。
そして、Unityroomの設定でもフルスクリーンは不可にしておいた方が丸いです。UIが崩れがちなので・・・。
※重要
ゲームを作り始める前に画面サイズを決めておいたほうがいいです
あとからサイズを直すのは大変です(経験談)
ボタンをクリックしたときのピョン
必須ではないですけどボタンクリックのときピョンとなると少し気持ちが良いです。
実装はDoTweenを使い、一瞬大きくして一瞬で元のサイズに戻します。
ButtonExtension.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
public class ButtonExtension : MonoBehaviour
{
// 対象のボタン本体
Button button;
[Header("クリックのピョン")]
// 拡大率
[SerializeField] float _expand_rate;
// イージング(ピョン速度が早いのであんまり意味ない)
[SerializeField] Ease ease;
// ピョン時間
[SerializeField] float expand_time;
// ピョン戻り時間
[SerializeField] float contract_time;
// サイズをもとに戻すときのオリジナルサイズ
Vector3 originalScale;
void Start()
{
button = GetComponentInChildren<Button>();
originalScale = button.transform.localScale;
}
public void OnClick()
{
Sequence sequence = DOTween.Sequence();
sequence.Append(button.transform.DOScale(_expand_rate, expand_time)
.SetRelative()
.SetEase(ease));
sequence.Append(button.transform.DOScale(originalScale, contract_time)
.SetEase(ease));
sequence.Play();
}
}
Sequenceを使っていますが、たぶんDelayを設定してもできます。
あまり長い時間かけて大きくしないのでイージングはおそらく意味をなさないと思います。
このスクリプトをボタンに取り付けてください。アタッチする場所はボタンの親でもボタン本体でもOKですがStartでちゃんとButtonを掴むか[SerializeField] しておきましょう。
ゲーム開始のカウントダウン
ミニゲームには必須のカウントダウンはコルーチンかTimeをカウントするかで実装します。
どちらかというとスタートコールにはコルーチンを使う方が簡単な気がします。
GameDirector.cs (名前はテキトウです)
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class GameDirector : MonoBehaviour
{
const int COUNTDOWN_SEC = 5;
[SerializeField] TextMeshProUGUI textCountdown;
private void Start()
{
StartCoroutine(countdown());
}
IEnumerator countdown()
{
for (int i = COUNTDOWN_SEC; i > 0; i--)
{
textCountdown.text = i + "";
// (ピッ音を入れるならココ)
// 1秒まつ
yield return new WaitForSeconds(1);
}
// (ポーン音入れるならココ)
textCountdown.text = "START !!";
//ここでゲーム開始のフラグをONにする
}
}
使うときは、カウントダウンを出すTextMeshProをインスペクタで設定しておいてください。
何秒かごとに何かしたい
3秒ごとに敵を出すとかですね。
いくつかやり方があります。1つはコルーチンで、スタートコールと同じ仕組みです。
ループを抜けるにはStopCoroutineを使うかwhileループを終了させるとよいです。
private void Start()
{
StartCoroutine("MainLoop");
}
IEnumerator MainLoop()
{
while (true)
{
// なにかする
yield return new WaitForSeconds(1);
}
}
もう1つはdeltaTimeをカウントする方法です。
const float INTERVAL_FAST = 5f;
float interval = INTERVAL_FAST;
float interval_cnt;
bool active;
void Update()
{
if (active)
{
if (interval_cnt <= 0)
{
// なにかする
interval_cnt = interval;
}
if (interval_cnt > 0) interval_cnt -= Time.deltaTime;
}
}
定期的に何かしたいオブジェクトがたくさんあるなら毎回これを書くのは大変なのでコンポーネントにしておいてもいいと思います。
IntervalTimer .cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class IntervalTimer : MonoBehaviour
{
public bool LoopActive;
[SerializeField] float interval;
[SerializeField] UnityEvent doSomething;
float interval_cnt;
void Update()
{
if (LoopActive)
{
if (interval_cnt <= 0)
{
doSomething?.Invoke();
interval_cnt = interval;
}
if (interval_cnt > 0) interval_cnt -= Time.deltaTime;
}
}
}
このスクリプトをアタッチして、定期的に実行したいメソッドを登録していきます。
音とBGM
音を出すにはAudioSourceとAudioClipを使います。
AudioSourceはBGMとSEで分けておいたほうがよいです。
SoundManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SoundManager : MonoBehaviour
{
// どこからでも参照できるようにしておく
public static SoundManager Instance;
AudioSource seAudioSource;
AudioSource bgmAudioSource;
[SerializeField] AudioClip bgmClip;
[SerializeField] AudioClip[] seClips;
private void Awake()
{
// Stage1でも管理オブジェクトを引き継ぐ
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(this);
} else
{
Destroy(gameObject);
}
// AudioSourceのコンポーネントが無かったら作っておく(インスペクタから入れるなら不要)
if (seAudioSource == null)
{
seAudioSource = gameObject.AddComponent<AudioSource>();
}
if (bgmAudioSource == null)
{
bgmAudioSource = gameObject.AddComponent<AudioSource>();
bgmAudioSource.volume = 0.1f;
}
}
/// <summary>
/// BGMを再生します
/// </summary>
public void PlayBGM()
{
bgmAudioSource.clip = bgmClip;
bgmAudioSource.Play();
}
/// <summary>
/// SEを鳴らします<br></br>
/// 番号はインスペクタに入れた順です
/// </summary>
/// <param name="num"></param>
public void PlaySE(int num)
{
if (num > seClips.Length)
{
return;
}
seAudioSource.clip = seClips[num];
seAudioSource.Play();
}
/// <summary>
/// SE音量を設定します
/// </summary>
/// <param name="volume"></param>
public void SetVolumeSE(float volume)
{
seAudioSource.volume = volume;
}
/// <summary>
/// BGM音量を設定します
/// </summary>
/// <param name="volume"></param>
public void SetVolumeBGM(float volume)
{
bgmAudioSource.volume = volume;
}
public float GetVolumeSE()
{
return seAudioSource.volume;
}
public float GetVolumeBGM()
{
return bgmAudioSource.volume;
}
public void StopBGM()
{
bgmAudioSource.Stop();
}
}
てきとうなオブジェクトにアタッチしてください。
BGMクリップとSEクリップに音を入れておきます。
SEクリップのほうは、Elementの番号がそのままPlayするときの番号になります。
使うときはInstance経由でPlayを呼び出します。前述のスタートカウントダウンのところで音を出すにはこんなかんじにします。
GameDirector.cs
IEnumerator countdown()
{
for (int i = COUNTDOWN_SEC; i > 0; i--)
{
textCountdown.text = i + "";
SoundManager.Instance.PlaySE(0);
// 1秒まつ
yield return new WaitForSeconds(1);
}
SoundManager.Instance.PlaySE(1);
textCountdown.text = "START !!";
}
ボリューム調整のスライダー
タイトル画面にボリューム調整のスライダーを入れておきましょう。
これがないとサウンド評価の★が1つ下がります。
でも正直ちょっと面倒です。もっと簡単な方法があったらおしえてください
まずはタイトルのシーンにSoundManagerとスライダーを置きます。
次に、スライダー用のスクリプトを作ります。
SoundSliderSE.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SoundSliderSE : MonoBehaviour
{
[SerializeField] Slider sliderSE;
private void Start()
{
sliderSE.value = SoundManager.Instance.GetVolumeSE();
}
public void SetVolumeSE(float volume)
{
SoundManager.Instance.SetVolumeSE(volume);
}
}
同じ内容のBGM版も作ります。
SoundSliderBGM.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SoundSliderBGM : MonoBehaviour
{
[SerializeField] Slider sliderBGM;
private void Start()
{
sliderBGM.value = SoundManager.Instance.GetVolumeBGM();
}
public void SetVolumeBGM(float volume)
{
SoundManager.Instance.SetVolumeBGM(volume);
}
}
スクリプトをスライダーにアタッチします
BGMも同じようにしてください。
このとき、SetVolumeのメソッドが2つあると思うのですが、下の方にあるのではなくて上の方にあるのを選んでください。下の方はニセモノです。
なぜスライダーにスクリプト1枚挟んでSetVolumeしているかというと、
スライダー標準のOnClickに直接SoundManagerのSetVolumeを入れているとステージ1に行ってタイトルに戻ってきたときにスライダーからSoundManagerへの参照が途切れてしまうからです。
これはSoundManagerでやってるDontDestroyOnLoadのせいです。
※DontDestroyOnLoadはタイトルで設定したSoundManager自体をStage1に持ってくための処置です。PlayerPrefでボリューム値を保存しておけば不要ですが、その場合全ステージにSoundManagerを配置しないといけないです。
スコアランキング
naichi様の解説をご覧ください。
なお、デフォルトのランキング画面からオリジナルの画面にカスタマイズすることができます。
あわせてごらんくださいませ。
まとめ
本記事では初めてunity1weekに参加するときに困りがちな(私が困った)TIPSをまとめました。
みなさまのゲームジャムが完成することを祈っております。
かわいい我が子にオリジナルアプリを!
コメント