I’m trying to constrain the object to move inside the plane.
Example
I check to see if object point is within bounds
If it’s within bounds or equals to bounds, then allow movement
If it’s out of bounds, point = bound.x or bound.y accordingly
Problem is that when it does go out of bounds, in this case point.x < -0.5f, it would instead return -0.500001f, instead of exactly -0.5f. This causes the logic to break.
I tried moving all logic to Update(), then I get the issue of teleporting. And still having the problem as above.
Teleport
I can simply break out of the movement loop to stop all interactions until the player clicks again. Which works fine. But I’m wondering if I can achieve what I want without forcing the player to reclick the object to move it back.
I have the movement in a while loop. So as long as left click is held, it’ll attempt to move to position. I can skip the iteration when the point goes out of bound.
Problem is that since it sets the point back at the bound, it’ll just bounce back and forth from the frame that goes out of bound then back to the bound, until the player stops holding the left click.
While Loop
while (PlayerRaycast._onButtonDown)
{
//Update the ray position and direction
r.origin = GameManager.Instance._Character.cameraTransform.position;
r.direction = GameManager.Instance._Character.GetEyeForwardVector();
if (objectPlane.Raycast(r, out enter))
{
//Converting the object world position relative to constraint plane to match rotations
rbPosLocalToConstraint = _constraintPlane.transform.InverseTransformPoint(rb.position);
//Store a temp RB pos to later be applied back to RB position
tempRBPos = rbPosLocalToConstraint;
if (!IsOutOfConstraintBounds(tempRBPos))
{
//Start the lerp movement if we're not at the target destination
if (rb.position != r.GetPoint(enter))
{
t += Time.fixedDeltaTime * 2f;
t = Mathf.Clamp01(t);
//Lerp to the target position to get a smoother transition.
rb.MovePosition(Vector3.Lerp(rb.position, r.GetPoint(enter), t));
}
//Reset t if we're at the target.
if (t.Equals(1f))
{
t = 0f;
}
}
}
yield return Timing.WaitForOneFrame;
}
When Out of Bounds
bool IsOutOfConstraintBounds(Vector3 rbLocalPos)
{
//If the object is out of bound then set the position back to the bound
//Check for the X axis constraints
if (rbPosLocalToConstraint.x < _contraintCorners[0].x)
{
//Set the x position to match the minX
rbLocalPos.x = _contraintCorners[0].x;
rb.position = _constraintPlane.transform.TransformPoint(rbLocalPos);
return true;
}
else if (rbPosLocalToConstraint.x > _contraintCorners[3].x)
{
//Set the x position to match the maxX
rbLocalPos.x = _contraintCorners[3].x;
rb.position = _constraintPlane.transform.TransformPoint(rbLocalPos);
return true;
}
//Check for the Y axis constraints
if (rbPosLocalToConstraint.y < _contraintCorners[0].y)
{
//Set the y position to match the minY
rbLocalPos.y = _contraintCorners[0].y;
rb.position = _constraintPlane.transform.TransformPoint(rbLocalPos);
return true;
}
else if (rbPosLocalToConstraint.y > _contraintCorners[3].y)
{
//Set the y position to match the maxY
rbLocalPos.y = _contraintCorners[3].y;
rb.position = _constraintPlane.transform.TransformPoint(rbLocalPos);
return true;
}
return false;
}
One way to solve this logically would be to do the out of bounds check BEFORE you move the object and only move it if the new position would be valid. This requires you to simulate/calculate the movement beforehand. That way it can never move outside (problem solved). Though it would also never move to the very edge. To do that too you need to calculate the bounding positions and move it there.
Here is a more step by step guide:
Get your current position
Calculate what your next position would be if moved
Check if the calculated position is valid
If valid then apply the calculated position
If invalid then calculate position on bounds and apply that.