Box2D/Farseer 2D physics has a useful component which draws a simple representation of the physics world using primitives (lines, polygons, fills, colors). Here's an example:
What's the best way to accomplish this in Unity3D? Is there a simple way to render polygons with fill, lines, points, etc.? If so, I could implement the interface of DebugDraw with Unity's API, but I'm having trouble finding how to implement primitive rendering like this with Unity.
I understand it'll be in 3D space, but I'll just zero-out one axis and use it basically as 2D.
In case you mean actually a debug box just displayed in the SceneView not in the GameView you can use Gizmos.DrawWireCube
void OnDrawGizmos()
{
//store original gizmo color
var color = Gizmos.color;
// store original matrix
var matrix = Gizmos.matrix;
// set gizmo to local space
Gizmos.matrix = transform.localToWorldMatrix;
// Draw a yellow cube at the transform position
Gizmos.color = Color.yellow;
// here set the scale e.g. for a "almost" 2d box simply use a very small z value
Gizmos.DrawWireCube(transform.position, new Vector3(0.5f, 0.2f, 0.001f));
// restor matrix
Gizmos.matrix = matrix;
// restore color
Gizmos.color = color;
}
you can use OnDrawGizmosSelected to show the Gizmo only if the GameObject is selected
you could also extend this by getting the box size over the inspector
[SerializeField] private Vector3 _boxScale;
and using
Gizmos.DrawWireCube(transform.position, _boxScale);
Related
I am creating a 2D platformer type game, and it has non flat terrain. How do I make it so that my character's legs always smoothly transition from a flat surface to a slope surface?
For reference you can check out [Alto's Adventure] (http://altosadventure.com/) (mobile). In that, the skateboard snaps to the curvy terrain.
Feel free to ask for more details.
To make such a possibility, you have to send a ray to the ground and then set the direction of up transform according to the Normal vector point of impact. The following code solves the basic problem.
public LayerMask groundLayer;
public float maxRayLength = 3;
public float offset = .5f; // set it to half of your character height
public void Update()
{
var ground = Physics2D.Raycast(transform.position, -transform.up, maxRayLength, groundLayer.value);
if (ground)
{
transform.up = ground.normal;
transform.position = new Vector3(ground.point.x, ground.point.y) + transform.up*offset;
}
}
In addition to the script, you must specify a suitable 2D collider as well as its layer. For layers, make sure that both the script inspector and the layer are set to the hypothetical ground layer.
Example Result:
We recieve a psd files from our designers for objects. We are working on an isometric 2.5D game, sprites are half-3D renders. We got 2 layers on PSD files, one is for ground (we use that as obstacle with polygon 2d collider) and other layer is building/object. For accurate sprite render order we have to put pivot point of the building/object to ground-level. When we did import PSD to Unity, the pivot points of layers are automaticly at the center of image. We need to set pivot point of sprite to ground level same as ground-layer's pivot.
Is there anyway to achieve this? Looks like "Sprite.pivot" is read-only can't changable via script.
You could create a new Sprite from the existing one and alter the pivot point using Sprite.Create
public Sprite CreateSpriteWithPivot(Sprite existingSprite, Vector2 pivot)
{
return Sprite.Create(existingSprite.texture, existingSprite.rect, pivot);
}
I made a tool for setting the Sprite pivot points in the editor while maintaining their world positions: https://github.com/thepowerprocess/UnitySpritePivotEditor
This is the part where the sprite texture is edited:
SpriteRenderer sr = selectedGameObject.GetComponent<SpriteRenderer>();
string path = AssetDatabase.GetAssetPath(sr.sprite.texture);
TextureImporter ti = (TextureImporter)AssetImporter.GetAtPath(path);
Vector2 newPivot = new Vector2(childMousePos.x / (sr.sprite.texture.width / sr.sprite.pixelsPerUnit), childMousePos.y / (sr.sprite.texture.height / sr.sprite.pixelsPerUnit)) + ti.spritePivot;
ti.spritePivot = newPivot;
TextureImporterSettings texSettings = new TextureImporterSettings();
ti.ReadTextureSettings(texSettings);
texSettings.spriteAlignment = (int)SpriteAlignment.Custom;
ti.SetTextureSettings(texSettings);
ti.SaveAndReimport();
IMAGE
Is there any way to snap UI sprite vertex? Holding "V" does not work in this case.
Checking Unity's Documentation is good start when you run into an issue. I checked the documentation, which can be found here: Modifying Sprite Vertices via Script.
Reading the documentation you can grab a Sprites Vertices using a Vector2 Array.
//Fetch the Sprite and vertices from the SpriteRenderer
Sprite sprite = m_SpriteRenderer.sprite;
Vector2[] spriteVertices = sprite.vertices;
You can draw using the vertices by following this and viewing them in scene view
// Show the sprite triangles
void DrawDebug()
{
Sprite sprite = m_SpriteRenderer.sprite;
ushort[] triangles = sprite.triangles;
Vector2[] vertices = sprite.vertices;
int a, b, c;
// draw the triangles using grabbed vertices
for (int i = 0; i < triangles.Length; i = i + 3)
{
a = triangles[i];
b = triangles[i + 1];
c = triangles[i + 2];
//To see these you must view the game in the Scene tab while in Play mode
Debug.DrawLine(vertices[a], vertices[b], Color.red, 100.0f);
Debug.DrawLine(vertices[b], vertices[c], Color.red, 100.0f);
Debug.DrawLine(vertices[c], vertices[a], Color.red, 100.0f);
}
}
Snapping the vertices together through the use of scripting, however, does seem overly complicated depending on what these are for. Given this, it would be useful to know why you want to do this? If these sprites are static and unmoving or only used for a short period it may be much easier to manually align them in the Scene view.
Another method could be to use ProGrid, which is a Unity Package that allows you to turn on snapping in your scene and is very useful for aligning gameobjects; this also allows the amount of snapping to be changed.
Find it by going to Window -> Package Manager. Note that you may need to turn on preview packages to find it.
I'm trying to detect contours in a scene and add a collider to every detected object, I used the canny edge detector to get the coordinates of the detected objects.
Here is my output image
I need to add a collider to each black line to prevent my game object from going in/out of that area but I don't know how to do so exactly.
The findContours function returns a list of detected contours each stored as a vector of points but how do I use that to generate a collider?
Thank you for your help.
Update
Here is my source code (for the update method)
void Update ()
{
if (initDone && webCamTexture.isPlaying && webCamTexture.didUpdateThisFrame) {
//convert webcamtexture to mat
Utils.webCamTextureToMat (webCamTexture, rgbaMat, colors);
//convert to grayscale
Imgproc.cvtColor (rgbaMat, grayMat, Imgproc.COLOR_RGBA2GRAY);
//Blurring
Imgproc.GaussianBlur(rgbaMat,blurMat,new Size(7,7),0);
Imgproc.Canny(blurMat, cannyMat, 50,100);
Mat inverted = ~cannyMat;
//convert back to webcam texture
Utils.matToTexture2D(inverted, texture, colors);
Mat hierarchy = new Mat();
List<MatOfPoint> contours = new List<MatOfPoint>();
Imgproc.findContours(inverted, contours, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
}
}
Use a PolygonCollider2d.
You can edit the collider at runtime using the SetPath function, to which you will pass a list of 2d points (that you already computed using the findContours function.
You can have several paths in the polygon if you want your collider to have holes.
My game generates a flat surface (the floor of a building). It's a flat poligon mesh as shown in the picture:
The poligon is generated procedurally and will be different each time.
I need to map UV coordinates so that a standard square texture of, say,a floor made of bricks, is properly displayed.
What is the best way to assing the correct UV coordinates to each vertex?
With an irregular shape, you might want to "paste" a texture across the mesh(imagine pasting a rectangular sticker across your mesh and cutting away those that fall outside your mesh shape).
For that type of mapping, you might want to use Mesh.bounds, which gives you the bounding box of your mesh in local coordinates, which is the area you are going to "paste" your texture over.
Mesh mesh = GetComponent<MeshFilter>();
Bounds bounds = mesh.bounds;
Get the vertices of your mesh:
Vector3[] vertices = mesh.vertices;
Now do the mapping:
Vector2[] uvs = new Vector2[vertices.Length];
for(int i = 0; i < vertices.Length; i++)
{
uvs[i] = new Vector2(vertices[i].x / bounds.size.x, vertices[i].z / bounds.size.z);
}
mesh.uv = uvs;