I want to draw lines grid in 3d Unity.
I found that i can draw lines using MeshTopology.Lines in Unity 4.
But I can not found example how do it with MeshTopology.Lines.
How draw lines in Unity 3d?
Vector3[] verts = new Vector3[]{Vector3.up, Vector3.right, Vector3.down, Vector3.left};
int[] indicesForLineStrip = new int[]{0,1,2,3,0};
//int[] indicesForLines = new int[]{0,1,1,2,2,3,3,0};
Mesh mesh = new Mesh();
mesh.vertices = verts;
mesh.SetIndicies(indicesForLineStrip, MeshTopology.LineStrip, 0);
//mesh.SetIndicies(indicesForLines, MeshTopology.Lines, 0);
mesh.RecalculateNormals();
mesh.RecalculateBounds();
Another recommendation -
Initialize a mesh, triangles, vertices, etc. etc. What worked for me was to then do the following (where meshMaterials is an array of materials, material 0 -> submesh 0, and material 1 -> submesh 1):
mesh.subMeshCount = 2;
GetComponent<MeshRenderer>().materials = meshMaterials;
mesh.SetIndices(triangles, MeshTopology.Lines, 1);
Useful discussion How to Render/Draw mesh lines OVER texture at runtime/play mode
Related
I am making a game with Unity, the project model is 2D.
What I have to do is a wheel divided into segments, each segment is an individual object, this wheel turns on itself with a certain speed, here is an imamgine for better understanding:
I have a "Selector", i.e. something to select a slice, so I made a temporary sprite, i.e. the red triangle, and a script to generate a Ray Cast to locate the selected slice, some images to better understand:
So far so good, my problem lies in the fact that the mesh of the slices is also the mesh of the collider, which is not convex but concave, so from what I've read on the Internet Unity does not allow to intercept objects with concave mesh by the Ray Cast due to calculation problems, so I can not intercept the slices, the only way to hit them is to tick the parameter "Convex"
of the Collider component, but I create a collider with a square shape, and so the selection precision is lacking, here are some pictures to better understand:
So I looked on the internet for a solution and found that the solution was to split the collider into several smaller but convex colliders, so I tried this, i.e. for each pair, i.e. 2 triangles, I created a collider that had a mesh made from the two triangles in question, so I got this:
But it is still not intercepted by RayCast, unless I tick the "Convex" parameter of the collider component, but even then a collider with a square shape is created.
Finally, here are some parts of the code within the post:
Code for generating ray cast:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Selector : MonoBehaviour
{
public GameObject objPosRef;
void Update()
{
if (Input.GetMouseButtonUp(1))
{
RaycastHit hit;
Debug.DrawRay(objPosRef.transform.position, new Vector3(0, 0.5f, 0), Color.green, 0.5f);
if (Physics.Raycast(objPosRef.transform.position, new Vector3(0, 0.5f, 0), out hit))
{
Debug.Log("Colpito: " + hit.collider.name);
}
}
}
}
Code to update the segment mesh:
...
private void UpdateMesh()
{
mesh.Clear();
mesh.vertices = vertex;
mesh.triangles = triangles;
createColldiers();
mesh.RecalculateNormals();
mesh.RecalculateBounds();
GetComponent<MeshRenderer>().material = new Material(material);
GetComponent<MeshRenderer>().material.color = color;
}
Code for creating segment colliders:
private void createColldiers()
{
int numColliders = (numVertex * 2 - 2) / 2;
for (int i = 0; i < numColliders; i++)
{
MeshCollider collider = gameObject.AddComponent<MeshCollider>();
Mesh mesh = new Mesh();
int[] tr = new int[6];
int k = 6 * i;
for (int j = 0; j < 6; j++)
{
tr[j] = triangles[k];
k++;
}
mesh.vertices = vertex;
mesh.triangles = tr;
collider.sharedMesh = mesh;
}
}
In summary I create a new mesh, the vertices of this mesh are identical to those of the segment mesh, although the new mesh does not need all the vertices, the triangles of the new mesh are only 2, and are taken in pairs from the triangle array of the segment mesh.
Sorry if my post is full of pictures, I hope I have been able to give you the best possible understanding of my problem, most likely the probelma will be something popping, thank you in advance for your help.
p.s: very few people say that raycasts can safely intercept objects with a concave collider, thus going against the grain of all other claims to the contrary, who is right?
I just started learning monogame a couple of days ago and I was wondering how I can draw a line from a Start Vector2 and an End Vector2 with a specific line thickness?
Should I use a one pixel image to draw it onto the screen and then use a Bresenham's line algorithm to find there positions, or is there a more optimized and less complicated method to do this using monogames built in functions?
One way is to create a Texture2D with a width that is the distance between the two Vector2s and a height that is the desired width. Then you apply a rotation to the texture when you draw it.
Here is an example (as a SpriteBatch extension method):
public static void DrawLineBetween(
this SpriteBatch spriteBatch,
Vector2 startPos,
Vector2 endPos,
int thickness,
Color color)
{
// Create a texture as wide as the distance between two points and as high as
// the desired thickness of the line.
var distance = (int)Vector2.Distance(startPos, endPos);
var texture = new Texture2D(spriteBatch.GraphicsDevice, distance, thickness);
// Fill texture with given color.
var data = new Color[distance * thickness];
for (int i = 0; i < data.Length; i++)
{
data[i] = color;
}
texture.SetData(data);
// Rotate about the beginning middle of the line.
var rotation = (float)Math.Atan2(endPos.Y - startPos.Y, endPos.X - startPos.X);
var origin = new Vector2(0, thickness / 2);
spriteBatch.Draw(
texture,
startPos,
null,
Color.White,
rotation,
origin,
1.0f,
SpriteEffects.None,
1.0f);
}
Example of use:
var startPos = new Vector2(0, 0);
var endPos = new Vector2(800, 480);
_spriteBatch.DrawLineBetween(startPos, endPos, 12, Color.White);
How it looks:
It's not a perfect solution. You'll want to modify it if you want to draw connected lines with different angles without any visible seams. Also not sure about the performance.
I use a library I found. It draws a number of 2D primitives, like lines, boxes, etc. Really easy to use. Called "C3.MonoGame.Primitives2D", it can be found here:
https://github.com/z2oh/C3.MonoGame.Primitives2D
Here's a screenshot of a demo I wrote using many of its methods:
It's just one file of around 500 lines. If you don't like Git or using libraries, you can just copy & paste it into your project.
I have build a custom pyramid in Unity like this:
Mesh mesh = GetComponent<MeshFilter>().mesh;
mesh.Clear();
Vector3[] vertices = {
new Vector3(0.0f, 0.5f, 0.0f),
new Vector3(0.5f, 0.0f, 0.5f),
new Vector3(-0.5f, 0.0f, 0.5f),
new Vector3(-0.5f, 0.0f, -0.5f),
new Vector3(0.5f, 0.0f, -0.5f),
};
int[] triangles = {
1, 2, 3,
1, 3, 4,
1, 0, 2,
2, 0, 3,
3, 0, 4,
4, 0, 1
};
mesh.vertices = vertices;
mesh.triangles = triangles;
I am trying to color my pyramid, as said in unity documentation like this:
Color[] colors = new Color[vertices.Length];
for (int i = 0; i < vertices.Length; i++)
colors[i] = Color.Lerp(Color.red, Color.green, vertices[i].y);
// assign the array of colors to the Mesh.
mesh.colors = colors;
but this wont change a thing..
i have no materials on my object, only this script.
Any ideas?
Note that comment in mesh.colors
// (Note that most built-in Shaders don't display vertex colors. Use one that does, such as a Particle Shader, to see vertex colors)
so in order to see those colors in the MeshRenderer component add a material that uses such a Vertex or Particle Shader.
Therefore
in the Project view (Assets) do right click → Create → Material
Give that material a name
For the Shader from the Dropdown menu find and select e.g. Particles → Standard Unlit (or if you want to receive lightning Standard Surface)
Finally use this material for your object either by dragging it into the MeshRenderer → material or by simply dragging it onto the according object in the Scene view (the latter might not work if there is no mesh for that object yet)
Result:
In addition to https://stackoverflow.com/a/55714190/617889:
When using Universal Render Pipeline you need to use other shaders:
Univeral Render Pipeline \ Particles \ Lit (with lightning)
Univeral Render Pipeline \ Particles \ Unlit (without lightning)
I am trying to create my whole mesh from 5 submeshes via script in Unity. For each submesh I've got a separated indice array and material assigned. Curiously Unity only renders the first submesh, but if I inspect the mesh assigned to the mesh filter it says that there are more vertices and triangle than actually are rendered.
GameObject go = new GameObject("Island Prototype");
Mesh mesh = new Mesh();
mesh.vertices = this.vertices.ToArray();
mesh.subMeshCount = this.indices.Count;
int c = 0;
foreach (List<int> l in this.indices)
{
Debug.Log(l.Count);
mesh.SetTriangles(l.ToArray(), c);
c++;
}
mesh.RecalculateNormals();
List<Material> materials = new List<Material>();
materials.Add(fieldMaterial);
foreach (TileSettings ts in tiles)
{
materials.Add(fieldMaterial);
}
Debug.Log("Number of materials: " + materials.Count);
//mesh.RecalculateBounds();
//mesh.RecalculateNormals();
MeshRenderer mr = go.AddComponent<MeshRenderer>();
mr.sharedMaterials = materials.ToArray();
MeshFilter mf = go.AddComponent<MeshFilter>();
mf.mesh = mesh;
At the screenshot you can see, that the mesh inspector says the correct count of submeshes. There are also 5 materials attached to the renderer.
At the console I've printed the count of vertices, so submesh 3-5 doesn't own triangles at the moment, but this shouldn't be a problem, should it? At least submesh 2 should be rendered...
I am trying out unity for a project that i am on.
I am attempting to draw 3D polygon from a set of coordinate that I have.
So what i am doing now is to build a row of cube btw the two points. I plan to build these points into either a solid shape or just "walls" to form a room.
However, it doesn't seem to work as expected. Please advise.
drawCube( Vector3(10,0,14),Vector3(70,0,14));
drawCube( Vector3(90,0,14),Vector3(60,87,45));
function drawCube(v1,v2) {
pA = v1;
pB = v2;
var plane : GameObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
var between:Vector3 = pB - pA;
var distance:float = between.magnitude;
plane.transform.localScale.x = distance;
plane.transform.localScale.y=10;
plane.transform.position = pA + (between / 2.0);
plane.transform.LookAt(pB);
}
updated: I have also tried using a mesh but all i got was the below image. What am i doing wrong?
I am trying to achieve something like this
You could make primitives and manipulate them but that would limit you very much if you needed to scale or change your requirements in the future. I would recommend using a procedural mesh to create the geometry you need as you need it. The basics aren't too hard, it's just a matter of constructing the Mesh object from it's base components given some vertices. Here's an example of constructing a 3d quadrilateral:
using UnityEngine;
using System.Collections.Generic;
public class SquareMaker : MonoBehaviour {
public List<Vector3> points;
void Start()
{
GameObject threeDSquare = new GameObject("3DSquare");
threeDSquare.AddComponent<MeshRenderer>();
threeDSquare.AddComponent<MeshFilter>();
threeDSquare.GetComponent<MeshFilter>().mesh = CreateMesh(points);
}
private Mesh CreateMesh(List<Vector3> points)
{
List<int> tris = new List<int>(); // Every 3 ints represents a triangle
List<Vector2> uvs = new List<Vector2>(); // Vertex position in 0-1 UV space
/* 4 points in the list for the square made of two triangles:
0 *--* 1
| /|
|/ |
3 *--* 2
*/
tris.Add(1);
tris.Add(2);
tris.Add(3);
tris.Add(3);
tris.Add(0);
tris.Add(1);
// uvs determine vert (point) coordinates in uv space
uvs.Add(new Vector2(0f, 1f));
uvs.Add(new Vector2(1f, 1f));
uvs.Add(new Vector2(1f, 0f));
uvs.Add(new Vector2(0f, 0f));
Mesh mesh = new Mesh();
mesh.vertices = points.ToArray();
mesh.uv = uvs.ToArray();
mesh.triangles = tris.ToArray();
mesh.RecalculateNormals();
return mesh;
}
}