8 hours Code/Asset
While not perfect this works as a functioning shield that creates a dynamic mesh. All you need is to place this onto a child empty object then place a material on it. Then modify it to the right size.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[ExecuteInEditMode]
[RequireComponent(typeof(MeshRenderer))]
public class CircleMesh : MonoBehaviour
{
public int elements = 60;
public float startAngle = 0f;
private float internalStartAngle = -1f;
public float endAngle = 360f;
private float internalEndAngle = -1f;
public float innerRadius = 50f;
private float savedInnerRadius = 50f;
public float circleWidth = 10f;
private float savedCircleWidth = 10f;
private float circleRadius = 360f;
public bool addCaps = false;
private Vector3[] allVertices = new Vector3[0];
private Vector2[] allUVs = new Vector2[0];
private int[] allTriangles = new int[0];
public Vector2 uv1 = new Vector2(0f, 0f);
public Vector2 uv2 = new Vector2(0f, 1f);
public Mesh mesh = null;
public bool createNewMeshInAwake = true;
public bool fullCircle = true;
private bool savedFullCircle = false;
public int count = 0;
private int savedCount = -1;
private bool busy = false;
void Awake()
{
if (createNewMeshInAwake)
{
MeshFilter mF = transform.GetComponent<MeshFilter>();
if (mF) mF.sharedMesh = null;
mesh = null;
RecalculateMesh();
}
}
void Update()
{
if (startAngle != internalStartAngle || endAngle != internalEndAngle || innerRadius != savedInnerRadius || circleWidth != savedCircleWidth || mesh == null)
{
RecalculateMesh(uv1, uv2, (mesh == null) ? true : false);
transform.rotation = Quaternion.Euler(90, 0, (endAngle / 2) - (circleRadius / elements /2));
}
}
public void ForceRefreshMesh()
{
StartCoroutine(ForceRefreshMeshNow());
}
IEnumerator ForceRefreshMeshNow()
{
while (busy) yield return null;
RecalculateMesh(uv1, uv2, true);
}
void RecalculateMesh()
{
RecalculateMesh(uv1, uv2, false);
}
void RecalculateMesh(Vector2 uvOne, Vector2 uvTwo, bool forceRefresh)
{
if (busy) return;
busy = true;
float degreeStep = 360f / elements;
internalStartAngle = startAngle;
internalEndAngle = endAngle;
if (internalEndAngle > 360f) internalEndAngle = 360f;
if (internalStartAngle < 0f) internalStartAngle = 0f;
if (internalStartAngle > 0f || internalEndAngle < 360f) fullCircle = false;
else fullCircle = true;
count = 0;
float deg = 0f;
for (int c = 0; c < elements; c++)
{
if (deg >= internalStartAngle && deg <= internalEndAngle) count++;
deg += degreeStep;
}
if (count < 2)
{
GetComponent<Renderer>().enabled = false;
busy = false;
return;
}
else GetComponent<Renderer>().enabled = true;
if (!forceRefresh && count == savedCount && fullCircle == savedFullCircle && innerRadius == savedInnerRadius && circleWidth == savedCircleWidth)
{
busy = false;
return;
}
savedCount = count;
savedFullCircle = fullCircle;
savedInnerRadius = innerRadius;
savedCircleWidth = circleWidth;
if (addCaps && !fullCircle) count += 2;
allVertices = new Vector3[count * 2];
allUVs = new Vector2[count * 2];
int numTris = count * 6;
if (!fullCircle) numTris -= 6;
allTriangles = new int[numTris];
if (addCaps && !fullCircle) count -= 2;
if (!gameObject.GetComponent("MeshFilter")) gameObject.AddComponent<MeshFilter>();
if (!gameObject.GetComponent("MeshRenderer")) gameObject.AddComponent<MeshRenderer>();
if (!mesh) mesh = GetComponent<MeshFilter>().sharedMesh;
if (!mesh)
{
mesh = new Mesh();
mesh.name = "Circle Mesh for " + gameObject.name;
GetComponent<MeshFilter>().sharedMesh = mesh;
}
mesh.Clear();
Quaternion quat = Quaternion.identity;
deg = 0f;
while (deg < internalStartAngle) deg += degreeStep;
for (int i = 0; i < count * 2; i += 2)
{
quat = Quaternion.AngleAxis(deg, -Vector3.forward);
allVertices[i] = quat * new Vector3(0f, innerRadius, 0f);
allVertices[i + 1] = quat * new Vector3(0f, innerRadius + circleWidth, 0f);
allUVs[i] = uvOne;
allUVs[i + 1] = uvTwo;
int nextDown = i + 2;
int nextUp = i + 3;
if (i + 2 >= count * 2)
{
nextUp = 1; nextDown = 0;
}
if (i + 2 >= count * 2 && !fullCircle) break;
allTriangles[(i * 3)] = i;
allTriangles[(i * 3) + 1] = i + 1;
allTriangles[(i * 3) + 2] = nextUp;
allTriangles[(i * 3) + 3] = i;
allTriangles[(i * 3) + 4] = nextUp;
allTriangles[(i * 3) + 5] = nextDown;
deg += degreeStep;
}
if (addCaps && !fullCircle)
{
float capAngleOffset = Mathf.Lerp(2f, 30f, circleWidth / innerRadius);
quat = Quaternion.AngleAxis(internalStartAngle - capAngleOffset, -Vector3.forward);
allVertices[count * 2] = quat * new Vector3(0f, innerRadius, 0f);
allVertices[count * 2 + 1] = quat * new Vector3(0f, innerRadius + circleWidth, 0f);
allUVs[count * 2] = uvOne + new Vector2(1f, 0f);
allUVs[count * 2 + 1] = uvTwo + new Vector2(1f, 0f);
allTriangles[(count * 2 * 3)] = count * 2;
allTriangles[(count * 2 * 3) + 1] = count * 2 + 1;
allTriangles[(count * 2 * 3) + 2] = 0;
allTriangles[(count * 2 * 3) + 3] = count * 2 + 1;
allTriangles[(count * 2 * 3) + 4] = 1;
allTriangles[(count * 2 * 3) + 5] = 0;
quat = Quaternion.AngleAxis(internalEndAngle + capAngleOffset, -Vector3.forward);
allVertices[count * 2 + 2] = quat * new Vector3(0f, innerRadius, 0f);
allVertices[count * 2 + 3] = quat * new Vector3(0f, innerRadius + circleWidth, 0f);
allUVs[count * 2 + 2] = uvOne + new Vector2(1f, 0f);
allUVs[count * 2 + 3] = uvTwo + new Vector2(1f, 0f);
allTriangles[(count * 2 * 3) - 6] = count * 2 - 2;
allTriangles[(count * 2 * 3) - 5] = count * 2 - 1;
allTriangles[(count * 2 * 3) - 4] = count * 2 + 3;
allTriangles[(count * 2 * 3) - 3] = count * 2 - 2;
allTriangles[(count * 2 * 3) - 2] = count * 2 + 3;
allTriangles[(count * 2 * 3) - 1] = count * 2 + 2;
}
mesh.vertices = allVertices;
mesh.uv = allUVs;
mesh.triangles = allTriangles;
mesh.bounds = new Bounds(Vector3.zero, new Vector3(innerRadius + circleWidth, 0.1f, innerRadius + circleWidth));
busy = false;
}
}
Thursday, 23 April 2015
Thursday, 2 April 2015
Unity 5: Create Mesh then Deform It
3 hours Code/Asset
Ok where to start, I have been busy following a tutorial and have come up with this, this code creates a cube then when you click on different vertices it makes the selected vertices go up or down in real time. I have been working on my commenting. It still needs more work.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class DeformableMesh : MonoBehaviour
{
public float pointDeformation = 0.01f;
Mesh mesh;
Material mat;
List<Vector3> Points;
List<Vector3> Verts;
List<int> Tris;
List<Vector2> UVs;
float size = 0.5f;
// Use to set up refernces between scripts Awake is called before Start.
// Is called after all objects are initialzed but before scripts are run.
void Awake ()
{
}
// Use this for initialization
void Start ()
{
Points = new List<Vector3>();
//Setting the poistions of the verts
Points.Add(new Vector3(-size, size,-size));
Points.Add(new Vector3( size, size,-size));
Points.Add(new Vector3( size,-size,-size));
Points.Add(new Vector3(-size,-size,-size));
Points.Add(new Vector3( size, size, size));
Points.Add(new Vector3(-size, size, size));
Points.Add(new Vector3(-size,-size, size));
Points.Add(new Vector3( size,-size, size));
Verts = new List<Vector3>();
Tris = new List<int>();
UVs = new List<Vector2>();
CreateMesh();
}
// Render update is called once per frame
void Update ()
{
// Controls to raise and lower points
// If its not working check the mesh collider mesh slot
if (Input.GetMouseButton(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit ))
{
RaisePoint(FindNearestPoint(hit.point));
Debug.Log(hit.point);
}
}
if (Input.GetMouseButton(1))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
LowerPoint(FindNearestPoint(hit.point));
}
}
}
// Pysics update is called once per 1/60 seconds
void FixedUpdate ()
{
}
private Vector3 FindNearestPoint(Vector3 point)
{
Vector3 NearestPoint = new Vector3();
float lastDistance = 99999999f;
for (int i = 0; i < Points.Count; i++)
{
float distance = GetDistance(point, Points[i]);
if (distance < lastDistance)
{
lastDistance = distance;
NearestPoint = Points[i];
}
}
return NearestPoint;
}
// Using math finding the distance between 2 points;
private float GetDistance(Vector3 start, Vector3 end)
{
return Mathf.Sqrt(Mathf.Pow((start.x - end.x), 2) + Mathf.Pow((start.y - end.y), 2) + Mathf.Pow((start.z - end.z), 2));
}
private void RaisePoint(Vector3 point)
{
int index = -1;
for (int i = 0; i < Points.Count; i++)
{
if (Points[i] == point)
{
index = i;
break;
}
}
if (index == -1)
{
Debug.LogError("Could not match points");
}
else
{
Vector3 newPoint = Points[index];
newPoint.y += pointDeformation;
Points[index] = newPoint;
UpdateMesh();
}
}
private void LowerPoint(Vector3 point)
{
int index = -1;
for (int i = 0; i < Points.Count; i++)
{
if (Points[i] == point)
{
index = i;
break;
}
}
if (index == -1)
{
Debug.LogError("Could not match points");
}
else
{
Vector3 newPoint = Points[index];
newPoint.y -= pointDeformation;
Points[index] = newPoint;
UpdateMesh();
}
}
private void CreateMesh()
{
// Adding the requite components to show a mesh
gameObject.AddComponent<MeshFilter>();
gameObject.AddComponent<MeshRenderer>();
gameObject.AddComponent<MeshCollider>();
mat = Resources.Load("Materials/Defualt") as Material;
if (mat == null)
{
Debug.LogError("Material not found");
return;
}
MeshFilter meshFilter = GetComponent<MeshFilter>();
if (meshFilter == null)
{
Debug.LogError("meshFilter not found");
return;
}
mesh = meshFilter.sharedMesh;
if (mesh == null)
{
meshFilter.mesh = new Mesh();
mesh = meshFilter.sharedMesh;
}
MeshCollider meshCollier = GetComponent<MeshCollider>();
if (meshCollier == null)
{
Debug.LogError("MeshCollider not found");
return;
}
mesh.Clear();
UpdateMesh();
}
private void UpdateMesh()
{
// Front Plane
Verts.Add(Points[0]); Verts.Add(Points[1]); Verts.Add(Points[2]); Verts.Add(Points[3]);
// Back Plane
Verts.Add(Points[4]); Verts.Add(Points[5]); Verts.Add(Points[6]); Verts.Add(Points[7]);
// Left Plane
Verts.Add(Points[5]); Verts.Add(Points[0]); Verts.Add(Points[3]); Verts.Add(Points[6]);
// Right Plane
Verts.Add(Points[1]); Verts.Add(Points[4]); Verts.Add(Points[7]); Verts.Add(Points[2]);
// Top Plane
Verts.Add(Points[5]); Verts.Add(Points[4]); Verts.Add(Points[1]); Verts.Add(Points[0]);
// Bottum Plane
Verts.Add(Points[3]); Verts.Add(Points[2]); Verts.Add(Points[7]); Verts.Add(Points[6]);
//Front Plane
Tris.Add(0); Tris.Add(1); Tris.Add(2);
Tris.Add(2); Tris.Add(3); Tris.Add(0);
//Back Plane
Tris.Add(4); Tris.Add(5); Tris.Add(6);
Tris.Add(6); Tris.Add(7); Tris.Add(4);
//Left Plane
Tris.Add(8); Tris.Add(9); Tris.Add(10);
Tris.Add(10); Tris.Add(11); Tris.Add(8);
//Right Plane
Tris.Add(12); Tris.Add(13); Tris.Add(14);
Tris.Add(14); Tris.Add(15); Tris.Add(12);
//Top Plane
Tris.Add(16); Tris.Add(17); Tris.Add(18);
Tris.Add(18); Tris.Add(19); Tris.Add(16);
//Bottum Plane
Tris.Add(20); Tris.Add(21); Tris.Add(22);
Tris.Add(22); Tris.Add(23); Tris.Add(20);
// Front Plane
UVs.Add(new Vector2(0, 1));
UVs.Add(new Vector2(1, 1));
UVs.Add(new Vector2(1, 0));
UVs.Add(new Vector2(0, 0));
// Back Plane
UVs.Add(new Vector2(0, 1));
UVs.Add(new Vector2(1, 1));
UVs.Add(new Vector2(1, 0));
UVs.Add(new Vector2(0, 0));
// Left Plane
UVs.Add(new Vector2(0, 1));
UVs.Add(new Vector2(1, 1));
UVs.Add(new Vector2(1, 0));
UVs.Add(new Vector2(0, 0));
// Right Plane
UVs.Add(new Vector2(0, 1));
UVs.Add(new Vector2(1, 1));
UVs.Add(new Vector2(1, 0));
UVs.Add(new Vector2(0, 0));
// Top Plane
UVs.Add(new Vector2(0, 1));
UVs.Add(new Vector2(1, 1));
UVs.Add(new Vector2(1, 0));
UVs.Add(new Vector2(0, 0));
// Bottum Plane
UVs.Add(new Vector2(0, 1));
UVs.Add(new Vector2(1, 1));
UVs.Add(new Vector2(1, 0));
UVs.Add(new Vector2(0, 0));
//Setting everything to arrays;
mesh.vertices = Verts.ToArray();
mesh.triangles = Tris.ToArray();
mesh.uv = UVs.ToArray();
//Clearing all the lists, so new ones can be created;
Verts.Clear();
Tris.Clear();
UVs.Clear();
//Telling unity to create the mesh with the above information
MeshCollider meshCollider = GetComponent<MeshCollider>();
mesh.RecalculateNormals();
mesh.RecalculateBounds();
RecalculateTangents(mesh);
meshCollider.sharedMesh = null; // need to set shared mesh to null before setting the mesh.
meshCollider.sharedMesh = mesh;
gameObject.GetComponent<Renderer>().material = mat; // To access the renderer you need to get the component
mesh.Optimize();
}
//Storing the data
private static void RecalculateTangents(Mesh mesh)
{
int[] triangles = mesh.triangles;
Vector3[] vertices = mesh.vertices;
Vector2[] uv = mesh.uv;
Vector3[] normals = mesh.normals;
int triangleCount = triangles.Length;
int vertexCount = vertices.Length;
Vector3[] tan1 = new Vector3[vertexCount];
Vector3[] tan2 = new Vector3[vertexCount];
Vector4[] tangents = new Vector4[vertexCount];
for (long a = 0; a < triangleCount; a += 3)
{
//Triangle Storage
long tris1 = triangles[a + 0];
long tris2 = triangles[a + 1];
long tris3 = triangles[a + 2];
//Vertices Storage
Vector3 verts1 = vertices[tris1];
Vector3 verts2 = vertices[tris2];
Vector3 verts3 = vertices[tris3];
//UV Storage
Vector2 w1 = uv[tris1];
Vector2 w2 = uv[tris2];
Vector2 w3 = uv[tris3];
//Verticies
float x1 = verts2.x - verts1.x;
float x2 = verts3.x - verts1.x;
float y1 = verts2.y - verts1.y;
float y2 = verts3.y - verts1.y;
float z1 = verts2.z - verts1.z;
float z2 = verts3.z - verts1.z;
//UVS
float s1 = w2.x - w1.x;
float s2 = w3.x - w1.x;
float t1 = w2.y - w1.y;
float t2 = w3.y - w1.y;
float div = s1 * t2 - s2 * t1;
float r = div == 0.0f ? 0.0f : 1.0f / div;
Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
Vector3 tdir = new Vector3((s2 * x2 - s1 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
tan1[tris1] += sdir;
tan1[tris2] += sdir;
tan1[tris3] += sdir;
tan2[tris1] += tdir;
tan2[tris2] += tdir;
tan2[tris3] += tdir;
}
for (long a = 0; a < vertexCount; ++a)
{
Vector3 n = normals[a];
Vector3 t = tan1[a];
Vector3.OrthoNormalize(ref n, ref t);
tangents[a].x = t.x;
tangents[a].x = t.y;
tangents[a].x = t.z;
tangents[a].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
}
mesh.tangents = tangents;
}
}
Ok where to start, I have been busy following a tutorial and have come up with this, this code creates a cube then when you click on different vertices it makes the selected vertices go up or down in real time. I have been working on my commenting. It still needs more work.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class DeformableMesh : MonoBehaviour
{
public float pointDeformation = 0.01f;
Mesh mesh;
Material mat;
List<Vector3> Points;
List<Vector3> Verts;
List<int> Tris;
List<Vector2> UVs;
float size = 0.5f;
// Use to set up refernces between scripts Awake is called before Start.
// Is called after all objects are initialzed but before scripts are run.
void Awake ()
{
}
// Use this for initialization
void Start ()
{
Points = new List<Vector3>();
//Setting the poistions of the verts
Points.Add(new Vector3(-size, size,-size));
Points.Add(new Vector3( size, size,-size));
Points.Add(new Vector3( size,-size,-size));
Points.Add(new Vector3(-size,-size,-size));
Points.Add(new Vector3( size, size, size));
Points.Add(new Vector3(-size, size, size));
Points.Add(new Vector3(-size,-size, size));
Points.Add(new Vector3( size,-size, size));
Verts = new List<Vector3>();
Tris = new List<int>();
UVs = new List<Vector2>();
CreateMesh();
}
// Render update is called once per frame
void Update ()
{
// Controls to raise and lower points
// If its not working check the mesh collider mesh slot
if (Input.GetMouseButton(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit ))
{
RaisePoint(FindNearestPoint(hit.point));
Debug.Log(hit.point);
}
}
if (Input.GetMouseButton(1))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
LowerPoint(FindNearestPoint(hit.point));
}
}
}
// Pysics update is called once per 1/60 seconds
void FixedUpdate ()
{
}
private Vector3 FindNearestPoint(Vector3 point)
{
Vector3 NearestPoint = new Vector3();
float lastDistance = 99999999f;
for (int i = 0; i < Points.Count; i++)
{
float distance = GetDistance(point, Points[i]);
if (distance < lastDistance)
{
lastDistance = distance;
NearestPoint = Points[i];
}
}
return NearestPoint;
}
// Using math finding the distance between 2 points;
private float GetDistance(Vector3 start, Vector3 end)
{
return Mathf.Sqrt(Mathf.Pow((start.x - end.x), 2) + Mathf.Pow((start.y - end.y), 2) + Mathf.Pow((start.z - end.z), 2));
}
private void RaisePoint(Vector3 point)
{
int index = -1;
for (int i = 0; i < Points.Count; i++)
{
if (Points[i] == point)
{
index = i;
break;
}
}
if (index == -1)
{
Debug.LogError("Could not match points");
}
else
{
Vector3 newPoint = Points[index];
newPoint.y += pointDeformation;
Points[index] = newPoint;
UpdateMesh();
}
}
private void LowerPoint(Vector3 point)
{
int index = -1;
for (int i = 0; i < Points.Count; i++)
{
if (Points[i] == point)
{
index = i;
break;
}
}
if (index == -1)
{
Debug.LogError("Could not match points");
}
else
{
Vector3 newPoint = Points[index];
newPoint.y -= pointDeformation;
Points[index] = newPoint;
UpdateMesh();
}
}
private void CreateMesh()
{
// Adding the requite components to show a mesh
gameObject.AddComponent<MeshFilter>();
gameObject.AddComponent<MeshRenderer>();
gameObject.AddComponent<MeshCollider>();
mat = Resources.Load("Materials/Defualt") as Material;
if (mat == null)
{
Debug.LogError("Material not found");
return;
}
MeshFilter meshFilter = GetComponent<MeshFilter>();
if (meshFilter == null)
{
Debug.LogError("meshFilter not found");
return;
}
mesh = meshFilter.sharedMesh;
if (mesh == null)
{
meshFilter.mesh = new Mesh();
mesh = meshFilter.sharedMesh;
}
MeshCollider meshCollier = GetComponent<MeshCollider>();
if (meshCollier == null)
{
Debug.LogError("MeshCollider not found");
return;
}
mesh.Clear();
UpdateMesh();
}
private void UpdateMesh()
{
// Front Plane
Verts.Add(Points[0]); Verts.Add(Points[1]); Verts.Add(Points[2]); Verts.Add(Points[3]);
// Back Plane
Verts.Add(Points[4]); Verts.Add(Points[5]); Verts.Add(Points[6]); Verts.Add(Points[7]);
// Left Plane
Verts.Add(Points[5]); Verts.Add(Points[0]); Verts.Add(Points[3]); Verts.Add(Points[6]);
// Right Plane
Verts.Add(Points[1]); Verts.Add(Points[4]); Verts.Add(Points[7]); Verts.Add(Points[2]);
// Top Plane
Verts.Add(Points[5]); Verts.Add(Points[4]); Verts.Add(Points[1]); Verts.Add(Points[0]);
// Bottum Plane
Verts.Add(Points[3]); Verts.Add(Points[2]); Verts.Add(Points[7]); Verts.Add(Points[6]);
//Front Plane
Tris.Add(0); Tris.Add(1); Tris.Add(2);
Tris.Add(2); Tris.Add(3); Tris.Add(0);
//Back Plane
Tris.Add(4); Tris.Add(5); Tris.Add(6);
Tris.Add(6); Tris.Add(7); Tris.Add(4);
//Left Plane
Tris.Add(8); Tris.Add(9); Tris.Add(10);
Tris.Add(10); Tris.Add(11); Tris.Add(8);
//Right Plane
Tris.Add(12); Tris.Add(13); Tris.Add(14);
Tris.Add(14); Tris.Add(15); Tris.Add(12);
//Top Plane
Tris.Add(16); Tris.Add(17); Tris.Add(18);
Tris.Add(18); Tris.Add(19); Tris.Add(16);
//Bottum Plane
Tris.Add(20); Tris.Add(21); Tris.Add(22);
Tris.Add(22); Tris.Add(23); Tris.Add(20);
// Front Plane
UVs.Add(new Vector2(0, 1));
UVs.Add(new Vector2(1, 1));
UVs.Add(new Vector2(1, 0));
UVs.Add(new Vector2(0, 0));
// Back Plane
UVs.Add(new Vector2(0, 1));
UVs.Add(new Vector2(1, 1));
UVs.Add(new Vector2(1, 0));
UVs.Add(new Vector2(0, 0));
// Left Plane
UVs.Add(new Vector2(0, 1));
UVs.Add(new Vector2(1, 1));
UVs.Add(new Vector2(1, 0));
UVs.Add(new Vector2(0, 0));
// Right Plane
UVs.Add(new Vector2(0, 1));
UVs.Add(new Vector2(1, 1));
UVs.Add(new Vector2(1, 0));
UVs.Add(new Vector2(0, 0));
// Top Plane
UVs.Add(new Vector2(0, 1));
UVs.Add(new Vector2(1, 1));
UVs.Add(new Vector2(1, 0));
UVs.Add(new Vector2(0, 0));
// Bottum Plane
UVs.Add(new Vector2(0, 1));
UVs.Add(new Vector2(1, 1));
UVs.Add(new Vector2(1, 0));
UVs.Add(new Vector2(0, 0));
//Setting everything to arrays;
mesh.vertices = Verts.ToArray();
mesh.triangles = Tris.ToArray();
mesh.uv = UVs.ToArray();
//Clearing all the lists, so new ones can be created;
Verts.Clear();
Tris.Clear();
UVs.Clear();
//Telling unity to create the mesh with the above information
MeshCollider meshCollider = GetComponent<MeshCollider>();
mesh.RecalculateNormals();
mesh.RecalculateBounds();
RecalculateTangents(mesh);
meshCollider.sharedMesh = null; // need to set shared mesh to null before setting the mesh.
meshCollider.sharedMesh = mesh;
gameObject.GetComponent<Renderer>().material = mat; // To access the renderer you need to get the component
mesh.Optimize();
}
//Storing the data
private static void RecalculateTangents(Mesh mesh)
{
int[] triangles = mesh.triangles;
Vector3[] vertices = mesh.vertices;
Vector2[] uv = mesh.uv;
Vector3[] normals = mesh.normals;
int triangleCount = triangles.Length;
int vertexCount = vertices.Length;
Vector3[] tan1 = new Vector3[vertexCount];
Vector3[] tan2 = new Vector3[vertexCount];
Vector4[] tangents = new Vector4[vertexCount];
for (long a = 0; a < triangleCount; a += 3)
{
//Triangle Storage
long tris1 = triangles[a + 0];
long tris2 = triangles[a + 1];
long tris3 = triangles[a + 2];
//Vertices Storage
Vector3 verts1 = vertices[tris1];
Vector3 verts2 = vertices[tris2];
Vector3 verts3 = vertices[tris3];
//UV Storage
Vector2 w1 = uv[tris1];
Vector2 w2 = uv[tris2];
Vector2 w3 = uv[tris3];
//Verticies
float x1 = verts2.x - verts1.x;
float x2 = verts3.x - verts1.x;
float y1 = verts2.y - verts1.y;
float y2 = verts3.y - verts1.y;
float z1 = verts2.z - verts1.z;
float z2 = verts3.z - verts1.z;
//UVS
float s1 = w2.x - w1.x;
float s2 = w3.x - w1.x;
float t1 = w2.y - w1.y;
float t2 = w3.y - w1.y;
float div = s1 * t2 - s2 * t1;
float r = div == 0.0f ? 0.0f : 1.0f / div;
Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
Vector3 tdir = new Vector3((s2 * x2 - s1 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
tan1[tris1] += sdir;
tan1[tris2] += sdir;
tan1[tris3] += sdir;
tan2[tris1] += tdir;
tan2[tris2] += tdir;
tan2[tris3] += tdir;
}
for (long a = 0; a < vertexCount; ++a)
{
Vector3 n = normals[a];
Vector3 t = tan1[a];
Vector3.OrthoNormalize(ref n, ref t);
tangents[a].x = t.x;
tangents[a].x = t.y;
tangents[a].x = t.z;
tangents[a].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
}
mesh.tangents = tangents;
}
}
Unity 5: Creating a Shield With Custom Polygons.
3 Hours Research
I have been looking at more ways to make a shield and the guys from Unity Answers gave me an option. http://answers.unity3d.com/questions/938443/how-do-you-create-a-custom-radial-object-or-partic.html Basicly Sunny is telling me to make my own meshes from scratch. Lucky for me I am a modeler first and know what most of what the API is telling me. Most of the research time I have put in that has led to many dead ends. I have been experimenting with this for several hours.
Creating my own meshs seems to be the answer. I will get back once I have a working prototype.
http://docs.unity3d.com/ScriptReference/Mesh.html
I have been looking at more ways to make a shield and the guys from Unity Answers gave me an option. http://answers.unity3d.com/questions/938443/how-do-you-create-a-custom-radial-object-or-partic.html Basicly Sunny is telling me to make my own meshes from scratch. Lucky for me I am a modeler first and know what most of what the API is telling me. Most of the research time I have put in that has led to many dead ends. I have been experimenting with this for several hours.
Creating my own meshs seems to be the answer. I will get back once I have a working prototype.
http://docs.unity3d.com/ScriptReference/Mesh.html
Saturday, 28 March 2015
Unity 5: Patrol, Follow, Return
4 Hour Code/Assets
To be fair 1 hour of the above was me banging my head against the wall or the keyboard, I went for my cat but she ran away. The logic for this code is a mix of simple and fustrating. This could be looked at as rudimentry AI, as it is able to follow you and knows when to stop, it also will not venture to far from its home. I am planning on making each planet a "home base" but that can wait for later. I really need to work on my commenting more.
using UnityEngine;
using System.Collections;
public class EnemyShip : MonoBehaviour
{
public float SpeedMax = 10f;
public float SpeedMin = 7f;
public int rotationSpeed = 50;
public int followRange = 75;
public float chaseTime = 5;
public float patrolRaduis = 10;
public float maxPatrolDistance = 100;
public static float moveSpeed;
private Vector3 patrolRaduisV3;
private Transform playerShip; //the enemy's target var moveSpeed = 3; //move speed var rotationSpeed = 3; //speed of turning
private Transform myTransform; //current transform data of this enemy
private Vector3 myStartPosition;
private Vector3 myTarget = new Vector3(0,0,0);
private Vector3 direction = new Vector3(1, 0, 0);
private float startChaseTime;
enum EnemyState
{
Patrol,
Attack,
Chase,
Return
}
EnemyState enemyState;
void Awake()
{
myTransform = transform;//cache transform data for easy access/preformance
enemyState = EnemyState.Patrol;
}
void Start()
{
playerShip = GameObject.FindWithTag("Player").transform; //target the player
moveSpeed = Random.Range(SpeedMin, SpeedMax);
startChaseTime = chaseTime;
myStartPosition = myTransform.position;
myTarget = myTransform.position;
myTarget = new Vector3(myTarget.x, 0, myTarget.z);
}
void FixedUpdate()
{
switch (enemyState)
{
case EnemyState.Patrol:
Patrol();
if (Vector3.Distance(playerShip.transform.position, myTransform.position) < followRange)
{
enemyState = EnemyState.Attack;
}
if (Vector3.Distance(myStartPosition, myTransform.position) > maxPatrolDistance)
{
enemyState = EnemyState.Return;
}
break;
case EnemyState.Attack:
Follow();
if (Vector3.Distance(playerShip.transform.position, myTransform.position) > followRange)
{
enemyState = EnemyState.Chase;
}
break;
case EnemyState.Chase:
Follow();
chaseTime -= Time.deltaTime;
if (chaseTime <= 0)
{
enemyState = EnemyState.Return;
chaseTime = startChaseTime;
}
break;
case EnemyState.Return:
Return();
// Need to convert all the floats to Int other wise the physics engin will not be able to make float = float
if ((int)myTransform.position.x == (int)myStartPosition.x && (int)myTransform.position.z == (int)myStartPosition.z)
{
enemyState = EnemyState.Patrol;
}
break;
}
}
void Patrol()
{
if ((int)myTarget.x == (int)myTransform.position.x && (int)myTarget.z == (int)myTransform.position.z)
{
patrolRaduisV3 = Random.insideUnitSphere * patrolRaduis;
myTarget = patrolRaduisV3 + myTransform.position;
myTarget = new Vector3(myTarget.x, 0, myTarget.z);
}
else
{
myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(myTarget - myTransform.position), rotationSpeed * Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
}
void Follow()
{
myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(playerShip.position - myTransform.position), rotationSpeed * Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
void Return()
{
myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(myStartPosition - myTransform.position), rotationSpeed * Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
}
To be fair 1 hour of the above was me banging my head against the wall or the keyboard, I went for my cat but she ran away. The logic for this code is a mix of simple and fustrating. This could be looked at as rudimentry AI, as it is able to follow you and knows when to stop, it also will not venture to far from its home. I am planning on making each planet a "home base" but that can wait for later. I really need to work on my commenting more.
using UnityEngine;
using System.Collections;
public class EnemyShip : MonoBehaviour
{
public float SpeedMax = 10f;
public float SpeedMin = 7f;
public int rotationSpeed = 50;
public int followRange = 75;
public float chaseTime = 5;
public float patrolRaduis = 10;
public float maxPatrolDistance = 100;
public static float moveSpeed;
private Vector3 patrolRaduisV3;
private Transform playerShip; //the enemy's target var moveSpeed = 3; //move speed var rotationSpeed = 3; //speed of turning
private Transform myTransform; //current transform data of this enemy
private Vector3 myStartPosition;
private Vector3 myTarget = new Vector3(0,0,0);
private Vector3 direction = new Vector3(1, 0, 0);
private float startChaseTime;
enum EnemyState
{
Patrol,
Attack,
Chase,
Return
}
EnemyState enemyState;
void Awake()
{
myTransform = transform;//cache transform data for easy access/preformance
enemyState = EnemyState.Patrol;
}
void Start()
{
playerShip = GameObject.FindWithTag("Player").transform; //target the player
moveSpeed = Random.Range(SpeedMin, SpeedMax);
startChaseTime = chaseTime;
myStartPosition = myTransform.position;
myTarget = myTransform.position;
myTarget = new Vector3(myTarget.x, 0, myTarget.z);
}
void FixedUpdate()
{
switch (enemyState)
{
case EnemyState.Patrol:
Patrol();
if (Vector3.Distance(playerShip.transform.position, myTransform.position) < followRange)
{
enemyState = EnemyState.Attack;
}
if (Vector3.Distance(myStartPosition, myTransform.position) > maxPatrolDistance)
{
enemyState = EnemyState.Return;
}
break;
case EnemyState.Attack:
Follow();
if (Vector3.Distance(playerShip.transform.position, myTransform.position) > followRange)
{
enemyState = EnemyState.Chase;
}
break;
case EnemyState.Chase:
Follow();
chaseTime -= Time.deltaTime;
if (chaseTime <= 0)
{
enemyState = EnemyState.Return;
chaseTime = startChaseTime;
}
break;
case EnemyState.Return:
Return();
// Need to convert all the floats to Int other wise the physics engin will not be able to make float = float
if ((int)myTransform.position.x == (int)myStartPosition.x && (int)myTransform.position.z == (int)myStartPosition.z)
{
enemyState = EnemyState.Patrol;
}
break;
}
}
void Patrol()
{
if ((int)myTarget.x == (int)myTransform.position.x && (int)myTarget.z == (int)myTransform.position.z)
{
patrolRaduisV3 = Random.insideUnitSphere * patrolRaduis;
myTarget = patrolRaduisV3 + myTransform.position;
myTarget = new Vector3(myTarget.x, 0, myTarget.z);
}
else
{
myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(myTarget - myTransform.position), rotationSpeed * Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
}
void Follow()
{
myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(playerShip.position - myTransform.position), rotationSpeed * Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
void Return()
{
myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(myStartPosition - myTransform.position), rotationSpeed * Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
}
Unity 5: The Search for a Shield (ContactPoint)
3 Hours Research
Shields I have learned alot about .shaders and DirectX and OpenGL. In an attempt to make a shield I have learned the basics of shaderlab and CG, as well as other shader languages. Ultimately I the only thing I have really learned is that the old shaderlab codes do not work with unity 4.6/5.
http://wiki.unity3d.com/index.php/Shield
The goal of this was to take and modify this code. To modify you can then take Collisions, which have the method ContactPoint. This calculates the exact point of contact allowing for things to happen at the exact transform of a Collision; as well as the direction.
Example:
foreach (ContactPoint contact in collision.contacts)
{
Object theShip = Resources.Load(EnemiesToCreate[EnemyNumber].name);
enemyShip = (GameObject)Instantiate(theShip);
enemyShip.transform.position = contact.transform;
}
Shields I have learned alot about .shaders and DirectX and OpenGL. In an attempt to make a shield I have learned the basics of shaderlab and CG, as well as other shader languages. Ultimately I the only thing I have really learned is that the old shaderlab codes do not work with unity 4.6/5.
http://wiki.unity3d.com/index.php/Shield
The goal of this was to take and modify this code. To modify you can then take Collisions, which have the method ContactPoint. This calculates the exact point of contact allowing for things to happen at the exact transform of a Collision; as well as the direction.
Example:
foreach (ContactPoint contact in collision.contacts)
{
Object theShip = Resources.Load(EnemiesToCreate[EnemyNumber].name);
enemyShip = (GameObject)Instantiate(theShip);
enemyShip.transform.position = contact.transform;
}
Friday, 27 March 2015
Unity 5: Vector3.Distance
1 Hour Research.
I am trying to make it so enemies will spawn at MIN distance of 100 unites away from the player in any direction. I tried numerous while loops with many playerObject.transform.position + or - 100 bools in it to no avail. Then I found Vector3.Distance. The code I could use for this is:
float distance = Vector3.Distance(enemyShip.transform.position, playerObject.transform.position)
It calculates the total distance from the enemy ship to the player ship. But then I realized that there are nearly an infinite number of floats... So if I were to use:
while (distance < 100f)
{
enemyShip.transform.position = new Vector3(playerObject.transform.position.x + Random.Range(-125, 125), 0, playerObject.transform.position.z + Random.Range(-125, 125));
}
It would go through several million calculations before it found a distance that may be equal to greater than 100.
Back to the drawing board.
Edit****************************
1 Hour Code/Assets
I found a use for Vector3.Distance, when creating a new level this code will take a number of random game objects and spawn them, the if statement makes it so they will not spawn within 100 unity units of the player GameObject. In this case for random objects they all need to have the same names with different numbers, you cannot miss numbers else the code will break.
for (int c = 0; c < NumberOfPlanets; c++)
{
int randomPlanet = Random.Range(1,5);
Object planetClone = Resources.Load("Planet"+randomPlanet) as GameObject;
GameObject planet = (GameObject)Instantiate(planetClone);
planet.transform.position = new Vector3(Random.Range(-500, 500),0,Random.Range(-500, 500));
if ((float)Vector3.Distance(planet.transform.position,player.transform.position) < 100f )
{
planet.transform.position = new Vector3(Random.Range(-500, 500),0,Random.Range(-500, 500));
}
}
I am trying to make it so enemies will spawn at MIN distance of 100 unites away from the player in any direction. I tried numerous while loops with many playerObject.transform.position + or - 100 bools in it to no avail. Then I found Vector3.Distance. The code I could use for this is:
float distance = Vector3.Distance(enemyShip.transform.position, playerObject.transform.position)
It calculates the total distance from the enemy ship to the player ship. But then I realized that there are nearly an infinite number of floats... So if I were to use:
while (distance < 100f)
{
enemyShip.transform.position = new Vector3(playerObject.transform.position.x + Random.Range(-125, 125), 0, playerObject.transform.position.z + Random.Range(-125, 125));
}
It would go through several million calculations before it found a distance that may be equal to greater than 100.
Back to the drawing board.
Edit****************************
1 Hour Code/Assets
I found a use for Vector3.Distance, when creating a new level this code will take a number of random game objects and spawn them, the if statement makes it so they will not spawn within 100 unity units of the player GameObject. In this case for random objects they all need to have the same names with different numbers, you cannot miss numbers else the code will break.
for (int c = 0; c < NumberOfPlanets; c++)
{
int randomPlanet = Random.Range(1,5);
Object planetClone = Resources.Load("Planet"+randomPlanet) as GameObject;
GameObject planet = (GameObject)Instantiate(planetClone);
planet.transform.position = new Vector3(Random.Range(-500, 500),0,Random.Range(-500, 500));
if ((float)Vector3.Distance(planet.transform.position,player.transform.position) < 100f )
{
planet.transform.position = new Vector3(Random.Range(-500, 500),0,Random.Range(-500, 500));
}
}
Thursday, 26 March 2015
Unity 5: Follow the player
1 Hour Code/Assets
By applying this simple script to an enemy GameObject they will follow any tag named player. I have not created a system that allows for more then one player. This also allows for variable speed, for each GameObject but it is easy to remove.
public float SpeedMax = 10f;
public float SpeedMin = 7f;
public int rotationSpeed = 5;
public Vector3 direction = new Vector3(0,0,0);
public static float moveSpeed;
Transform target; //the enemy's target var moveSpeed = 3; //move speed var rotationSpeed = 3; //speed of turning
Transform myTransform; //current transform data of this enemy
void Awake()
{
myTransform = transform;//cache transform data for easy access/preformance
}
void Start()
{
target = GameObject.FindWithTag("Player").transform; //target the player
moveSpeed = Random.Range(SpeedMin, SpeedMax);
}
void Update ()
{
myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed*Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
By applying this simple script to an enemy GameObject they will follow any tag named player. I have not created a system that allows for more then one player. This also allows for variable speed, for each GameObject but it is easy to remove.
public float SpeedMax = 10f;
public float SpeedMin = 7f;
public int rotationSpeed = 5;
public Vector3 direction = new Vector3(0,0,0);
public static float moveSpeed;
Transform target; //the enemy's target var moveSpeed = 3; //move speed var rotationSpeed = 3; //speed of turning
Transform myTransform; //current transform data of this enemy
void Awake()
{
myTransform = transform;//cache transform data for easy access/preformance
}
void Start()
{
target = GameObject.FindWithTag("Player").transform; //target the player
moveSpeed = Random.Range(SpeedMin, SpeedMax);
}
void Update ()
{
myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed*Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
Subscribe to:
Posts (Atom)