1.首先
可可有限公司的“椰子技术谈话”我使用了 LT 文章作为参考。
谢谢你。
本文使用的 Unity 版本为“Unity 2021.3.1f1”。
2. 为什么不使用单例
综上所述,如果您只想在场景之间保留信息,则不需要使用单例。是。
首先使用单例的原因是因为
- 我要确保只有一个实例
- 我想获得来自不同类的引用
等等。
在游戏开发中,你可能会遇到使用单例更方便的情况。
“这个 `Manager'' 是一个我经常使用的类,所以让我们让它成为一个单例。”
如果你用一个简单的想法让它成为一个单身人士,比如具有无数引用的紧耦合类完成了。
如果你不小心使用它,可读性会很差,并且设计会变得相互依赖。
另外,实际上可以说,当事实证明拥有多个实例更方便时,影响范围非常大。
3. 实施细节
在每个场景的根对象中放置一个继承 AbstractScene 的组件。
基类 AbstractScene 的详细信息。
这个放置在每个场景中并使用它接收到的变量。
抽象场景.cs
using UnityEngine;
using Cysharp.Threading.Tasks;
public abstract class AbstructScene : MonoBehaviour
{
protected SceneOperator _sceneOperator;
private void Awake()
{
OnAwake();
}
protected virtual void OnAwake() { }
/// <summary>
/// SceneOperatorのLoadSceneを非同期で呼ぶ
/// </summary>
public async void LoadScene(string sceneName,string message)
{
//最初に一度インスタンスを初期化
if (_sceneOperator == null)
{
_sceneOperator = new SceneOperator(message);
}
await _sceneOperator.LoadScene(sceneName);
}
/// <summary>
/// 前のシーンからSceneOperatorを引き継ぐための関数
/// </summary>
public void SetOperator(SceneOperator appOperator)
{
_sceneOperator = appOperator;
}
/// <summary>
/// ロード時に呼ばれる
/// </summary>
public abstract UniTask OnLoad(string message);
/// <summary>
/// ロードされた後に呼ばれる
/// </summary>
public abstract void OnOpen();
/// <summary>
/// シーンの破棄時に呼ばれる
/// </summary>
public abstract UniTask OnUnLoad();
}
异步加载一个场景并将值传递给下一个场景的 AbstractScene。
场景操作员.cs
using UnityEngine;
using System.Threading;
using UnityEngine.SceneManagement;
using Cysharp.Threading.Tasks;
public class SceneOperator
{
/// <summary>
/// シーン間で保持する文字列
/// </summary>
string _message;
public SceneOperator(string message)
{
SetUp(message);
}
public void SetUp(string message)
{
_message = message;
}
public async UniTask LoadScene(string sceneName)
{
//シーンを破棄
await GetActiveAbstructScene(SceneManager.GetActiveScene()).UnLoad();
//シーンをロード
await SceneManager.LoadSceneAsync(sceneName);
//ロード先のAbstructSceneを取得
var absScene = GetActiveAbstructScene(SceneManager.GetSceneByName(sceneName));
absScene.SetOperator(this);
//ロード時の処理を呼ぶ
await absScene.Load(_message);
absScene.Open();
}
/// <summary>
/// シーン内のRootObjectsからAbstructSceneを返す
/// </summary>
AbstructScene GetActiveAbstructScene(Scene scene)
{
AbstructScene abstructScene = null;
foreach (var obj in scene.GetRootGameObjects())
{
if (obj.TryGetComponent(out AbstructScene getAbstructScene))
{
abstructScene = getAbstructScene;
break;
}
}
if (abstructScene)
{
return abstructScene;
}
else
{
throw new System.ArgumentNullException($"{scene.name}のRootObjectsにAbstructSceneがアタッチされたオブジェクトが含まれていません。");
}
}
}
AbstractScene 的实现示例。
InGameManager.cs
using UnityEngine;
using UnityEngine.UI;
using Cysharp.Threading.Tasks;
public class InGameManager : AbstructScene
{
/// <summary>シーン内で使用する文字列</summary>
protected string _message = "";
[Header("コンポーネント")]
[SerializeField,Tooltip("押下時にロードが呼ばれるボタン")]
Button _loadButton;
[SerializeField,Tooltip("押下時に次のシーンに渡したい文字列を決定するボタン")]
Button _inputButton;
[SerializeField,Tooltip("次のシーンに渡したい文字列を入力するフィールド")]
protected InputField _inputField = null;
[SerializeField,Tooltip("現在保持されている変数を表示するText")]
protected Text _text;
[Header("ロード関連")]
[SerializeField,Tooltip("ロード先のシーン名")]
string _sceneName;
protected override void OnAwake()
{
//押下時に指定のシーンにロードする。
_loadButton.onClick.AddListener(() => { LoadScene(_sceneName, _inputField.text); });
//押下時に次のシーンに渡す文字列を変更する
_inputButton.onClick.AddListener(() => {
if (_sceneOperator == null)
{
_sceneOperator = new SceneOperator(_inputField.text);
}
else
{
_sceneOperator.SetUp(_inputField.text);
}
});
}
public override async UniTask Load(string message)
{
_message = message;
await UniTask.Yield();
}
/// <summary>
/// シーンがロードされた後に呼ばれる
/// </summary>
public override void Open()
{
_text.text = _message;
}
public override async UniTask UnLoad()
{
await UniTask.Yield();
}
}
这是我运行它时的样子:
按下中间按钮切换场景,上面显示的文本会跨场景保留。
您可以更改 InputField 中的值。
需要注意的是,根据 AbstractScene,没有源或子,因此在使用该值的类中需要一些独创性。 ,
4.总结
顺便说一句,我从不反对单例 w (输入等往往是单例)
单例是一种在 GoF 和其他地方被采用和使用的设计模式,但使用起来可能有点棘手。
这一次,我尝试实现它的目的是增加设计抽屉的数量。
这似乎可以防止使用单例往往发生的紧密耦合。
这是我第一次在Qiita上发表文章,所以如果有任何错误或错误,请告诉我。
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308631851.html