- Home /
Mathf.Clamp() not working as expected.
I'm attempting to use the Mathf.Clamp() function to restrict the movement of a user controlled object. But for some reason, it doesn't seem to have any effect. All the examples that I have come across seem to be in Javascript, rather than my preffered C#, so I'm open to the possibility it could be a variable type issue of some sort. Can any of you kind folks see the issue?
using UnityEngine;
using System.Collections;
public class MoveXY : MonoBehaviour {
public Transform target;
public float speedHorizontal = 10.0F;
public float speedVertical = 10.0F;
void Start () {
if(!target)
return;
}
void Update () {
float translation = Input.GetAxis("Vertical") * speedVertical;
translation = translation * Time.deltaTime;
float translation2 = Input.GetAxis("Horizontal") * speedHorizontal;
translation2 = translation2 * Time.deltaTime;
target.transform.Translate(0.0F, translation, 0.0F);
target.transform.Translate(Mathf.Clamp(translation2, -2.0F, 2.0F), 0.0F, 0.0F);
}
}
On a side-note, you can write things like translation = translation * Time.deltaTime
as translation *= Time.deltaTime
. It's the same with other operands.
Thanks for the response. I am actually familar with the short hand you mentioned, but I'm a little pedantic when it comes to writing this sort of expression lol - for some reason I tend to prefer the more verbose version.
Answer by Bunny83 · Jul 06, 2011 at 04:07 PM
public static Vector3 ClampVector3(Vector3 vec, Vector3 min, vector3 max)
{
return Vector3.Min(max,Vector3.Max(min,vec));
}
This function will clamp a vector3 within the box defined by min and max. If you just want to clamp only one axis you have to do it that way:
Vector3 pos = target.position;
pos.x = Mathf.Clamp(pos.x, 2.0f, -2.0f);
target.position = pos;
Answer by sneftel · Jul 06, 2011 at 03:42 PM
I note that you're clamping the displacement of the object (its per-frame movement), not its absolute position. If you want to constrain its x position, translate it without clamping, then do target.transform.position.x = Mathf.Clamp(target.transform.position.x, -2, 2)
afterwards.
Just to mention it in C# you can't do it that way. position is a property and this line:
target.transform.position.x = ...
Will call the getter of the position and return a copy of the Vector3 of which you are setting the x value. The actual position won't be affected.
You have to save a copy of the position and assign the Vector3 back to position.
Ah, so there is indeed a inherent C# issue located somewhere in this problem. I can only lament that most examples I come across are in Javascript for this very reason!
Answer by Eric5h5 · Jul 06, 2011 at 03:42 PM
Mathf.Clamp always works as expected. Your code is limiting the speed. If you mean to limit the position, transform.Translate isn't what you want, since that's relative movement, not absolute.
This is my code moveDirection = Vector3.forward + new Vector3(Input.acceleration.x * 0.3f, 0, 0);
transform.Translate(moveDirection * Time.deltaTime *9);
transform.position.x = $$anonymous$$athf.Clamp(transform.position.x, -2.0f, 2.0f);
But i am getting error CS1612: Cannot modify a value type return value of `UnityEngine.Transform.position'. Consider storing the value in a temporary variable
You can only write code like that in Unityscript, not C#. As the error says, you should use a temporary variable; specifically a Vector3, then write it back.
No, the error is referring to transform.position. You can't write to transform.position.x in C#, you have to use a temporary Vector3 variable.
Answer by AndyB_1992 · Sep 09, 2013 at 02:04 AM
I had a script which clamped x and y using transform.position to move my player - this worked fine. I tried to use the Translate method, and clamp the X and Y values in C# but did not work.
Annoying since using Translate() makes my object transform a lot smoother than using transform.position = new Vector(x,y,z) - this is too precise.
In order to use Translate() with clamps I had to write the code in Javascript (which worked) so that is one of your options. However I forgot I had a C# script that I found which results in smooth transformations that uses transform.position = new Vector 3 so here it is:
using System.Collections;
public class DragScript : MonoBehaviour
{
[SerializeField]
float _horizontalLimit = 2.5f, _verticalLimit = 2.5f, dragSpeed = 0.01f;
Transform cachedTransform;
Vector3 startingPos;
void Start ()
{
//Make reference to transform
cachedTransform = transform;
//Save starting position
startingPos = cachedTransform.position;
}
void Update ()
{
if (Input.touchCount > 0) {
Vector2 deltaPosition = Input.GetTouch (0).deltaPosition;
//Switch through touch events
switch (Input.GetTouch (0).phase) {
case TouchPhase.Began:
break;
case TouchPhase.Moved:
DragObject (deltaPosition);
break;
case TouchPhase.Ended:
break;
}
}
}
void DragObject (Vector2 deltaPosition)
{
cachedTransform.position = new Vector3 (Mathf.Clamp ((deltaPosition.x * dragSpeed) + cachedTransform.position.x,
startingPos.x - _horizontalLimit, startingPos.x + _horizontalLimit),
Mathf.Clamp ((deltaPosition.y * dragSpeed) + cachedTransform.position.y, startingPos.y - _verticalLimit, startingPos.y + _verticalLimit),
cachedTransform.position.z);
}
}