Is there anyway to set pivot of sprite with script? - unity3d

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();

Related

How do I make my 2D character's legs snap to non flat terrain?

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:

Snapping UI sprite in Unity?

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.

Best way to use Farseer/Box2D's DebugDraw in Unity3D?

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);

Instantiate prefab around a object

I have a scene with a body maked with makehuman, and I need to add a simple prefab (a torus) around the arm of the body when the user touch the arm.
I tried:
Instantiate the prefab in the point where the user touch, but the prefab apear in the border of the arm.
Instantiate the prefab in the center of the arm, with this code:
float radio = hit.transform.collider.radius; // the arm has a capsuleCollider
Ray r = Camera.main.ScreenPointToRay(Input.GetTouch(0));
Vector3 origin = r.origin;
float distance = (origin - hit.point).magnitude;
RaycastHit ou;
Vector3 position = hit.point;
Ray r2 = new Ray(r.GetPoint(distance + 10f), -r.direction);
if (cc.Raycast(r2, out ou, distance + 10f))
position = (hit.point + ou.point) / 2;
Instantiate(Prefab, position, Quaternion.identity);
This try to Select the center of the arm and initialite a torus.
The second option works in some cases, but the general impression is that is the wrong way to do it.
How can I add a prefab around a collider? or, how can I modify the mesh to add a visual indicator?
This should work a lot better as well as look a lot cleaner:
Vector3 center = hit.transform.collider.bounds.center;
Instantiate(Prefab, center, Quaternion.identity);
hit.transform.collider is a vital part of this process and you got that part. collider.bounds is the bounding box that surrounds the collider (http://docs.unity3d.com/ScriptReference/Collider-bounds.html), and bounds.center is the center of the bounding box (http://docs.unity3d.com/ScriptReference/Bounds-center.html). The Vector3 that bounds.center returns is where you want to spawn your prefab.
From there, you should be able to rotate the prefab to the desired angle and perform any number of operations you want.

Why is Unity3D RaycastHit.textureCoord always 0,0?

var startPoint =
shaft.transform.position
+ shaft.transform.forward;
var ray = new Ray(
startPoint,
-shaft.transform.forward
);
RaycastHit rayCastHit;
Physics.Raycast(ray, out rayCastHit);
var textured2D = (Texture2D)discoBall.renderer.material.mainTexture;
Vector2 textureCoord = rayCastHit.textureCoord;
Debug.Log(string.Format(
"{0},{1} at distance {2}",
textureCoord.x * textured2D.width,
textureCoord.y * textured2D.height,
rayCastHit.distance
));
I have a sphere with an object "Shaft" object inside it. I work out a startPoint as a distance away from the shaft in the direction the shaft points (to get outside the sphere). I then create a ray pointing back at the sphere with the same distance, so that it collides with the outside of my sphere.
The Debug.Log outputs x,y = 0,0 for the textureCoord, and the correct value of 0.35 for the distance. Why is the textureCoord always 0,0 when I do in fact have a material with a texture on my sphere?
Actually let me move my comment here, does the sphere use a mesh collider or a sphere collider? If it doesn't use a mesh collider, textureCoord returns Vector2.zero.
Update:
To change the collider type of a GameObject highlight it in the Unity editor and go to Component->Physics->MeshCollider. If prompted to 'Replace Existing Component', select 'Replace'.
GameObjects added from Unity's GameObject->Create_Other menu tend to default to colliders based on the shape of the object (spheres, boxes, etc), since mesh colliders are computationally more expensive.
Is the texture2d width and height actually what you expect? Possibly maintexture is not the correct texture on the shader you are using.