Skip to content

Instantly share code, notes, and snippets.

@sknjpn
Created May 9, 2020 03:49
Show Gist options
  • Save sknjpn/809fa028b80f5028f96a21e022744cd7 to your computer and use it in GitHub Desktop.
Save sknjpn/809fa028b80f5028f96a21e022744cd7 to your computer and use it in GitHub Desktop.
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