首页 > 解决方案 > 如何将锁系统状态添加到我的 SaveState 类?

问题描述

锁定系统脚本:

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

public class LockSystem : MonoBehaviour
{
    public bool mouseCursorLockState = true;
    public PlayerCameraController playerCameraController;
    public PlayerController playerController;

    // Start is called before the first frame update
    void Start()
    {
        MouseCursorLockState(mouseCursorLockState);
    }

    public void MouseCursorLockState(bool lockState)
    {
        if (lockState == false)
        {
            Cursor.visible = true;
            Cursor.lockState = CursorLockMode.None;
        }
        else
        {
            Cursor.visible = false;
            Cursor.lockState = CursorLockMode.Locked;
        }
    }

    public void PlayerLockState(bool LockPlayer, bool LockPlayerCamera)
    {
        if (LockPlayer == true)
        {
            playerController.enabled = false;
        }
        else
        {
            playerController.enabled = true;
        }

        if (LockPlayerCamera == true)
        {
            playerCameraController.enabled = false;
        }
        else
        {
            playerCameraController.enabled = true;
        }
    }
}

我在游戏的某些地方使用它,例如:

public LockSystem playerLockMode;
playerLockMode.PlayerLockState(true, false);

playerLockMode 位于顶部,在某些功能中使用它只是我如何使用它的示例。

保存状态类。到目前为止,我可以保存任何对象位置旋转缩放。现在我还想保存锁定系统状态:

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;
    }

    public bool LockState(bool lockState)
    {

        return lockState;
    }
}

我试图在底部添加新函数 LockState 但这不是处理它的正确方法。

保存管理器脚本:

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;
        }
    }
}

用于保存播放器状态的播放器状态脚本,但我也可以在此处保存锁定系统状态,但尚不确定如何:

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

public class PlayerState : MonoBehaviour
{
    private void Awake()
    {
        Save();
    }

    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);
    }
}

游戏开始后,我将在 Awake 中保存一次。然后将加载函数调用到我的主菜单 ui 按钮:

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

public class MainMenu : MonoBehaviour
{
    public void StartNewGame()
    {
        ScenesManager.StartNewGame();
    }

    public void LoadGame()
    {
        var playerstate = GameObject.Find("Player").GetComponent<PlayerState>();
        playerstate.Load();
    }

    public void ResumeGame()
    {
        ScenesManager.ResumeGame();
    }

    public void QuitGame()
    {
        Application.Quit();
    }
}

我的想法是在游戏开始时保存一个,然后使用计时器,例如每 5 分钟保存一次。所以我只在主菜单中调用加载函数。保存将在游戏过程中自动进行。

在 SaveState 类中,我想添加越来越多的东西来保存它的状态,比如锁定系统和协程状态。游戏从一个正在运行的协同程序开始,它产生了一些效果。如果游戏在协程运行时开始或稍后保存,我还想保存协程状态,因此也要保存当前协程状态。

这是游戏开始的时候:

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

public class DepthOfField : MonoBehaviour
{
    public UnityEngine.GameObject player;
    public PostProcessingProfile postProcessingProfile;
    public bool dephOfFieldFinished = false;
    public LockSystem playerLockMode;

    private Animator playerAnimator;
    private float clipLength;
    private Coroutine depthOfFieldRoutineRef;

    // Start is called before the first frame update
    void Start()
    {
        if (depthOfFieldRoutineRef != null)
        {
            StopCoroutine(depthOfFieldRoutineRef);
        }

        playerAnimator = player.GetComponent<Animator>();

        AnimationClip[] clips = playerAnimator.runtimeAnimatorController.animationClips;
        foreach (AnimationClip clip in clips)
        {
            clipLength = clip.length;
        }

        DepthOfFieldInit(clipLength);

        // Don't forget to set depthOfFieldRoutineRef to null again at the end of routine!
    }

    public void DepthOfFieldInit(float duration)
    {
        var depthOfField = postProcessingProfile.depthOfField.settings;
        depthOfField.focalLength = 300;
        StartCoroutine(changeValueOverTime(depthOfField.focalLength, 1, duration));
        postProcessingProfile.depthOfField.settings = depthOfField;
    }

    public IEnumerator changeValueOverTime(float fromVal, float toVal, float duration)
    {
        playerLockMode.PlayerLockState(true, true);

        float counter = 0f;

        while (counter < duration)
        {
            var dof = postProcessingProfile.depthOfField.settings;

            counter += Time.deltaTime;

            float val = Mathf.Lerp(fromVal, toVal, counter / duration);

            dof.focalLength = val;
            postProcessingProfile.depthOfField.settings = dof;

            yield return null;
        }

        playerAnimator.enabled = false;
        dephOfFieldFinished = true;
        depthOfFieldRoutineRef = null;
    }
}

这是游戏开始的截图和协程运行时的效果:这个模糊效果是由 PostProcessing 和协程完成的。如果那样的话,我也想保存状态。

启动效果

保存对象信息很容易,例如位置旋转和缩放,但是如何保存其他东西的状态,例如锁定系统和 DepthOfField ?我应该如何扩展 SaveState 类,然后如何使用它将它保存在 PlayerState 脚本中?

标签: c#unity3d

解决方案


推荐阅读