TG9six 03a642d635 first push
first push
2025-09-06 17:17:39 +04:00

402 lines
14 KiB
C#

#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(World))]
public class WorldEditor : Editor
{
public override void OnInspectorGUI()
{
GUILayout.Label("Server file for a* pathfinding");
if (GUILayout.Button("Generate .mapdata"))
{
GenerateAStarMapData(World.WORLD_SIZE_X, World.WORLD_SIZE_Y);
}
GUILayout.Label("Server file for height data");
if (GUILayout.Button("Generate .heightmap"))
{
generateHeightMap();
}
//if (GUILayout.Button("Generate Object Data"))
//{
// generateObjectData();
//}
//if (GUILayout.Button("Turn All Box Colliders into Mesh Colliders"))
//{
// turnAllBoxCollidersIntoMesh();
//}
}
public void generateHeightMap()
{
int[] heightData = new int[World.WORLD_SIZE_X * World.WORLD_SIZE_Y];
for (int i = 0; i < World.WORLD_SIZE_Y; i++)
{
for (int j = 0; j < World.WORLD_SIZE_X; j++)
{
Vector3 position = new Vector3(j, 0.0f, i);
Terrain t = Misc.GetClosestCurrentTerrain(position);
float height = t.SampleHeight(position);
heightData[i * World.WORLD_SIZE_X + j] = (int)(height * 100);
}
}
using (FileStream fileStream = new FileStream("output/.heightmap", FileMode.Create)) // destiny file directory.
{
using (BinaryWriter binaryWriter = new BinaryWriter(fileStream))
{
byte[] mapWidth = convInt(World.WORLD_SIZE_X);
for (int i = 0; i < 4; i++)
{
fileStream.WriteByte(mapWidth[i]);
}
byte[] mapHeight = convInt(World.WORLD_SIZE_Y);
for (int i = 0; i < 4; i++)
{
fileStream.WriteByte(mapHeight[i]);
}
for (int i = 0; i < heightData.Length; i++)
{
byte[] value = convInt((int)(heightData[i]));
for (int j = 0; j < 4; j++)
{
fileStream.WriteByte(value[j]);
}
}
fileStream.Close();
}
//now write the data file
//write world collision map to a png file
Texture2D texture = new Texture2D(World.WORLD_SIZE_X, World.WORLD_SIZE_Y, TextureFormat.RGB24, false); // create texture2D to store the map in, written to file at the end of the method
// set all pixels to black
for (int i = 0; i < World.WORLD_SIZE_Y; i++)
{
for (int j = 0; j < World.WORLD_SIZE_X; j++)
{
float f = (float)heightData[i * World.WORLD_SIZE_X + j];
Color c = new Color(f / 1000.0f, 0.0f, 0.0f);
texture.SetPixel(j, i, c);
}
}
texture.Apply();
byte[] fileData = texture.EncodeToPNG();
System.IO.File.WriteAllBytes("output/heightmap.png", fileData);
}
}
public void GenerateAStarMapData(int width, int height)
{
Debug.ClearDeveloperConsole();
Debug.Log("Generating A* Path Data...");
RaycastHit[] hits = new RaycastHit[5];
FileStream fileStream = new FileStream("output/.astar", FileMode.Create);
byte[] mapWidth = convInt(width);
for (int i = 0; i < 4; i++) { fileStream.WriteByte(mapWidth[i]); }
byte[] mapHeight = convInt(height);
for (int i = 0; i < 4; i++) { fileStream.WriteByte(mapHeight[i]); }
for (int z = 0; z < height; z++)
{
for (int x = 0; x < width; x++)
{
bool collision = false;
Terrain terrain = Misc.GetClosestCurrentTerrain(new Vector3(x, 0, z));
float terrainHeight = terrain.SampleHeight(new Vector3(x, 0, z)) - 0.1f;
float startingHeight = terrainHeight + 5.1f;
float distance = Mathf.Abs(startingHeight - terrainHeight);
Vector3 rayOrigin = new Vector3(x + 0.5f, startingHeight, z + 0.5f);
Ray ray = new Ray(rayOrigin, Vector3.down);
int ignoredLayers = LayerMask.GetMask("Ignore Raycast", "Water", "BlockPlayer");
int hitCount = Physics.SphereCastNonAlloc(ray.origin, .5f, ray.direction, hits, distance, ~ignoredLayers);
if (hitCount > 0)
{
bool isClosestHitWithObject = false;
float closestDistance = float.PositiveInfinity;
for (int i = 0; i < hitCount; i++)
{
if (hits[i].distance < closestDistance)
{
isClosestHitWithObject = !hits[i].collider.TryGetComponent(out Terrain _);
closestDistance = hits[i].distance;
}
}
collision = isClosestHitWithObject;
}
byte[] value = convInt(collision ? 1 : 0);
for (int j = 0; j < 4; j++)
{
fileStream.WriteByte(value[j]);
}
}
}
fileStream.Close();
Debug.Log("Task complete.");
}
//We don't need this anymore. -Thomas09- I've made a system
private void turnAllBoxCollidersIntoMesh()
{
Debug.ClearDeveloperConsole();
Debug.Log("Converting All Box Colliders into Mesh Colliders");
var gameObjectsWithBoxColliders = FindObjectsOfType<BoxCollider>();
for (int i = 0; i < gameObjectsWithBoxColliders.Length; i++)
{
var go = gameObjectsWithBoxColliders[i].gameObject;
var meshCollider = go.GetComponent<MeshCollider>();
//If an existing MeshCollider exists, just Destroy it
if (go.GetComponent<MeshCollider>() != null)
{
DestroyImmediate(meshCollider);
}
meshCollider = go.AddComponent<MeshCollider>();
var meshfilter = go.GetComponent<MeshFilter>();
if (meshfilter != null)
{
meshCollider.sharedMesh = meshfilter.sharedMesh;
}
DestroyImmediate(go.GetComponent<BoxCollider>());
}
}
private void generateObjectData()
{
Debug.ClearDeveloperConsole();
Debug.Log("Generate Object Data...");
//Get All GameObjects in Scene with World Object Type
var initialArray_1 = FindObjectsOfType<WorldObject>();
//Filter WorldObject gameobjects that has MeshColliders;
List<GameObject> initialArray_2 = new List<GameObject>();
for (int i = 0; i < initialArray_1.Length; i++)
{
var go = initialArray_1[i];
if (go.GetComponent<MeshCollider>() != null)
{
initialArray_2.Add(go.gameObject);
}
}
//Get All GameObjects in initialArray_2 with MeshFilter Component
List<MeshAndTransform> meshAndTransform = new List<MeshAndTransform>();
for (int i = 0; i < initialArray_2.Count; i++)
{
var meshfilter = initialArray_2[i].GetComponent<MeshFilter>();
if (meshfilter != null)
{
meshAndTransform.Add(new MeshAndTransform
{
Mesh = meshfilter.sharedMesh,
Transform = meshfilter.transform
});
}
}
List<ObjectsAndTilesData> objectsAndTiles = new List<ObjectsAndTilesData>();
for (int i = 0; i < meshAndTransform.Count; i++)
{
List<Vector3> vertices = meshAndTransform[i].Mesh.vertices.ToList();
var transform = meshAndTransform[i].Transform;
HashSet<Vector2> overlapHashSet = new HashSet<Vector2>();
for (int j = 0; j < vertices.Count; j++)
{
var posV3 = transform.TransformPoint(vertices[j]);
var posX = posV3.x < 0 ? posV3.x - 1 : posV3.x;
var posY = posV3.z < 0 ? posV3.z - 1 : posV3.z;
overlapHashSet.Add(new Vector2((int)posX, (int)posY));
}
objectsAndTiles.Add(new ObjectsAndTilesData
{
GameObjectName = transform.gameObject.name,
OverlapHashSet = overlapHashSet
});
}
//Write it to file
using (FileStream fileStream = new FileStream("outputTileData.csv", FileMode.Create))
{
for (int i = 0; i < objectsAndTiles.Count; i++)
{
var name = objectsAndTiles[i].GameObjectName;
var overlaptiles = objectsAndTiles[i].OverlapHashSet.ToList();
var count = overlaptiles.Count;
string cov = name + ", " + count + ", ";
for (int j = 0; j < overlaptiles.Count; j++)
{
cov += overlaptiles[j].ToString();
if (j < overlaptiles.Count - 1)
{
cov += ", ";
}
}
if (i < objectsAndTiles.Count - 1)
{
cov += Environment.NewLine;
}
byte[] covByteArray = Encoding.Default.GetBytes(cov);
fileStream.Write(covByteArray, 0, covByteArray.Length);
}
fileStream.Close();
}
Debug.Log("Done! Check the root project folder! There should be a outputTileData.csv there!");
}
public byte[] convInt(int i)
{
byte[] b = new byte[4];
b[3] = (byte)i;
b[2] = (byte)(i >> 8);
b[1] = (byte)(i >> 16);
b[0] = (byte)(i >> 24);
return b;
}
public void generateNavigationHeightmap()
{
Debug.ClearDeveloperConsole();
Debug.Log("Generating Collision Maps.");
//find a reference to terrain for height checking
Terrain terrain = GameObject.Find("Terrain").GetComponent<Terrain>();
float[] navigationHeightData = new float[1024 * 1024];
//now loop through all tiles of the game
for (int i = 0; i < 1024; i++)
{
for (int j = 0; j < 1024; j++)
{
RaycastHit rch;
if (Physics.Raycast(new Vector3(j, terrain.SampleHeight(new Vector3(j, 0, i)) + 10.0f, i), new Vector3(0, -1.0f, 0), out rch, 20.0f))
{
navigationHeightData[i * 1024 + j] = rch.point.y;
}
}
}
//write world collision map to a png file
Texture2D texture = new Texture2D(1024, 1024, TextureFormat.RGB24, false); // create texture2D to store the map in, written to file at the end of the method
// set all pixels to black
for (int i = 0; i < 1024; i++)
{
for (int j = 0; j < 1024; j++)
{
Color c = Color.black;
c.r = navigationHeightData[i * 1024 + j] / 100.0f;
texture.SetPixel(j, i, c);
}
}
texture.Apply();
byte[] fileData = texture.EncodeToPNG();
System.IO.File.WriteAllBytes("NavigationHeightMap.png", fileData);
}
public void generateCollisionMap()
{
Debug.ClearDeveloperConsole();
Debug.Log("Generating Collision Maps.");
//find a reference to terrain for height checking
Terrain terrain;// = GameObject.Find("Terrain").GetComponent<Terrain>();
//create data for the map
bool[] collisionMapData = new bool[1024 * 1024];
for (int i = 0; i < collisionMapData.Length; i++) collisionMapData[i] = false;
//now loop through all tiles of the game
for (int i = 0; i < 1024; i++)
{
for (int j = 0; j < 1024; j++)
{
terrain = Misc.GetClosestCurrentTerrain(new Vector3(j, 0, i));
bool collision = false;
for (int y = 0; y < 10; y++)
{
for (int x = 0; x < 10; x++)
{
float rX = ((float)x / 10) + j + -0.5f;
float rZ = ((float)y / 10) + i + -0.5f;
float rY = terrain.SampleHeight(new Vector3(rX, 0, rZ)) - 0.05f;
Ray ray = new Ray(new Vector3(rX, rY, rZ), new Vector3(0, 1, 0));
RaycastHit rch;
if (Physics.Raycast(new Vector3(j, terrain.SampleHeight(new Vector3(j, 0, i)) + 10.0f, i), new Vector3(0, -1.0f, 0), out rch, 20.0f))
//if (Physics.Raycast(ray, 20.5f))
{
if (rch.collider.gameObject.GetComponent<WorldObject>() == null)
{
collision = true;
}
else if (rch.collider.gameObject.GetComponent<WorldObject>().canWalkOnTop == false)
{
collision = true;
}
}
}
}
if (collision)
{
collisionMapData[i * 1024 + j] = true;
Debug.Log("Collision x:" + j + " y: " + i);
}
}
}
//write world collision map to a png file
Texture2D texture = new Texture2D(1024, 1024, TextureFormat.RGB24, false); // create texture2D to store the map in, written to file at the end of the method
// set all pixels to black
for (int i = 0; i < 1024; i++)
{
for (int j = 0; j < 1024; j++)
{
Color c = Color.black;
if (collisionMapData[i * 1024 + j])
c = Color.red;
texture.SetPixel(j, i, c);
}
}
texture.Apply();
byte[] fileData = texture.EncodeToPNG();
System.IO.File.WriteAllBytes("collisionMap.png", fileData);
}
}
#endif