Unity中不使用场景和预制体保存关卡信息(附源文件)
在游戏中我们搭建关卡的时候一般有两种办法,一种是一个关卡创建一个场景,还有一种是将所有的关卡做成预制体,然后进入游戏加载对应的预制体。
但是上面两种方法或多或少会导致安装包体积增大,所有有什么更简便的方法吗?
其实关卡信息,无非就是一些场景物体的排列组合,我们只要把一个关卡的所有物体的位置,旋转,缩放用文本的形式记录下来,我们就能复刻出一个场景的原貌了。
第一步:创建一个这样的场景(关卡1和关卡2是两个空对象,注意将坐标设为(0,0,0),不然保存的坐标会发生偏移,然后创建一些预制体放在Resources/Preform文件夹中,然后将预制体拖到场景中频成你想要的形状)
第二步:创建一个空对象同样把坐标设为(0,0,0),编写HighSave脚本,并将脚本拖到这个空对象上
脚本:
using System.IO;
using UnityEngine;
public class HighSave : MonoBehaviour
{
public string levelName;
public GameObject levelonj;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
for (int i = 0; i < levelonj.transform.childCount; i++)
{
Transform childTransform = levelonj.transform.GetChild(i);
Debug.Log(childTransform.name + " : " + childTransform.position + " : " + childTransform.rotation + " : " + childTransform.localScale + "\n");
}
}
if (Input.GetKeyDown(KeyCode.A))
{
string content = null;
string filePath = Application.persistentDataPath + levelonj.gameObject.name + ".txt";
for (int i = 0; i < levelonj.transform.childCount; i++)
{
Transform childTransform = levelonj.transform.GetChild(i);
content += childTransform.name + ":" + childTransform.position + ":" + childTransform.rotation + ":" + childTransform.localScale + "\n";
}
File.WriteAllText(filePath, content);
Debug.Log("数据已保存");
}
if (Input.GetKeyDown(KeyCode.S))
{
string content = null;
string filePath = null;
if (levelName != null)
{
filePath = Application.persistentDataPath + levelName + ".txt";
}
else
{
Debug.Log("关卡名称为空");
return;
}
if (!File.Exists(filePath))
{
Debug.Log("文件不存在");
return;
}
content = File.ReadAllText(filePath);
string[] lines = content.Split('\n');
for (int i = 0; i < lines.Length - 1; i++)
{
string[] parts = lines[i].Split(':');
if (parts.Length < 4)
{
Debug.LogWarning($"格式不正确: {lines[i]}");
continue;
}
string objname = parts[0];
string positionString = parts[1];
string rotationString = parts[2];
string scaleString = parts[3];
GameObject obj = Resources.Load<GameObject>("Preform/" + objname);
if (obj == null)
{
Debug.LogWarning($"无法加载对象: {objname}");
continue;
}
GameObject instantiatedObj = Instantiate(obj, transform);
Transform instantiatedTransform = instantiatedObj.transform;
// 解析位置字符串
positionString = positionString.Trim('(', ')'); // 去掉括号
string[] positionCoordinates = positionString.Split(',');
Vector3 position = new Vector3(
float.Parse(positionCoordinates[0].Trim()), // 解析 x 坐标
float.Parse(positionCoordinates[1].Trim()), // 解析 y 坐标
float.Parse(positionCoordinates[2].Trim()) // 解析 z 坐标
);
// 解析旋转字符串
rotationString = rotationString.Trim('(', ')'); // 去掉括号
string[] rotationCoordinates = rotationString.Split(',');
Quaternion rotation = new Quaternion(
float.Parse(rotationCoordinates[0].Trim()), // 解析 x 坐标
float.Parse(rotationCoordinates[1].Trim()), // 解析 y 坐标
float.Parse(rotationCoordinates[2].Trim()), // 解析 z 坐标
float.Parse(rotationCoordinates[3].Trim()) // 解析 w 坐标
);
// 解析缩放字符串
scaleString = scaleString.Trim('(', ')'); // 去掉括号
string[] scaleCoordinates = scaleString.Split(',');
Vector3 scale = new Vector3(
float.Parse(scaleCoordinates[0].Trim()), // 解析 x 坐标
float.Parse(scaleCoordinates[1].Trim()), // 解析 y 坐标
float.Parse(scaleCoordinates[2].Trim()) // 解析 z 坐标
);
instantiatedTransform.position = position; // 设置位置
instantiatedTransform.rotation = rotation; // 设置旋转
instantiatedTransform.localScale = scale; // 设置缩放
Debug.Log(objname + " : " + position + " : " + rotation + " : " + scale);
}
}
}
}
参数说明
第三步: 运行游戏,生成对应的关卡文本
先后将关卡1和关卡2拖到对应的位置然后按下A,就会看到打印出了保存成功就说明OK了。
然后在C:\Users\用户名\AppData\LocalLow\DefaultCompany。这个文件夹的路径下找到保存的关卡信息
可以看到数据通过文本的信息保存了下来。
第4步:将关卡1和关卡2删掉,然后运行游戏读取关卡(填写你需要读取的关卡名字,必须是之前保存了的),运行游戏按下S就能读取之前保存的关卡数据了
注意事项:
1:关卡的中的所有物体必须要有对应的预制体,或者由预制体变换得来,不然加载的时候会报错,最好是把所有预制体做好了再拖动搭建关卡。
2.Resources其实也挺占用资源的,实际中可以把预制体改为AB包加载。
3.这里是将生成的文本保存在了本地,然后加载的时候也是读取的本地文本,这样在别人电脑上就不好使了,可以将生成好的文本也做成AB包之后通过AB包加载。
项目源文件
https://github.com/laozhupeiqia/HighSave.git
如果这篇文章对你有帮助欢迎点赞支持哦。