Created
May 9, 2020 03:49
-
-
Save sknjpn/809fa028b80f5028f96a21e022744cd7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Linq; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using System; | |
public class FlagsManager : MonoBehaviour | |
{ | |
[SerializeField] int FieldSizeX = 50; | |
[SerializeField] int FieldSizeZ = 60; | |
[SerializeField] float TileSize = 2.0f; | |
[SerializeField] Function functionRed = null; | |
[SerializeField] Function functionBlue = null; | |
[SerializeField] Material material = null; | |
[SerializeField] Mesh landMesh = null; | |
private List<Flag> flags = null; | |
private Mesh mesh; | |
public List<Flag> Flags { get => flags; set => flags = value; } | |
public static FlagsManager Instance = null; | |
void Start() | |
{ | |
Instance = this; | |
// Flag登録 | |
flags = GetComponentsInChildren<Flag>().ToList(); | |
} | |
void OnValidate() | |
{ | |
Instance = this; | |
// Flag登録 | |
flags = GetComponentsInChildren<Flag>().ToList(); | |
UpdateMesh(); | |
} | |
private void UpdateMesh() | |
{ | |
mesh = new Mesh(); | |
// Mesh生成 | |
var vertices = new Vector3[(FieldSizeX + 1) * (FieldSizeZ + 1) + FieldSizeX * FieldSizeZ]; | |
// 四角形の頂点 | |
for (int x = 0; x <= FieldSizeX; ++x) | |
{ | |
for (int z = 0; z <= FieldSizeZ; ++z) | |
{ | |
var position = new Vector3(x - FieldSizeX / 2, 32, z - FieldSizeZ / 2) * TileSize; | |
// 座標修正 | |
RaycastHit hit_info; | |
if (Physics.Raycast(position, -Vector3.up, out hit_info, Mathf.Infinity, 1 << 8)) | |
position = hit_info.point + 0.1f * Vector3.up; | |
vertices[x + z * (FieldSizeX + 1)] = position; | |
} | |
} | |
// 四角形の中心 | |
for (int x = 0; x < FieldSizeX; ++x) | |
{ | |
for (int z = 0; z < FieldSizeZ; ++z) | |
{ | |
var position = new Vector3(0.5f + x - FieldSizeX / 2, 32, 0.5f + z - FieldSizeZ / 2) * TileSize; | |
// 座標修正 | |
RaycastHit hit_info; | |
if (Physics.Raycast(position, -Vector3.up, out hit_info, Mathf.Infinity, 1 << 8)) | |
position = new Vector3(hit_info.point.x, ((float)Math.Round(hit_info.point.y * 1.0f) / 1.0f), hit_info.point.z); | |
vertices[(FieldSizeX + 1) * (FieldSizeZ + 1) + x + z * FieldSizeX] = position; | |
} | |
} | |
var indexs = new List<int>[flags.Count]; | |
for (int i = 0; i < flags.Count; ++i) | |
indexs[i] = new List<int>(); | |
for (int x = 0; x < FieldSizeX; ++x) | |
{ | |
for (int z = 0; z < FieldSizeZ; ++z) | |
{ | |
int p0 = x + z * (FieldSizeX + 1); | |
int p1 = (x + 1) + z * (FieldSizeX + 1); | |
int p2 = (x + 1) + (z + 1) * (FieldSizeX + 1); | |
int p3 = x + (z + 1) * (FieldSizeX + 1); | |
int p4 = (FieldSizeX + 1) * (FieldSizeZ + 1) + x + z * FieldSizeX; | |
int n = (x + z * FieldSizeX) * 3 * 2; | |
// 座標修正 | |
RaycastHit hit_info; | |
bool cp0 = Physics.Raycast(vertices[p0] + Vector3.up, -Vector3.up, out hit_info, Mathf.Infinity, 1 << 11); | |
bool cp1 = Physics.Raycast(vertices[p1] + Vector3.up, -Vector3.up, out hit_info, Mathf.Infinity, 1 << 11); | |
bool cp2 = Physics.Raycast(vertices[p2] + Vector3.up, -Vector3.up, out hit_info, Mathf.Infinity, 1 << 11); | |
bool cp3 = Physics.Raycast(vertices[p3] + Vector3.up, -Vector3.up, out hit_info, Mathf.Infinity, 1 << 11); | |
bool cp4 = Physics.Raycast(vertices[p4] + Vector3.up, -Vector3.up, out hit_info, Mathf.Infinity, 1 << 11); | |
var flag = GetNearestFlag((vertices[p0] + vertices[p1] + vertices[p2] + vertices[p3]) / 4.0f); | |
// Flag | |
var flag1 = GetNearestFlag((vertices[p1] + vertices[p0] + vertices[p4]) / 3.0f); | |
var flag2 = GetNearestFlag((vertices[p2] + vertices[p1] + vertices[p4]) / 3.0f); | |
var flag3 = GetNearestFlag((vertices[p3] + vertices[p2] + vertices[p4]) / 3.0f); | |
var flag4 = GetNearestFlag((vertices[p0] + vertices[p3] + vertices[p4]) / 3.0f); | |
if (cp4 && cp1 && cp0) | |
{ | |
indexs[GetNumberOfFlag(flag)].Add(p1); | |
indexs[GetNumberOfFlag(flag)].Add(p0); | |
indexs[GetNumberOfFlag(flag)].Add(p4); | |
} | |
if (cp4 && cp2 && cp1) | |
{ | |
indexs[GetNumberOfFlag(flag)].Add(p2); | |
indexs[GetNumberOfFlag(flag)].Add(p1); | |
indexs[GetNumberOfFlag(flag)].Add(p4); | |
} | |
if (cp4 && cp3 && cp2) | |
{ | |
indexs[GetNumberOfFlag(flag)].Add(p3); | |
indexs[GetNumberOfFlag(flag)].Add(p2); | |
indexs[GetNumberOfFlag(flag)].Add(p4); | |
} | |
if (cp4 && cp0 && cp3) | |
{ | |
indexs[GetNumberOfFlag(flag)].Add(p0); | |
indexs[GetNumberOfFlag(flag)].Add(p3); | |
indexs[GetNumberOfFlag(flag)].Add(p4); | |
} | |
} | |
} | |
mesh.vertices = vertices; | |
mesh.colors = Enumerable.Repeat(Color.white, vertices.Length).ToArray(); | |
mesh.subMeshCount = flags.Count; | |
for (int i = 0; i < flags.Count; ++i) | |
mesh.SetTriangles(indexs[i], i); | |
mesh.RecalculateBounds(); | |
mesh.RecalculateNormals(); | |
GetComponent<MeshFilter>().mesh = mesh; | |
// Material割り当て | |
GetComponent<MeshRenderer>().materials = Enumerable.Repeat(material, flags.Count).ToArray(); | |
} | |
private void UpdateMaterials() | |
{ | |
for (int i = 0; i < flags.Count; ++i) | |
{ | |
if (flags[i].OccupationFunction == null) GetComponent<MeshRenderer>().materials[i].color = new Color(1.0f, 1.0f, 1.0f, 0.25f); | |
if (flags[i].OccupationFunction == functionRed) GetComponent<MeshRenderer>().materials[i].color = new Color(1.0f, 0.0f, 0.0f, 0.5f); | |
if (flags[i].OccupationFunction == functionBlue) GetComponent<MeshRenderer>().materials[i].color = new Color(0.0f, 0.0f, 1.0f, 0.5f); | |
} | |
} | |
void Update() | |
{ | |
UpdateMaterials(); | |
} | |
private int GetNumberOfFlag(Flag flag) | |
{ | |
for (int i = 0; i < flags.Count; ++i) | |
if (flag == flags[i]) return i; | |
// おかしい | |
return -1; | |
} | |
public float GetDistanceToFlagFrom(Vector3 position) | |
{ | |
return flags.Min(f => (f.transform.position - position).magnitude); | |
} | |
public Flag GetNearestFlag(Vector3 position) | |
{ | |
position = new Vector3((int)position.x + 0.5f, 128.0f, (int)position.z + 0.5f); | |
RaycastHit hit_info; | |
if (Physics.Raycast(position, -Vector3.up, out hit_info, Mathf.Infinity, 1 << 8)) | |
position = hit_info.point; | |
return flags.OrderByDescending(f => (f.transform.position - position).magnitude).Last(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment