如何保存和加载用户创建的游戏对象?

Posted

技术标签:

【中文标题】如何保存和加载用户创建的游戏对象?【英文标题】:How can I save and load the gameObject that the user creates? 【发布时间】:2019-01-13 20:30:13 【问题描述】:

我已经实现了用户可以选择自定义 3D 对象的所有选项,并添加了一些 GUI 按钮来改进我的旧代码并提高可用性。但是我在弄清楚如何保存和加载游戏对象时遇到了一些麻烦。

我读过关于序列化的文章,也看到有人提到 PlayerPrefs,但我仍然无法理解如何将它与对象一起使用。

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

 public class cubeControls : MonoBehaviour
 
     // Constants for object rotation
     public float moveSpeed = 80.0F;
     public float turnSpeed = 100.0F;

     // Initial scale of the original cube
     public static Vector3 initscale = Vector3.one;

     // Start is called before the first frame update
     void Start()
     
     

     // Update is called once per frame
     void Update()
     
         // Changing the position of the object

         // Moving the object right
         if (Input.GetKey(KeyCode.D))
         
             transform.Translate(Vector3.right * moveSpeed * Time.deltaTime);
     

         // Moving the object left
         if (Input.GetKey(KeyCode.A))
         
             transform.Translate(Vector3.left * moveSpeed * Time.deltaTime);
     

         // Changing the rotation of the object

         // Rotating the cube to the right
         if (Input.GetKey(KeyCode.RightArrow))
         
             transform.Rotate(Vector3.up, turnSpeed * Time.deltaTime);
         

         // Rotating the cube to the left
         if (Input.GetKey(KeyCode.LeftArrow))
         
             transform.Rotate(Vector3.down, turnSpeed * Time.deltaTime);
         

         // Saving the current rendered material
         Renderer rend = GetComponent<Renderer>();

         // Changing the scale of the object

         // Double the size of the cube
         if (Input.GetKeyDown(KeyCode.Alpha2))
         
             transform.localScale += new Vector3(2F, 2F, 2F);
         

         // Changing the color via key presses

         if (Input.GetKeyDown(KeyCode.R))
         
             rend.material.SetColor("_Color", Color.red);
         
     

     // To add button elements to the visual interface
     void OnGUI() 
     
         // Changing to cylinder
         if (GUI.Button(new Rect(50, 90, 100, 40), "Cylinder"))
         
             GameObject newCylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
             newCylinder.AddComponent<cubeControls>();
             Destroy(gameObject);
         

         // Saving
         if (GUI.Button(new Rect(700, 330, 50, 30), "Save"))
         
         

         // Loading
         if (GUI.Button(new Rect(770, 330, 50, 30), "Load"))
         
         
     
 

【问题讨论】:

【参考方案1】:

您无法保存游戏对象。您唯一保存的是游戏对象的详细信息。举个例子,如果你有一个带有一些粒子效果的 3D 立方体,你首先保存立方体的所需值,如位置、旋转、缩放、颜色和其他必要的元素(需要更改的粒子发射器值)。即使在序列化中,您也无法保存 Vector3,因为它是一个结构,并且必须为向量编写自己的序列化程序。简而言之,您保存的游戏对象工作所需的值以及需要来自用户/其他系统的自定义输入的其他行为特征。可以将其视为通过保存和加载影响对象的变量状态来将对象重建到停止状态的一种方式。

Unity保存有两种类型

1) Player prefs :使用播放器首选项,您一次只能在字段中保存一个值。通常是三个之一:

浮动 诠释 字符串

您通常会保存令牌和其他不需要大文件的小值

2) 序列化游戏数据:在这里您可以将大型数据集和类(如 PlayerInfo、自定义场景更改)保存在序列化文件中。

我相信您正在寻找的是第二个。因此,与其查找所有示例并感到困惑,您真正可以开始的是在文件中保存/加载多维数据集值(可能是位置?或您在运行时修改的任何内容)。逐渐你可以转向序列化程序。

您可以查看以下链接以帮助您进一步了解。

Reference

Save/Load Data using simple BinaryFormatter

XML serialiser


这个保存 sn-p 来自简单的二进制格式器链接,它保存了一些类型和用户分数的整数列表。

[System.Serializable]
public class Save

  public List<int> livingTargetPositions = new List<int>();
  public List<int> livingTargetsTypes = new List<int>();

  public int hits = 0;
  public int shots = 0;


private Save CreateSaveGameObject()

  Save save = new Save();
  int i = 0;
  foreach (GameObject targetGameObject in targets)
  
    Target target = targetGameObject.GetComponent<Target>();
    if (target.activeRobot != null)
    
      save.livingTargetPositions.Add(target.position);
      save.livingTargetsTypes.Add((int)target.activeRobot.GetComponent<Robot>().type);
      i++;
    
  

  save.hits = hits;
  save.shots = shots;

  return save;


public void SaveGame()

  // 1
  Save save = CreateSaveGameObject();

  // 2
  BinaryFormatter bf = new BinaryFormatter();
  FileStream file = File.Create(Application.persistentDataPath + "/gamesave.save");
  bf.Serialize(file, save);
  file.Close();

  // 3
  hits = 0;
  shots = 0;
  shotsText.text = "Shots: " + shots;
  hitsText.text = "Hits: " + hits;

  ClearRobots();
  ClearBullets();
  Debug.Log("Game Saved");

【讨论】:

感谢您的详尽解释!好的,所以我设法使用序列化、PlayerPrefs 和 JSON 以字符串的形式保存了位置坐标 (x, y, z)。我已经确认它们确实保存在字符串中并且字符串不为空,但是我将如何获取这些值并重绘 3D 对象?由于 3D 对象的形状不能像其他属性一样以字符串格式保存。 您重新初始化 3d 对象并使用您保存的值在关卡中调整对象参数。现在,如果您想在保存中取回 3d 对象的位置,只需从文件中获取位置坐标并将其设置回您的对象上 一般STOP using the BinaryFormatter at all!

以上是关于如何保存和加载用户创建的游戏对象?的主要内容,如果未能解决你的问题,请参考以下文章

Python - 向用户显示游戏保存文件的推荐方式

如何加载文件并创建无限保存文件?

在泡菜文件中保存和加载多个对象?

Django:保存创建对象实例的用户

从保存的文件初始化类

应用程序进入/离开后台时保存和加载数据