如何保存一个二维数组,作为变量检查器的一部分?
How to save a two-dimensional array, as part of the variable inspector?
我有一个包含一些变量的组件。重新启动 Unity 时将保存变量。 (整数,颜色,浮点数)
using UnityEngine;
using System.Collections;
public class Grid : MonoBehaviour
{
public float startX = 0;
public float startZ = 0;
public int width = 1000;
public int height = 1000;
public float boxWidth = 32.0f;
public float boxHeight = 32.0f;
public float px;
public float pz;
public Color color = Color.white;
public bool[,] map;
void OnDrawGizmos()
{
if (map != null)
{
Vector3 pos = transform.position;
px = pos.x + startX;
pz = pos.z + startZ;
Gizmos.color = color;
Vector3 size = new Vector3(boxWidth, 0f, boxHeight);
for (int x = 0; x < width; x++)
{
for (int z = 0; z < height; z++)
{
if (map[x, z])
{
Gizmos.DrawCube(new Vector3(px + x * boxWidth, pos.y + 1, pz + z * boxHeight), size);
}
else
{
Gizmos.DrawWireCube(new Vector3(px + x * boxWidth, pos.y + 1, pz + z * boxHeight), size);
}
}
}
}
}
}
要编辑变量,我有我的检查员:
using UnityEngine;
using UnityEditor;
using System.Collections;
[CustomEditor (typeof(Grid))]
public class GridEditor : Editor
{
Grid grid;
public void OnEnable()
{
grid = (Grid)target;
SceneView.onSceneGUIDelegate += GridUpdate;
if (grid.map == null)
{
grid.map = new bool[grid.width, grid.height];
for (int x = 0; x < grid.width; x++)
{
for (int y = 0; y < grid.height; y++)
{
grid.map[x, y] = false;
}
}
}
}
public void OnDisable()
{
SceneView.onSceneGUIDelegate -= GridUpdate;
}
private int lastX = -1;
private int lastZ = -1;
void OnSceneGUI()
{
Event e = Event.current;
Camera camera = Camera.current;
Vector3 mousePos = Vector3.zero; // = camera.ScreenToWorldPoint(new Vector3(e.mousePosition.x, e.mousePosition.y, distance));
if (EventType.KeyDown == e.type && KeyCode.LeftControl == e.keyCode)
{
Ray ray = camera.ScreenPointToRay(new Vector3(e.mousePosition.x, -e.mousePosition.y + camera.pixelHeight, 0));
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 2550f))
{
mousePos = hit.point;
}
int x = Mathf.RoundToInt((mousePos.x - grid.px)/grid.boxWidth);
int z = Mathf.RoundToInt((mousePos.z - grid.pz)/grid.boxHeight);
if (x >= 0 && x < grid.width && z >= 0 && z < grid.height)
{
if (x != lastX || z != lastZ)
{
grid.map[x, z] = !grid.map[x, z];
lastX = x;
lastZ = z;
SceneView.RepaintAll();
}
}
}
}
public override void OnInspectorGUI()
{
GUILayout.BeginHorizontal();
GUILayout.Label(" Start x ");
grid.startX = EditorGUILayout.FloatField(grid.startX, GUILayout.Width(50));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label(" Start z ");
grid.startZ = EditorGUILayout.FloatField(grid.startZ, GUILayout.Width(50));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label(" Grid Width ");
grid.width = EditorGUILayout.IntField(grid.width, GUILayout.Width(50));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label(" Grid Height ");
grid.height = EditorGUILayout.IntField(grid.height, GUILayout.Width(50));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label(" Box Width ");
grid.boxWidth = EditorGUILayout.FloatField(grid.boxWidth, GUILayout.Width(50));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label(" Box Height ");
grid.boxHeight = EditorGUILayout.FloatField(grid.boxHeight, GUILayout.Width(50));
GUILayout.EndHorizontal();
if (GUILayout.Button("Open Grid Window", GUILayout.Width(255)))
{
GridWindow window = (GridWindow) EditorWindow.GetWindow(typeof (GridWindow));
window.Init();
}
SceneView.RepaintAll();
}
}
不幸的是,我无法弄清楚如何存储一个二维数组(map[])的boolean,所以他在重启Unity时仍然存在。所有我来它是为了对文件进行序列化并在启动应用程序时查找文件。 (数组可以很大 1000x20)也许你可以提出一个更好的主意?谢谢!请原谅我的英语。
问题实际上与数据类型无关,例如地图,在你的情况下。你可以试试ScriptableObject class,它不需要附加到一些游戏对象
从 ScriptableObject 派生一个 class 并将 [Serializable] 属性添加到 class
[Serializable]
class MyData: ScriptableObject
{
public bool[,] map;
void OnEnable() {
//... do something to initialise the map or reload the map
}
}
实例化对象保存数据
//in this case MyData contains your map data
var data = SciptableObject.CreateInstance(typeof(MyData));
保存到Unity数据库:
AssetDatabase.CreateAsset(data, "Assets/SomeFolder/abc.asset");
AssetDatabase.SaveAssets()
AssetDatabase.Refresh();
检查资产中是否已经有一些资产:
var data = AssetDatabase.LoadAssetAtPath("Assets/SomeFolder/abc.asset",
typeof(SomeData));
if(data != null) {
//Your own logic to consume the map or whatever data
}
这样,当 Unity 重新启动时,所有变量都将被保存,您可以在 class 上添加 [InitializeOnLoad] 属性以使其自动加载。并且unity里面可以看到abc.asset文件,使用自定义编辑器编辑地图也是小菜一碟。
我有一个包含一些变量的组件。重新启动 Unity 时将保存变量。 (整数,颜色,浮点数)
using UnityEngine;
using System.Collections;
public class Grid : MonoBehaviour
{
public float startX = 0;
public float startZ = 0;
public int width = 1000;
public int height = 1000;
public float boxWidth = 32.0f;
public float boxHeight = 32.0f;
public float px;
public float pz;
public Color color = Color.white;
public bool[,] map;
void OnDrawGizmos()
{
if (map != null)
{
Vector3 pos = transform.position;
px = pos.x + startX;
pz = pos.z + startZ;
Gizmos.color = color;
Vector3 size = new Vector3(boxWidth, 0f, boxHeight);
for (int x = 0; x < width; x++)
{
for (int z = 0; z < height; z++)
{
if (map[x, z])
{
Gizmos.DrawCube(new Vector3(px + x * boxWidth, pos.y + 1, pz + z * boxHeight), size);
}
else
{
Gizmos.DrawWireCube(new Vector3(px + x * boxWidth, pos.y + 1, pz + z * boxHeight), size);
}
}
}
}
}
}
要编辑变量,我有我的检查员:
using UnityEngine;
using UnityEditor;
using System.Collections;
[CustomEditor (typeof(Grid))]
public class GridEditor : Editor
{
Grid grid;
public void OnEnable()
{
grid = (Grid)target;
SceneView.onSceneGUIDelegate += GridUpdate;
if (grid.map == null)
{
grid.map = new bool[grid.width, grid.height];
for (int x = 0; x < grid.width; x++)
{
for (int y = 0; y < grid.height; y++)
{
grid.map[x, y] = false;
}
}
}
}
public void OnDisable()
{
SceneView.onSceneGUIDelegate -= GridUpdate;
}
private int lastX = -1;
private int lastZ = -1;
void OnSceneGUI()
{
Event e = Event.current;
Camera camera = Camera.current;
Vector3 mousePos = Vector3.zero; // = camera.ScreenToWorldPoint(new Vector3(e.mousePosition.x, e.mousePosition.y, distance));
if (EventType.KeyDown == e.type && KeyCode.LeftControl == e.keyCode)
{
Ray ray = camera.ScreenPointToRay(new Vector3(e.mousePosition.x, -e.mousePosition.y + camera.pixelHeight, 0));
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 2550f))
{
mousePos = hit.point;
}
int x = Mathf.RoundToInt((mousePos.x - grid.px)/grid.boxWidth);
int z = Mathf.RoundToInt((mousePos.z - grid.pz)/grid.boxHeight);
if (x >= 0 && x < grid.width && z >= 0 && z < grid.height)
{
if (x != lastX || z != lastZ)
{
grid.map[x, z] = !grid.map[x, z];
lastX = x;
lastZ = z;
SceneView.RepaintAll();
}
}
}
}
public override void OnInspectorGUI()
{
GUILayout.BeginHorizontal();
GUILayout.Label(" Start x ");
grid.startX = EditorGUILayout.FloatField(grid.startX, GUILayout.Width(50));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label(" Start z ");
grid.startZ = EditorGUILayout.FloatField(grid.startZ, GUILayout.Width(50));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label(" Grid Width ");
grid.width = EditorGUILayout.IntField(grid.width, GUILayout.Width(50));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label(" Grid Height ");
grid.height = EditorGUILayout.IntField(grid.height, GUILayout.Width(50));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label(" Box Width ");
grid.boxWidth = EditorGUILayout.FloatField(grid.boxWidth, GUILayout.Width(50));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label(" Box Height ");
grid.boxHeight = EditorGUILayout.FloatField(grid.boxHeight, GUILayout.Width(50));
GUILayout.EndHorizontal();
if (GUILayout.Button("Open Grid Window", GUILayout.Width(255)))
{
GridWindow window = (GridWindow) EditorWindow.GetWindow(typeof (GridWindow));
window.Init();
}
SceneView.RepaintAll();
}
}
不幸的是,我无法弄清楚如何存储一个二维数组(map[])的boolean,所以他在重启Unity时仍然存在。所有我来它是为了对文件进行序列化并在启动应用程序时查找文件。 (数组可以很大 1000x20)也许你可以提出一个更好的主意?谢谢!请原谅我的英语。
问题实际上与数据类型无关,例如地图,在你的情况下。你可以试试ScriptableObject class,它不需要附加到一些游戏对象
从 ScriptableObject 派生一个 class 并将 [Serializable] 属性添加到 class
[Serializable]
class MyData: ScriptableObject
{
public bool[,] map;
void OnEnable() {
//... do something to initialise the map or reload the map
}
}
实例化对象保存数据
//in this case MyData contains your map data
var data = SciptableObject.CreateInstance(typeof(MyData));
保存到Unity数据库:
AssetDatabase.CreateAsset(data, "Assets/SomeFolder/abc.asset");
AssetDatabase.SaveAssets()
AssetDatabase.Refresh();
检查资产中是否已经有一些资产:
var data = AssetDatabase.LoadAssetAtPath("Assets/SomeFolder/abc.asset",
typeof(SomeData));
if(data != null) {
//Your own logic to consume the map or whatever data
}
这样,当 Unity 重新启动时,所有变量都将被保存,您可以在 class 上添加 [InitializeOnLoad] 属性以使其自动加载。并且unity里面可以看到abc.asset文件,使用自定义编辑器编辑地图也是小菜一碟。