おみそしる✦前編

本日のおすすめです。 
実は世界一おいしいおみそしるの作り方を伝授!

表情差分
Webへのアップロードのやり方

いままでのレシピを組み合わせるだけでできます。
記念すべき定食の完成の瞬間!!


だしまきたまごの前編にある、
いつものじゃないスクリプトを使うやつ。

『作成』→『Scripting』→『ScriptableObject』

using System.Collections.Generic; //C#で型を決めたリストを作る
using UnityEngine; //標準C#を使うよ

[CreateAssetMenu(fileName = "New Data", menuName = "StoryData")] //新しいクラスを作れるようにするよ、それの名前はこれだよ
public class StoryData : ScriptableObject //StoryDataのクラスがScriptableObjectを継承するよ
{
    [System.Serializable] //クラスの前につけるとそのクラスを編集できるようになるよ
    public class Story //Storyの名前がついたクラスを編集できるようにしたよ
    {
        public Sprite Background; //背景の画像
        public Sprite CharacterImage; //キャラの立ち絵
        [TextArea] //↓ここからテキスト
        public string StoryText; //ストーリーのテキスト
        public string CharacterName; //キャラの名前
    }

    public List<Story> stories = new List<Story>(); //作成したリスト【Story】に【stories】を【new】として新しいリストを作れるよ
}

これで作れるようになる

『作成』→『StoryData』

中身こんな感じ

このときに一緒にここにいれるための画像をCanvasとして作っておく
『UI(Canvas)』から『画像』→背景と立ち絵、テキストウィンドウ入れよう


画面が合わないならこれ見て、多分できるはず


空のゲームオブジェクトに
ふたつめのスクリプト(ふつうのやつ)『StoryManager』をいれる

using System.Collections; //C#で型を決めたリストを作る
using System.Collections.Generic; //同じ処理を使い回せるようにするよ
using TMPro; //いいテキストを使うよ
using UnityEngine; //標準のC#を使うよ
using UnityEngine.UI; //標準で基本のC#を使うよ

public class StoryManager : MonoBehaviour //StoryManagerの初期スクリプトを使うよ
{
    [SerializeField] private StoryData[] storyDatas; //ストーリーデータのスクリプト
    [SerializeField] private Image background; //背景
    [SerializeField] private Image characterImage; //キャラの立ち絵
    [SerializeField] private TextMeshProUGUI storyText; //ストーリーのテキスト
    [SerializeField] private TextMeshProUGUI characterName; //キャラの名前

    [Header("===== テキスト演出設定 =====")]
    [SerializeField, Range(0.01f, 0.2f)] //0.01fから0.2fの間で設定できるよ
    private float typingSpeed = 0.05f; //0.05fで設定してるよ

    [Header("===== 効果音設定 =====")]
    [SerializeField] private AudioClip typingSE; //タイピング音
    [SerializeField] private AudioClip nextSE; //次に進むときの音
    [SerializeField, Range(0f, 1f)] //0fから1fの間で設定できるよ
    private float seVolume = 0.7f; //0.7fで設定してるよ

    public int storyIndex { get; private set; } = 0; //storyIndexを誰でも設定変更できるよ
    public int textIndex { get; private set; } = 0; //textIndexを誰でも設定変更できるよ

    private bool isTyping = false; //タイピング進行中か判定してくれる
    private string currentFullText = ""; //いま表示しようとしている全文を一時的に保存してくれる
    private Coroutine typingCoroutine = null; //いま表示しようとしているところのタイピング音の一時停止
    private AudioSource audioSource; //効果音を再生するのに必要
    private bool storyEnded = false; //ストーリーが終わったか確認してくれる 終わったら終わるための処理に入る

    private void Start() //すたーと!
    {
        audioSource = GetComponent<AudioSource>(); //同じゲームオブジェクトに音があるか確認してくれる
        if (audioSource == null) //音がなかったら自動的に音をつけてくれる
        {
            audioSource = gameObject.AddComponent<AudioSource>(); //音を追加してほしいよ~
            audioSource.playOnAwake = false; //音が鳴らないようにしてくれる
        }

        if (storyDatas == null || storyDatas.Length == 0) 
        { //ストーリーデータがないときに挙動がおかしくならないようにしてくれる
            Debug.LogError("storyDatasが空!"); 
            return;
        } //ストーリーデータがないときにインスペクターで設定してねって教えてくれる

        SetStoryElement(storyIndex, textIndex); //どこの処理をしているか教えてくれる
    }

