投稿記事

しゅぽがきをしゅぽらせる【薄消】

最近名前が明らかになったけどシュポガキはシュポガキです

有料プランおまけは薄消し版高解像度版とテキスト無し差分です





今月はできればゲームの方のCGの進捗もまた公開したいです

【 一発500円 】プラン以上限定 支援額:500円

薄消・テキスト無し

このバックナンバーを購入すると、このプランの2024/04に投稿された限定特典を閲覧できます。 バックナンバーとは?

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

Unity開発メモ #9 セーブスロットシステムの実装

EasySave3によるセーブスロットシステムの実装

EasySave3というアセットでヘホゲのセーブシステムを構築しているという情報を得たのでヌケルさんもこちらのアセットを使用してシステムを構築しています


とても簡単にセーブ & ロードが実装できてやさしいアセットだと思います!


https://assetstore.unity.com/packages/tools/utilities/easy-save-the-complete-save-data-serializer-system-768




ただし値段は円安でやさしくない



変数のセーブとロード

EasySave3はオートセーブやゲーム内のオブジェクトの位置情報を保存するなど高度な機能があるが、今回のゲームでは変数さえ保存できればいいのでとても単純です。


各セーブスロットに変数をセーブする

ES3.Save関数を使います
https://docs.moodkie.com/easy-save-3/es3-api/es3-methods/es3-save/

public static void Save<T>(string key, T value, string filePath, ES3Settings settings)

<>にはデータ型、第1引数でセーブデータのキーを設定し、第2引数にはキーに格納する具体的なデータを入れ、第3引数はオプショナルで設定した場合は書き込み先のファイル名となります

下はインスペクターで指定した数字のスロットにゲームの進捗状況を管理する変数を格納しているProgressDataクラスの変数をセーブするコードです

ついでにセーブ時間も記録しています


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class SaveGame : MonoBehaviour
{

public int saveSlotNumber; // インスペクターで指定した1~3の数字のスロットにゲームの変数(ProgressData)をセーブする

// セーブボタンをクリックしたときに呼び出す
public void Save()
{
    string saveFileName = "save" + saveSlotNumber + ".es3"; // 例 saveSlotが1のときはsave1.es3にデータを保存する
    DateTime now = DateTime.Now; // 現在時刻の取得

    ES3.Save<int>("NowDay", ProgressData._NowDay, saveFileName);
    ES3.Save<int>("NowCharacter", ProgressData._NowCharacter, saveFileName);
    ES3.Save<bool>("Night", ProgressData._Night, saveFileName);

中略

    ES3.Save<int>("SavedMonth", now.Month, saveFileName);
    ES3.Save<int>("SavedDay", now.Day, saveFileName);
    ES3.Save<int>("SavedHour", now.Hour, saveFileName);
    ES3.Save<int>("SavedMinute", now.Minute, saveFileName);
    ES3.Save<int>("SavedSecond", now.Second, saveFileName);
}

}



各セーブスロットにセーブされた変数を出力する

セーブファイルからデータを取り出すときはES3.Loadを使います
https://docs.moodkie.com/easy-save-3/es3-api/es3-methods/es3-load/


public static T Load<T>(string key, string filePath, T defaultValue, ES3Settings settings)


<>には同じくデータ型を、第1引数でロードするデータのキーを設定し、第2引数では読込先のセーブファイルの名称を指定、defaultValueでは何も保存されていない場合に読み込むデフォルト値を設定します


ES3.Loadで読み取ったデータをゲームオブジェクト上のTextに反映させたりするようなコードを書けば、ゲーム画面上にどのようなセーブデータが保存されているかを表示することができるので、セーブスロットシステムの外観が整います



アイコン・日付表示・テキスト・進捗バー・セーブ時間・登録者数・やみ度の表示を各セーブスロットに保存されたデータをもとに表示しています


ロードしたデータをゲームに反映する

各セーブスロットのロードボタンを押したときに下記の処理を実行すれば実現できます

・ロードSceneに飛ばす
・ES3.Loadを使って必要な変数をゲーム内の進捗管理変数に代入する
・再開すべきSceneに戻す


コードにすると下のような感じです
ロードときはセーブファイルが存在するか確認してなければ処理を止める処理を入れておいた方がよさそうです



using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.SceneManagement;

