c# - 如何将锁系统状态添加到我的 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 脚本中?
解决方案
推荐阅读
- excel - 如何在我的 excel vba 代码中添加循环以从一组工作簿中复制数据
- mysql - 无法转储数据库(从 xampp 迁移到 laragon)
- javascript - 基于循环渲染对象?
- reactjs - DocumentSnapshot.exists 在 Document 存在时返回 false
- html - 有没有办法从 chrome 开发人员工具中获取特定的反应指令?
- common-lisp - Common Lisp 中重复的 case 语句
- redirect - Drupal 8 内部重定向
- javascript - 基于任意排序的 Javascript 数组排序
- ubuntu - 在 /usr/share/webmin/changepass.pl 中找不到 ./acl/md5-lib.pl
- javascript - 我需要将两个 csv 文件合并为单个 csv 文件