    private void Update() //更新!
    {
        if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space))
        { //左クリックかスペースキーを押されたときを検知してくれる
            if (storyEnded) //このストーリーが終わったかどうかのチェックと分岐
            {
                Debug.Log("ストーリーは既に終了しています。"); //その時に終わっていることを教えてくれる
                return;
            }

            if (isTyping) //タイピング中のとき
            {
                if (typingCoroutine != null) StopCoroutine(typingCoroutine); //タイピングを終わらせる
                storyText.maxVisibleCharacters = currentFullText.Length; //全文表示
                isTyping = false; //タイピングの終わりを更新してくれる
                PlayNextSE(); //スキップしたよの効果音
            }
            else //まだ途中だよ
            {
                Next(); //つぎ!
            }
        }
    }

    public void Next() //つぎを始める!
    {
        if (storyEnded || storyIndex >= storyDatas.Length) // 全部見たか判定してくれる 
        {
            Debug.Log("ストーリーは既に終了しています。"); //終わったか教えてくれる
            return;
        }

        PlayNextSE(); //つぎへの効果音を鳴らすよ

        textIndex++; //つぎのテキストを表示するよ

        if (textIndex >= storyDatas[storyIndex].stories.Count) //全部見たか判定してくれる
        {
            textIndex = 0; //いまのテキスト表示が終わったよ
            storyIndex++; //いまのストーリーが終わったからつぎに進む準備をするよ

            if (storyIndex >= storyDatas.Length) //全部見たか教えてくれる
            {
                storyEnded = true; //ストーリーが終わったことを確認したら終わる準備に入る
                Debug.Log("全てのストーリーが終了しました。"); //終わったら教えてくれる
                return;
            }
        }

        SetStoryElement(storyIndex, textIndex);
    } //指定した位置を画面に全部反映してくれる、やっと動ける

    private void SetStoryElement(int _storyIndex, int _textIndex)
    { //セリフ変わったりキャラが変わるよ
        var currentStoryData = storyDatas[_storyIndex]; //いま処理しているところを編集できるようにしてくれる
        var storyElement = currentStoryData.stories[_textIndex]; //いま表示するべきものを取り出して表示するとこに入れてるよ

        background.sprite = storyElement.Background;
        characterImage.sprite = storyElement.CharacterImage;
        characterName.text = storyElement.CharacterName; //いま表示するべきものを反映してくれる
    
        currentFullText = storyElement.StoryText; //いま表示する全文を保存してくれてる

        if (typingCoroutine != null) StopCoroutine(typingCoroutine); //タイピングを終わらせてくれる

        storyText.text = currentFullText; //ストーリーテキストを全文セットしてくれる
        storyText.maxVisibleCharacters = 0; //何文字まで表示するかを非表示
        isTyping = true; //いまタイピング中だよ
        typingCoroutine = StartCoroutine(TypeText()); //一文字ずつ表示して音をだすループに入る
    }

    private IEnumerator TypeText() //タイピングテキストをできるように待機中
    {
        int total = currentFullText.Length; //全文の文字数を取得するよ
        isTyping = true; //いまタイピング中を確認

        for (int i = 0; i <= total; i++) //全表示終わりをループ
        {
            storyText.maxVisibleCharacters = i; //何文字まで出すかを指定できる

            if (i < total && !char.IsWhiteSpace(currentFullText[i]) && typingSE != null)
            { //文字と効果音を設定している場合だけ
                audioSource.PlayOneShot(typingSE, seVolume);
            } //タイピング音を鳴らしてくれる 文字や効果音がないときは鳴らさない

            yield return new WaitForSeconds(typingSpeed); //つぎの文字まで待機するよ
        }

        isTyping = false; //タイピング終わり
        typingCoroutine = null; //再開をさせないで終了判定してくれる
    }

    private void PlayNextSE() //つぎへの効果音
    {
        if (nextSE != null) //つぎのテキストにいくとき一度だけ
            audioSource.PlayOneShot(nextSE, seVolume); //つぎへ進む効果音の音量調整
    }
}
『要素』に『NewData』を入れていく

ここで設定されている
背景 立ち絵 セリフ 名前 は【場所】を決めるため

増やした『要素』ひとつひとつに同じ『NewData』を入れていく


『NewData』に
別の立ち絵を入れたら表情差分になる。
別のテキストを入力したら次のテキストに進むことができる。

『Typing Speed』でテキスト表示のスピードを変えられる。
マイナスにするとゆっくりになってくれる。


ここの設定が両方になってないと動かないかも。
両方なら動くはず。
動かなかったらその都度修正しに来てください

ここ詳しく載せておきたいもあれば更新しに来て


ここからアップする方法!
続きは後編で