【问题标题】:What is the best way to pass between scenes? [duplicate]在场景之间传递的最佳方式是什么? [复制]
【发布时间】:2019-12-14 08:47:27
【问题描述】:

我有 3 个场景。游戏,主菜单,经理。 在管理器上,我有一个带有保存管理器脚本的保存管理器对象:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.Serialization.Formatters.Binary;
using System;
using System.IO;

public class SaveManager : MonoBehaviour
{
    public static void Save(SaveState player)
    {
        BinaryFormatter formatter = new BinaryFormatter();
        string path = Application.persistentDataPath + "/player.bin";
        FileStream stream = new FileStream(path, FileMode.Create);

        formatter.Serialize(stream, player);
        stream.Close();
    }

    public static SaveState Load()
    {
        string path = Application.persistentDataPath + "/player.bin";
        if (File.Exists(path))
        {
            BinaryFormatter formatter = new BinaryFormatter();
            FileStream stream = new FileStream(path, FileMode.Open);

            SaveState data = formatter.Deserialize(stream) as SaveState;
            stream.Close();

            return data;
        }
        else
        {
            Debug.LogError("Save file not found in " + path);
            return null;
        }
    }
}

还有一个类: 这个 Save State 类应该稍后处理游戏中所有事物的状态。

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

[Serializable]
public class SaveState
{
    [Serializable]
    public struct SerializableVector3
    {
        public float X;
        public float Y;
        public float Z;

        public SerializableVector3(Vector3 v)
        {
            X = v.x;
            Y = v.y;
            Z = v.z;
        }

        // And now some magic
        public static implicit operator SerializableVector3(Vector3 v)
        {
            return new SerializableVector3(v);
        }

        public static implicit operator Vector3(SerializableVector3 sv)
        {
            return new Vector3(sv.X, sv.Y, sv.Z);
        }
    }

    [Serializable]
    public struct SerializableQuaternion
    {
        public float X;
        public float Y;
        public float Z;
        public float W;

        public SerializableQuaternion(Quaternion q)
        {
            X = q.x;
            Y = q.y;
            Z = q.z;
            W = q.w;
        }

        public static implicit operator SerializableQuaternion(Quaternion q)
        {
            return new SerializableQuaternion(q);
        }

        public static implicit operator Quaternion(SerializableQuaternion sq)
        {
            return new Quaternion(sq.X, sq.Y, sq.Z, sq.W);
        }
    }

    public SerializableVector3 position;
    public SerializableQuaternion rotation;
    public SerializableVector3 scale;

    public SaveState(Vector3 pos, Quaternion rot, Vector3 sca)
    {
        position = pos;
        rotation = rot;
        scale = sca;
    }

    public void ApplyToPlayer(Transform player)
    {
        player.localPosition = position;
        player.localRotation = rotation;
        player.localScale = scale;
    }
}

以及在游戏场景中附加到玩家的脚本:

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

public class PlayerState : MonoBehaviour
{
    public void Save()
    {
        SaveState saveState = new SaveState(transform.localPosition,
            transform.localRotation, transform.localScale);
       SaveManager.Save(saveState);
    }

    public void Load()
    {
        var playerInfo = SaveManager.Load();
        playerInfo.ApplyToPlayer(transform);
    }
}

在此之前,PlayerState 与 SaveManager 具有相同的场景,我在 Update 中使用输入键来保存和加载,它工作正常。

现在我想使用更新和输入键来使用我拥有的主菜单场景 ui 按钮保存和加载。问题是播放器是一个场景,主菜单是另一个场景,当玩家开始新游戏时,播放器被卸载并再次加载的场景会丢失主菜单 ui 按钮中的引用。

Save System 下 Main Menu 中的 Save/Load ui 按钮,这是我想在 On Click 事件中调用 PlayerState 脚本中的 Save/Load 函数的 ui 按钮。

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    我认为你最好的选择是确保你的经理和你的 UI 是持久的,所以只需设置:

    private void Awake()
    {
        DontDestroyOnLoad(this);
    }
    

    然后在他们的更新中只有一个 switch 语句检查当前场景,因此您将只更新该场景所需的内容,如下所示:

    private void Update()
    {
        switch(SceneManager.GetActiveScene().name)
        {
            case "Game":
                //Do you game update stuff...
                break;
    
            case "Menu":
                //Do your menu update stuff...
                break;
        }
    }
    

    希望对你有帮助:)

    【讨论】:

      猜你喜欢
      • 2012-12-18
      • 1970-01-01
      • 2021-04-28
      • 2014-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-29
      相关资源
      最近更新 更多