Clamp a Vector3 position to an arbitrary line segment
Vector3 start;
Vector3 end;
Transform objectA;
Given points "start" and "end", I would like to clamp "objectA" onto the line segment between both points when moving the transform. Is that possible? How would I approach this?
At the moment I'm using a workaround in which I define the world space axis to which I clamp and then just check the corresponding vector component, but I'd much rather have the system work with any two points, not just axis aligned ones.
My concrete use case is a world space slider object which can be moved by the player with physics forces via a spring joint. Everything works fine if I just freeze two of the rigidbodies axis and check the other axis to limit its movement, but I want it to work when arbitrarily rotated, too.
Answer by lPVDl · Jul 30, 2017 at 06:45 AM
You can try this idea:
Project point onto segment in order to get projected point: Then check distance from point to start, and from point to end: If one of the distances (or their sum, but might be not safe) more than segment length, then their is a need to clamp position, take biggest distance and return opposite point; if start->projection biggest, return end, otherwise return start: And also you can try this code:
using UnityEngine;
public static class VectorUtil
{
public static Vector3 ClampPoint(Vector3 point, Vector3 segmentStart, Vector3 segmentEnd)
{
return ClampProjection(ProjectPoint(point, segmentStart, segmentEnd), segmentStart, segmentEnd);
}
public static Vector3 ProjectPoint(Vector3 point, Vector3 segmentStart, Vector3 segmentEnd)
{
return segmentStart + Vector3.Project(point - segmentStart, segmentEnd - segmentStart);
}
private static Vector3 ClampProjection(Vector3 point, Vector3 start, Vector3 end)
{
var toStart = (point - start).sqrMagnitude;
var toEnd = (point - end).sqrMagnitude;
var segment = (start - end).sqrMagnitude;
if (toStart > segment || toEnd > segment) return toStart > toEnd ? end : start;
return point;
}
}
@xarbrough in your case you can do the following:
objectA.position = VectorUtil.ClampPoint(objectA.position, start, end);
But make sure to move on a chosen line (you can do this by Vector3.MoveTowards or by adding normalized direction multiplied by delta value to current position, etc. etc.
Your answer
Follow this Question
Related Questions
clamp crosshair(vector3) to player 0 Answers
Problem with Crouch Script - 3D C# 2 Answers
How to change Force direction immediately? 1 Answer
How do I change the speed of this script 0 Answers
Vector3.MoveTowards Problems 0 Answers