- Home /
Limit the position of the object, but still keep following the touch? How to use ClampMagnitude properly?
How do I limit/clamp the position of an object that's following the touch, but still be able to follow the touch?
I want it to be like this one:
I also tried magnitude.clamp but it just won't work for some reason. Maybe I'm doing something wrong with it? Nothing happens when I insert the magnitude.clamp code. With or without it, the results are the same.
I'm also using a 2nd camera on Orthographic View. Maybe that has something to do with it? The only limiter I'm using right now are the colliders, but it doesn't follow the touch anymore once the touch is outside the collider, and I don't want that to happen.
Here's the code I'm currently using:
if (Input.touchCount > 0)
{
Ray ray = camera2.ScreenPointToRay(theTouch[0].position);
//When the touch is out of the "border", this object completely stops following the touch
//I want it to just limit the position of this object, but still keep following the touch
//Where it can still detect where my touches are, and then try to follow it, but it can't go outside the border
if(Physics.Raycast(ray, out hit) && hit.collider.tag == "border")
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Stationary || touch.phase == TouchPhase.Moved)
{
//Finds the position of the touch
touchPosition = camera2.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, 10));
//Follows the touch
transform.position = Vector3.Lerp(transform.position, touchPosition, Time.deltaTime * 10);
}
}
}
Thanks! I've tried Google and searching here on Unity Answers but found none unfortunately
Can you post the version of your code where you use $$anonymous$$agnitude.Clamp
?
You should be able to use $$anonymous$$athf.Clamp
to limit the axes of the touchPosition vector you are calculating:
touchPosition = camera2.ScreenToWorldPoint(...);
touchPosition.x = $$anonymous$$athf.Clamp(touchPosition.x, -10f, 10f);
@christoph_r Yeah here's the code, I'm not really sure on how to use it really. if (Input.touchCount > 0) {
Ray ray = camera2.ScreenPointToRay(theTouch[0].position);
if(Physics.Raycast(ray, out hit) && hit.collider.tag == "border")
{
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Stationary || touch.phase == TouchPhase.$$anonymous$$oved)
{
//THE CLA$$anonymous$$P
touchPosition = Vector3.Clamp$$anonymous$$agnitude(touchPosition, 10.945309f);
touchPosition = camera2.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, 10));
transform.position = Vector3.Lerp(transform.position, touchPosition, Time.deltaTime * 10);
}
}
}
@Josh707 Thanks! I'll try it out later when i get home. Can this also be used for $$anonymous$$agnitude.Clamp? I need a circular clamp or something.
It would be easier to do something circular without using Clamp methods in my opinion, if you have the center position of the circle you can do some vector subtraction to get a direction.
Something like this:
public Transform obj; //Object you're dragging around
public Transform circle_center; //Center of the circle
float circle_radius = 1f;
//Get the direction/distance towards the object from the center
Vector3 direction = obj.position - circle_center.position;
/*If the distance is greater than the set radius,
set 'obj' position to the circle's center with direction
multiplied by radius added to it*/
if(direction.magnitude > circle_radius)
player.position = circle_center.position + (direction.normalized * circle_radius);
Answer by rutter · May 29, 2014 at 08:47 PM
Unless you're very sure of what you're doing, you're using Lerp incorrectly.
Assuming 30fps, this Lerp call gives you a point about 33% between pos1
and pos2
:
Vector3 v = Vector3.Lerp(pos1, pos2, Time.deltaTime * 10);
This MoveTowards call gives you a point that moves from pos1
toward pos2
at about 10 meters per second:
Vector3 v = Vector3.MoveTowards(pos1, pos2, Time.deltaTime * 10);
Finally, I don't see any ClampMagnitude
call in your code. If you're trying to clamp within a sphere, that should do the trick. If one axis of the vector is guaranteed to be zero, then it'll clamp on a circle.
This would clamp within 10 units, for example:
Vector3 v2 = Vector3.ClampMagnitude(v, 10f);
Thanks! But I couldn't get the Clamp$$anonymous$$agnitude to work. Is it because the object isn't in the middle (0,0,0)? I wanted the center of the circle to be on the bottom right of the screen.
I've tried this one and it just stays on middle of the screen when I'm touching it:
transform.position = Vector3.$$anonymous$$oveTowards(transform.position, touchPosition, Time.deltaTime * 10);
transform.position = Vector3.Clamp$$anonymous$$agnitude(transform.position + centerPos.position, 1f);
Is there something wrong with my script? Thanks :)
If you want a clamped position relative to something other than (0,0,0), you can calculate that:
//where you want to be (according to $$anonymous$$oveTowards)
Vector3 desiredPosition = ???
//your clamp is relative to this position
Vector3 origin = ???
//this vector points from 'origin' to 'desiredPosition'
Vector3 diff = desiredPosition - origin;
//clamp the difference, then add it to the origin
transform.position = origin + Vector3.Clamp$$anonymous$$agnitude(diff, 1f);
origin
is perhaps the position of another object, or a point calculated using ScreenToWorldPoint.