public class LoadGame : MonoBehaviour
{

public int saveSlotNumber; // インスペクターで指定した1~3の数字のスロットからゲームの変数(ProgressData)をロードする

// ロードボタンをクリックしたときに呼び出す
public void Load()
{
    string saveFileName = "save" + saveSlotNumber + ".es3"; // 例 saveSlotが1のときはsave1.es3のデータをロードする

    if(!ES3.FileExists(saveFileName)) // ファイルが存在していない場合
    {
        return;
    }

    SceneManager.LoadScene("Loading"); // ロード画面に飛ばす

    // データをロードしProgressDataに格納していく

    ProgressData._NowDay = ES3.Load<int>("NowDay", saveFileName, defaultValue: 0);
    ProgressData._NowCharacter = ES3.Load<int>("NowCharacter", saveFileName, defaultValue: 2);
    

後略


ファイルの保存場所について



LocationをFile、DirectoryをPersistent Data pathに指定すると、C:/Users/Owner/AppDataに保存ファイル(es3ファイル)が作成される。
多くのUnity製アプリがここを保存場所にしており、安全と思われる。 (Unity標準ログ出力もここ)



LocationをDataPathにした場合はゲームフォルダ内の「ゲーム名_Data」に保存される。こちらの方が場所はわかりやすいか



Persistent Data pathの方が面倒ゴトが少なく安全そうなので、そちらで実装すると思います



他にもセーブファイルの暗号化機能とかもあるのですが、オンラインゲームではないのでセーブデータを改造して遊んでもらって全くかまわないので、あえてしないと思います




PlayerPrefsによるコンフィグ設定の保存

PlayerPrefはUnityにデフォルトで備わったデータ保存機能ですが、
種種の理由からセーブファイルの保存にはあまり推奨されていなようです

ただ言語設定やマスター音量等のコンフィグ設定であれば使ってもよさそう説も見かけたので、それぞれ保存するようにしてみました



以下はスライダーバーUIにアタッチするだけで、マスター音量の変更に加えて、変更した値を保存してゲーム再開時にその音量でプレイできるように作成したコードです

これで前回音量を下げたのにゲームを再開したら爆音でBGMがなるという事故が防げます、たぶん



using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MasterVolumeControl : MonoBehaviour
{

public Slider masterVolumeSlider;
private const string masterVolumeKey = "MasterVolume";

private void Start()
{
    // PlayerPrefsから保存されたマスター音量の値を読み込む
    float savedVolume = PlayerPrefs.GetFloat(masterVolumeKey, 1f);
    masterVolumeSlider.value = savedVolume;
    SetMasterVolume(savedVolume);

    // スライダーの値が変更されたときに呼び出されるイベントを登録
    masterVolumeSlider.onValueChanged.AddListener(OnMasterVolumeChanged);
}

private void OnMasterVolumeChanged(float volume)
{
    // スライダーの値が変更されたときに呼び出される関数
    SetMasterVolume(volume);
}

private void SetMasterVolume(float volume)
{
    // マスター音量を設定する
    AudioListener.volume = volume;

    // PlayerPrefsにマスター音量の値を保存する
    PlayerPrefs.SetFloat(masterVolumeKey, volume);
    PlayerPrefs.Save();
}

}





実績やアーカイブ(いわゆる回想)に関してはPlayerPrefsではなく、セーブスロットとは別のグローバルセーブデータをEasySave3で作成して管理しようと思います

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

Unityのポストエフェクトで遊びまくった成果


何かの演出に使えそうなポストエフェクト(ゲーム画面全体に適応する特殊効果)を作ってました
動画は作ったShader Graphとゲーム画面への適用結果です

たのしい



参考にした動画

Distortion Effect

https://www.youtube.com/watch?v=MaVmsOF4pXY

Glitch Effect

https://www.youtube.com/watch?v=VgBv6OrYY7E

Retro Effect

https://www.youtube.com/watch?v=k9g2LaBrirI

Pixelate Effect

https://www.youtube.com/watch?v=siiqnXA156Y

Marble Effect

https://www.youtube.com/watch?v=pr0CWXOBV4Y

その他

https://www.youtube.com/watch?v=Ylq2y6Qez3s

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

Unity開発メモ #8

フルスクリーンのポストプロセスをシェーダーグラフでつくる

ポストプロセスとは、レンダリングされたゲーム画面全体に最後にくわえられる特殊エフェクトのようなものです

FPSゲームで「ダメージを受けた際に視界が赤く」なったり、「ダンジョンに入るときに画面がフェードアウト」したり、卑猥なものがうつって突如「画面全体がモザイクになった」り、「いけないおくちゅりをのんだときに画面が揺れ」たりといった例がわかりやすいと思います


今回はUnity 2022.2から標準機能として搭載されたシェーダーグラフによるフルスクリーンエフェクト作成によって、「いけないおくちゅりをのんだときに画面が揺れ」る効果を作ってみました


(これのためにUnityのバージョン上げました、バージョン上げて不具合でなかったのでよかったです)

参考動画

https://www.youtube.com/watch?v=7Cd7kQl6N50

https://www.youtube.com/watch?v=AQGgwgo51lo

https://www.youtube.com/watch?v=Ylq2y6Qez3s

https://www.youtube.com/watch?v=E_oDKQU3e94&t=0s

参考記事

https://docs.unity3d.com/ja/Packages/com.unity.render-pipelines.universal@14.0/manual/Setup.html

https://qiita.com/generosity_honda/items/f091f8edc7d938c7b2fb

https://www.hanachiru-blog.com/entry/2022/12/22/120000


実装時のメモ

Fullscreen ShaderGraphがない

Create -> ShaderGraph -> URP -> Fullscreen ShaderGraphは、Unity 2022.2以降でないとありません

どのUniversal Renderer assetにFull Screen Pass Renderer Featureを追加するの?

Edit -> ProjectSettings -> Quality -> Rendering -> Render Pipeline Assetから使用しているRender Pipeline Assetを探し出し、InspectorからRendering -> Renderer Listに設定されているUniversal Renderer Dataを調べればOK
Asset > Settingに入ってるやつだった

とりあえず画面そのままのレンダリング結果をだしたい

URP Sample Bufferノード(BlitSource)でだせます

↑したんだけど画面が灰色一色のままなんだけど

シェーダーは保存しないと反映されません

シェーダーのオンオフをスクリプトで制御したい

chatGPTで出力されたコードをいじくって下のようなものをこさえました
とりあえず動きますが、もっとスマートな方法があったら教えてください


using UnityEngine;
using UnityEngine.Rendering.Universal;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using System.Collections;
public class UseDrag : MonoBehaviour
{

public Renderer2DData rendererData; // Renderer 2D Data への参照

(中略)

// 指定したフィーチャーを有効または無効にするメソッド
private void SetFeatureEnabled(string featureName, bool isEnabled)
{
    if (rendererData != null)
    {
        List<ScriptableRendererFeature> features = rendererData.rendererFeatures;

        foreach (var feature in features)
        {
            if (feature.name == featureName) // 指定した名前のフィーチャーを見つけた場合
            {
                feature.SetActive(isEnabled); // フィーチャーの有効・無効を設定する
                return;
            }
        }

        Debug.LogWarning($"Feature '{featureName}' not found in the Renderer 2D Data.");
    }
    else
    {
        Debug.LogWarning("Renderer 2D Data reference is not set.");
    }
}

(中略)

}



Drag 01 (Full Screen Pass Renderer Feature)のチェックをスクリプトでオンオフする挙動です

その他

遅延処理使いたいけどなぜかInvokeもコルーチンもうまくいかない

根本的な解決にはなっていないがTaskを使う方法もある
使うにはまず System.Threading.Tasks を読み込む必要がある。
await を使用して待機させるには、実行されるメソッドに async が付与されている必要がある。
単純に1秒待たせたいだけならこんな感じ

private async void DelayMethod()
{
await Task.Delay(1000);
Debug.Log("DelayMethod");
}

https://12px.com/blog/2016/11/unity-delay/

キャンバスの子要素のキャンバスを親より上に表示させたい

CanvasコンポーネントをアタッチしてOverride SortingいチェックをいれるとSort順を独立して設定できる

↑をやったら子要素のキャンバスがクリックできなくなった!

Graphic Raycasterコンポーネントをアタッチしないとキャンバスにはレイキャストが設定されないのでアタッチする

UIのトグルとかで別のオブジェクトのActiveを操作したい

Objectをインスペクターで指定してSetActiveを弄れる

画面のクリックをブロックしたい

画面全体最前面にレイキャストを持った透明なオブジェクトをかぶせる

テキストのレイキャストの無効化方法

インスペクターで設定できないのでコードをアタッチして対応

画像ファイル等の置き換え方法

Unityに同じ名前のファイルをドラッグアンドペーストしても新規で連番ファイルが作成されるだけ
正しくはShow in Explorer (win) で Explorerを開いてそこで置き換える


進捗

多言語対応システムはひとまず完成でテスト中

日付・時間遷移のシステム周りもおおむね完成しました

本編部分の前にシステム面をまずあらかた完成させてしまうつもりです


今後技術的に新規学習しなければならない要素としては、Live2Dのスクリプト制御、セリフ送り・選択肢分岐機能、ボイス・SE・BGM制御、セーブ・ロード機能、グローバルな回想・実績管理機能あたりかと思われます


今回はUnityの学習のためにあえて一人で1から完成させる感じなので、なるべくシンプルにプリミティブに、完成優先で進めたいと思います

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

台湾の夜市にえっちな売り子さんはいたのか? + 台湾限界旅行(金門島・921地震教育園区)

ひま潰しにYoutubeを巡回していたヌケルさんの目にある日、

異常な閲覧数をたたき出している「台湾で人気のイカ焼き屋台」の動画が飛び込んできた。



https://www.youtube.com/shorts/9ktGtWuROvk





上半身裸エプロンのような恰好でイカを屋台でひたすら焼く巨乳の女にコメント欄はわきあがっていたが、

よくよく動画をみると不審な点もある。


何らかのモデルとしか思えない女性のスタイルのよさに加え、

女をとなりから見守る腕に入れ墨の入った怪しげな男性がいたりと、何やら不穏な気配がただよっている…



台湾の夜市某所で撮影されたという映像、

はたして本当に台湾の夜市ではえっちなお姉さんが半裸エプロンでイカを焼いているのか?



実際に行って確かめてみた

(+マイナー台湾観光地紹介)

フォロワー以上限定無料

調査結果

無料

【 一発500円 】プラン以上限定 支援額:500円

金門島・921地震教育区ほか

このバックナンバーを購入すると、このプランの2024/03に投稿された限定特典を閲覧できます。 バックナンバーとは?

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

1 2 3 4 5 6 7

月別アーカイブ

記事を検索