- Home /
Find point perpendicular to line
Hi, I'm struggling with understanding how to convert some algebra into code. I have an RTS game where I can select units and click at a point to move them. I would like to make it so every unit is spaced apart a constant value (units are all the same size) from eachother unit. I would like this spacing to be angle aware, meaning that the units will be spaced relative to the perpendicular angle of the closest unit.
Known: Fist unit's position, target move position, max number of units in one line, current x and z iteration.
I tried a bunch of different things, but my current attempt was
float dx = firstUnit.currentPos.x - targetPos.x;
float dy = firstUnit.currentPos.z - targetPos.z;
float dist = math.sqrt((dx*dx)+(dy*dy));
dx /= dist;
dy /= dist;
for(int i=0 i<selectedUnits.Count; i++)
{
float3 target = targetPos;
target.x += (currentX*1.6f) * dy;
target.z += currentZ*1.6f * dx;
}[/code]
I'm rather stumped on how to get pos2 through 9. Any help is appreciated. Also Unity Forums has this nice code formatter block thing, but I'm not seeing it here on Unity Answers. I apologize for the long codesnippet.
EDIT: Removed magority of content in codesnippet due to unreadability.
Answer by Pangamini · Nov 06, 2019 at 04:22 PM
Let's try this
Vector3 targetPosition; // input value
Vector3 currentPosition; // input value
Vector3 offset = targetPosition - currentPosition;
// if your positions were all 2D vectors, to create a perpendicular vector, it would be sufficient to do
// Vector2 offset;
// Vector2 perpendicular = new Vector2(-direction.y, direction.x).normalized;
// you can either do that (if you ignore the vertical portion) or do some more math.
// To have a perpendicular to direction, we need one more vector to define a plane, to which the final vector will be perpendicular. Let's say it's world Up vector
Vector3 perpendicular = Vector3.Cross(offset, Vector3.up).normalized;
You should be able to manage from here, right?
Thank you for the response! I apparently am not able to manage from here. I thought I just multiplied the perpendicular by the distance away from the target point. That process is not working, so I am a little stumped.
float3 offset = targetPos - firstUnit.currentPos;
float3 perpendicular = Vector3.Cross(offset,Vector3.up).normalized;
for(int i=1; i<selectedUnits.Length; i++)
{
float3 target = targetPos;
target.x += currentX * 1.6f *perpendicular.x;
target.z += currentZ * 1.6f *perpendicular.z;
//set pathfinding target here
//switch currentX between positive and negative values (so target is left-right-left-etc of original target) here, as well as iterate the currentZ value when the row exceeds unit capacity.
}
Is it not as simple as I think it is, or am I just doing something silly without realizing it?
well, you now have 2 vectors
Vector3 forward = offset.normalized;
Vector3 perpendicular;
These represent the transformation from local space (your grid of target positions) to the world space. Let's calculate points in local space on the grid. Let's say the first one is always exact. The position on the grid is (0, 0). Then let's say you want one position to the left and right of the target position, those coords would be (1, 0) and (-1, 0). And to form a second line, you'd generate points (-1, -1), (0, -1), (1, -1). I guess you can generate such points, based on the number of units and other parameters (number of units in line, for$$anonymous$$g a square, etc). Now, to convert each local point to a world point, simply do
Vector3 worldPoint = targetPosition + perpendicular * localPoint.x + forward * localPoint.y;
So, from the equation you can see, the worldPoint is a sum of a couple of vectors:
targetPosition, giving us a pivot of your local positions grid/space in the world space
perpendicular * localPoint.x, moving the point perpendicularly, left and right
forward * localPoint.y, moving the point in the main direction, forward and backwards
Yup that was what I misunderstood! Thank you millions.
Answer by petur · Nov 06, 2019 at 09:15 PM
I use this code to move 2 units at the same time:
//Calculating the normal
Vector3 startPosition = GameManager.GetAveragePlayerPosition();
Vector3 moveDirection = (destination - startPosition).normalized;
Vector3 normal = Vector3.Cross(moveDirection, Vector3.up);
GameManager.playerCreatures[0].GetComponent<CreatureIABasic>().MoveCommand(destination + (normal * 1.5f));
GameManager.playerCreatures[1].GetComponent<CreatureIABasic>().MoveCommand(destination - (normal * 1.5f));