So, i have access to three Vector2 composing a triangle.
The user picks an edge.
I need to put a gameobject with the right rotation on that edge. For example, a monster (it’s not a monster but this is the easiest way to explain). The monster has to be rotated so it’s feet are against this edge ( it has first to detect if this edge is the floor, or a ceiling, because if it doesn’t, it will maybe think this is a floor instead of a ceiling, and sets it’s position inside of the triangle instead of outside)
I guess i could try to draw a perpendicular line to the red line, and check which side of the line goes back inside the triangle, then calculate the angle from that .
Or directly check the angles between [1,1/0,0] and [-2,2/0,0] and use that.
As this is a map editor, performances aren’t really an issue, thing is, i forgot most of my mathematics classes and my brain starts to melt everytime i try to figure out how to do it.
(Actually, someone told me I should use Vector3.Cross, but, i believe i’m not clever enough to understand the way to use it).
Almost exactly. The only difference is i won’t click on the line. The line is already known before (well, i clicked on the line to select it, adding in a script a reference to that line), and i make the monster appear by checking a UI box / keyboard input.
OK, this is the solution I came up with. There must be better solutions. But this works.
// find the center of that edge
Vector3 center = (point1.localPosition + point2.localPosition) / 2;
// find the angle of that edge
Vector3 diff = point1.localPosition - point2.localPosition;
float angle = Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg;
// making a test point with a distance of the center point to see if it is closer to the third point or not
float testingAngle = angle + 90;
const float testingRadius = 0.1f;
Vector3 testPoint = new Vector3();
testPoint.x = Mathf.Cos(testingAngle * Mathf.Deg2Rad) * testingRadius + center.x;
testPoint.y = Mathf.Sin(testingAngle * Mathf.Deg2Rad) * testingRadius + center.y;
// check the distance between the center point and the test point
float distance = (center - point3.localPosition).sqrMagnitude;
float testDistance = (testPoint - point3.localPosition).sqrMagnitude;
// if test point is closer, then it is in the triangle and we need the oposite angle (+180 degrees)
float rotationAmount = 0;
if (testDistance < distance)
rotationAmount = angle + 180;
else
rotationAmount = angle;
// we put our monster in the position
monster.localRotation = Quaternion.Euler(0, 0, rotationAmount);
monster.localPosition = center;
Tell me if anything looks confusing.
I attached the project.
Hope it helps you
It helps me, a lot. Thank you, a lot.
You gave 100% of the answer in a way I can understand tweak to my needs (I tried your attached project, it’s just perfect).
The question in this topic is in fact the end of the answer I ended up with after asking how to detect the facing direction of sides of a polygon in answers.unity3d.com . Here is the topic (click).
(it explains the use of what you have done for me). I’ll just need to re-read the basics about trigonometry to know where to place my 8 mesh vertices (if someone reading this knows how to make a quad instead of a mesh have 3 materials(one left, one right, and one repeating middle) i would love to see how it’s done).
Something like a quarter of the functions you use were unknown to me , but using the unity documentation I understood what does every part of your code. I was actively trying to figure out the answer of my own question, but you were faster and better than me, checking the distance relative to the 3rd point was a genius move, as it works with triangles only, most poeple would have tried something working for any generic polygon instead.
This is just out of curiosity, but i’d like to know what kind of project you are actually working on, and since when you did start creating things.
Thanks a bunch, you are the real MVP.
I am doing this for 4 years professionally, but was always curious.
I mostly do 2d casual games. But also love to create tools for other developers. Give me a message if you had any questions or need some specific tools. I love to help
Well, as generic polygon i meant convex as well as concave, and as non generic, i meant (mostly) a polygon where edges actually cross each other (i’m not sure if it is still a polygon). Still, using your solution after disassembling the polygons into triangles, my project now works with convex/concave polygons, but also polygons having edges crossing each other.
(Well it’s pretty hard to understand with such a pic, but it create 8 new Vector2 for each edge of the polygon, these will be used to create meshes. The final result will have this polygon, with grass on top, “rocks” on edges close to 90/-90 degrees edges, and a slope border for those around 45/-45 degrees. )
I checked the results multiple times and everything is at the right spot.
(here is the same result with a square, but a lot of points are at the same position)
(For google user finding this and needing something close to that (this is destiny, you can’t get there needing this by mistake), “creating a platform as a mesh autotilled by setting some points, and automatically creating edges according to the platform polygon”, you will need trigonometry to figure out how to rotate a point around the center of each edge, as long as reading the result of the link to the “Answer dot unity3d dot com” and the results of this topic. Leave me a message, if i’m still active around there i’ll try to help you.
Actually, I can’t find the way to finish it…
As the meshes i try i create are filled with a repeating texture, as the meshes uv are set to the vertices vector2 positions, and as the gameobject containing the mesh 's position is zero, it creates some kind of grid visible inside the rectangles created by the yellow points. By rotating the gameobject, i rotate the grid, by setting the gameobjects position inside a Vector2 between (0,0) and (1,1) i can translate the entire grid in any direction.
(actual result)
But i can’t find the way to translate it correctly (But achieve to get the attended result afterwhile by positionning the object correctly myself using unity’s editor). This is getting on my nerves, i guess i’m gonna make a break from programming for a few days, i’m pretty sure the way to do this is just under my nose but i’m a bit too upset right now.
I can’t understand your problem. Why do you set position for rotating the grid? You want to rotate entire grid with all of vertices? I guess there is a math solution involving matrices. But personally I would use polar coordinate system. It is a very simple equation. I can explain it to you, if you want. But first explain a little more about what you’re trying to do.
Take it easy my friend. Programming is full of these “unable to complete the task in hand” days. I am sure you know it better than I do. You’re just a little frustrated. A problem that refuses to go away. But hey! That’s what we are here for. That’s what this entire forum is based on upon. Cheer Up
I calmed down, and after tweaking the thing a bit randomly, i found half of the solution.
TheObjectHoldingTheMesh.transform.position = RotateAroundPivot(new Vector2(center.x , center.y-0.5f ), center, line.angle);
Vector2 RotateAroundPivot(Vector2 aPoint, Vector3 aPivot, float aDegree)
{
aPoint -= (Vector2)aPivot;
float rad = aDegree * Mathf.Deg2Rad;
float s = Mathf.Sin(rad);
float c = Mathf.Cos(rad);
return aPivot + new Vector3(
aPoint.x * c - aPoint.y * s,
aPoint.y * c + aPoint.x * s
);
}
Getting this result
As vertices are made from WorldPositions , moving the gameObject doesn’t make the mesh move, only the texture repeated inside the mesh moves (because i recreate the mesh everytime the game object move, using the very same vertices)
If the GameObject is in world positions [0,0], the image of the texture starts at [0,0] and ends at [1,0], then repeat from [1,0] to [2,0].
If the GameObject is at [0.1,0]; the texture will start at [0.1,0] then end at [1.1,0].
And I can’t find the way to set the gameobject at the right position .
The yellow points are positionned this way for each side of the polygon:
float distance = Vector3.Distance(line.pointA.transform.position, line.pointB.transform.position) / 2;
points[0].transform.position = new Vector2(center.x - distance, center.y+0.2f);
points[1].transform.position = new Vector2(center.x - distance, center.y-0.55f);
points[2].transform.position = new Vector2(center.x - distance+1, center.y-0.55f);
points[3].transform.position = new Vector2(center.x + distance-1, center.y-0.55f);
points[4].transform.position = new Vector2(center.x + distance, center.y-0.55f);
points[5].transform.position = new Vector2(center.x + distance, center.y+0.2f);
points[6].transform.position = new Vector2(center.x + distance-1, center.y+0.2f);
points[7].transform.position = new Vector2(center.x - distance+1, center.y+0.2f);
foreach (GameObject point in points)
{
point.transform.position = RotateAroundPivot(point.transform.position, center, line.angle);
}
The left part of the texture should start in the middle of the points 0 and 1, and and in the middle of the points 2 and 7. (0,1,2,7 create a 1 unit large square).
After 3 times reading your post, I still don’t know what are you trying to do
I know you have a main game object and a bunch of world positioned game objects that are supposed to move and rotate according to the main game object. But it seems that you’ve already handled that part. So I don’t know what do you mean when you say:
Here is the edge of a square , it’s length is 5 Units.
I need to add a mesh on top of that edge. This mesh contains 3 textures. The first texture, onf the left, will start from the very left of the edge; and will end one unit further on the right.
The second texture, will start from where the first texture ended, and will end one unit before touching the end of the edge.
The third texture, on the right, starts one unit left from the end of the edge, and ends one unit later, on the end of the edge.
Here is a picture of that when it works:
The textures repeat every unit. Setting the gameobject’s position to 0 on the x Axis, the textures repeat everytime their world position value after the point of the float is the same than the value of the gameobject position after the point of the float.
Setting the game object x position to 1.0f, 2.0f,189.0f leads to the same result here.
(The Y position is set to be the y position of the center of the edge, minus 0.55f, this is just what it needs for the textures to be nicely centered on the edge, the using “%1”, i get rid of the integer value of the float and just take the value after the point).
But setting it’s position to 0.5f will have another result:
As the position of the gameObject ends with .5f, the textures starts 0.5f before they should, end right in the middle, and repeat on the other half . This also happens if:
The edge don’t start in an integer position. If the edge starts at (0.5f,0) and the gameobject is at (0,0), this will lead to the same result.
I tried something, by translating the gameObject along the axe made by the angle of the edge;
(Distance is a float value, it is half the value of the edge length). But this works only when the angle is 0,90,180 or 270. And it doesn’t work if the length of the edge isn’t an integer value.
In fact, I believe the entire way i use trying to acheive it is bad and just cannot work, I believe I should do it by modifying the UV of the mesh, but I don’t understand at all how to do it, and furthermore understand even less how to do it the way I need .
So yeah, i was too stubborn before, and the answer to my problem was uv manipulation.I finally found a great tutorial about uv mapping.
I just had to create 12 vertices instead of 8, and set the uv this way:
Vector2[] uv = new Vector2[]
{
new Vector2(0,0.8f),
new Vector2(0,-0.2f),
new Vector2(1,-0.2f),
new Vector2(1,0.8f),
new Vector2(0,0.8f),
new Vector2(0,-0.2f),
new Vector2((distance * 2)-2,-0.2f),
new Vector2((distance * 2)-2,0.8f),
new Vector2(0,0.8f),
new Vector2(0,-0.2f),
new Vector2(1,-0.2f),
new Vector2(1,0.8f),
};
msh.uv = uv;
I’m sorry I made you try to understand something that had no use at all.