- Home /
Two Strange MathF Clamp Issues: The Disabling of OnMouseDrag
Hey friends,
.
I'm having a couple of issues that I haven't seen addressed before. After a couple of hours of research, I figured it's time to ask the questions myself to figure out what mistakes I am making. I'm very new to unity, so please let me know if I am doing something stupid. Here's the first conundrum:
.
MathF clamp works if I use the clamp in the script. However, if I set up the floats to use inside of the Unity Editor itself, it clamps my game objects on play and I cannot move them. I know they are still draggable because they become a trigger when I stop dragging them, they just don't move. This isn't that big of a deal since I can get it to work with the solution below, but I want to figure out why it does it. I used the clamp code from the Space Shooter tutorial. here's the code for my script:
using System.Collections;
using UnityEngine;
[System.Serializable]
public class Boundary
{
public float xMin, xMax, yMin, yMax;
}
public class Merge_1 : MonoBehaviour
{
public Rigidbody rb;
Vector2 mousePos;
public GameObject Merge_2;
Collider ObjectCollider;
public Boundary boundary;
void Start()
{
mousePos = new Vector2(transform.position.x, transform.position.y);
rb = GetComponent<Rigidbody>();
ObjectCollider = GetComponent<Collider>();
ObjectCollider.isTrigger = false;
}
void OnMouseDrag() // Use this to Move Game Objects By Clicking and Dragging Mouse
{
mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
}
IEnumerator noTrigger()
{
yield return new WaitForSeconds(0.1f);
ObjectCollider.isTrigger = false;
}
void OnMouseUp()
{
ObjectCollider.isTrigger = true;
StartCoroutine(noTrigger());
}
void FixedUpdate()
{
rb.MovePosition(mousePos); // Moves Object with Mouse Position with RigidBody Component
rb.position = new Vector2
(
Mathf.Clamp(rb.position.x, boundary.xMin, boundary.xMax),
Mathf.Clamp(rb.position.y, boundary.yMin, boundary.yMax)
);
}
void LateUpdate()
{
Vector2 pos = transform.position;
pos.x = Mathf.Clamp(pos.x, -8, 8);
pos.y = Mathf.Clamp(pos.y, -4, 4);
transform.position = pos;
}
void OnTriggerEnter(Collider other) // Allows game objects to be merged and create the next unit
{
if (other.gameObject.tag == gameObject.tag) // destroys current object
{
Destroy(gameObject);
if (GetInstanceID() < other.gameObject.GetInstanceID()) //Creates new object
{
Instantiate(Resources.Load("Merge_2"), transform.position, transform.rotation);
}
}
}
}
Now, the second issue is in the way I am using Mathf.Clamp. When I use the clamp and give the transform positions in the script itself, it works! The objects are draggable, and they don't go passed the clamped positions. However, SOMETIMES the objects get stuck on the clamped position and I have to drag it multiple times to unstick it.
.
For example, my x.min clamp is set to -8. If I try to drag the object passed -8 on the x axis, it gets stopped. Perfect. I can then drag it again and move it elsewhere. However, when I stop dragging when the object is at -8, SOMETIMES it gets stuck on -8 and I have trouble dragging it again. When this happens, there is no shaking of the object; it just seems that I haven't even clicked it until multiple attempts have passed.
.
.
Here are some screenshots of what's happening on the editor's side of things:
Just some further notes:
.
1. I have placed the second solution in late update to stop the game objects from clipping passed the clamped coordinates. This works. If I place them in update or fixed update, they continually try to get passed the clamp when I stop dragging with my mouse passed the clamp. If I place the first clamp I mentioned in late update, the objects are draggable, but the clamps don't work at all.
.
2. The floats for the mathf clamp in my first issue and the ones used in my solution (by listing the values in the script) are identical.
.
3. To stop the game objects from getting stuck at the clamped position, I attempted to move the game object with an if statement. Pseudo code: If position is -8, move to -7. It moved, but the object would still sometimes get stuck, so I'm not sure what's causing the issue.
.
.
There you have it. I'm very new to Unity and have done my best to research before asking, but I haven't found an answer yet on what I could be doing wrong. I'm hoping it will help newcomers like me to understand what's going on and how to fix these things!
.
.
Thank you eternally for reading this and perhaps even finding a solution! I apologize if I have overlooked a simple fix. Thank you again!
Cheers,
Sam
$$anonymous$$ay i ask how are you moving them? Also you sre using both fixedupdate and kateupdate code?
Hey there! Thanks for getting back to me.
I use On$$anonymous$$ouseDrag to move the objects.
void On$$anonymous$$ouseDrag()
{
mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
}
FixedUpdate contains "rb.moveposition (mousepos);"
LateUpdate only contains the code for the $$anonymous$$athf clamp that I posted above in my second issue section.
Can you tty changing the fixedupdate code to the lateupdate in case it is having any conflict? Hard to tell without being ablr to debug
Answer by xxmariofer · Apr 09, 2019 at 02:45 PM
i will post is as an answer, transform.position isnt hte same as rigidbody.position (i also learned today) override the fixedupdate code
void FixedUpdate()
{
rb.MovePosition(mousePos); // Moves Object with Mouse Position with RigidBody Component
Vector2 pos = rb.position;
pos.x = Mathf.Clamp(pos.x, -8, 8);
pos.y = Mathf.Clamp(pos.y, -4, 4);
rb.position = pos;
}
Thanks $$anonymous$$ario, unfortunately I used your code and the object is completely undraggable now. I'm looking at my other pieces to try to figure out what's going on. Hopefully I'll figure it out soon.
Edit: The issue appears to be that the cube was set to "Is $$anonymous$$inematic". When it is not, it works perfectly! If the object is kinematic, then I can't move the object at all with the code you provided. Any suggestions on how to fix this? I don't want other objects to be bumping around when I'm dragging. I want the object I am dragging to seamlessly pass through other objects.
Then you neef to mark it as trigger in the boxcollider
Here's what I did. I made it so that the object gets lifted up on the z-axis above everything else. that way it's not bumping everything when I'm dragging it. So kinematic can stay false, and when I want to merge, I just drop it down and the trigger activates. Here's the code if anyone is curious:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NoGlitch : $$anonymous$$onoBehaviour
{
public Rigidbody rb;
Vector3 mousePos;
void Start()
{
rb = GetComponent<Rigidbody>();
mousePos = new Vector3(transform.position.x, transform.position.y, 0);
}
void On$$anonymous$$ouseDrag() // Use this to $$anonymous$$ove Game Objects By Clicking and Dragging $$anonymous$$ouse
{
mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z = 4;
}
void On$$anonymous$$ouseUp()
{
mousePos.z = 0;
}
void FixedUpdate()
{
rb.$$anonymous$$ovePosition(mousePos); // $$anonymous$$oves Object with $$anonymous$$ouse Position with RigidBody Component
Vector3 pos = rb.position;
pos.x = $$anonymous$$athf.Clamp(pos.x, -8, 8);
pos.y = $$anonymous$$athf.Clamp(pos.y, -4, 4);
pos.z = $$anonymous$$athf.Clamp(pos.z, 0, 4);
rb.position = pos;
}
I can't thank you enough for all of your help $$anonymous$$ario!! You really helped me figure all this out. Thanks so much, you legend!
Answer by Bunny83 · Apr 06, 2019 at 01:51 PM
First of all assuming theres a "bug" in Mathf.Clamp is the absolute last thing you should assume. You should look for the error / bug in your own code first. Actually Mathf.Clamp is exactly defined here:
public static float Clamp(float value, float min, float max)
{
if (value < min)
value = min;
else if (value > max)
value = max;
return value;
}
So there's nothing that can go wrong in Mathf.Clamp unless you pass nonsense to the method.
The description of your issues are very vague and the code you've provided are just seemingly unrelated fragments. Since you seem to have dragging code somewhere, chances are high you do something fishy there. Also what have you done already to debug your issue? You said using hardcoded boundary constants works while using a serialized value does not? This makes no sense. Have you tried printing out the position before and after the clamp? Also print out the boundary values at the point where they are used.
When a certain issue happens only "SOMETIMES" it's a quite clear indicator that you have some sort of race condition / competing code. You need to get better to understand your own code, which part can influence which other part. Always keep in mind Computers don't make mistakes, humans do. If a computer makes a mistake, it's broken and is trash. Unless you have a hardware failure in your machine, code will do 100% what it instructs the CPU to do. Of course there are other factors of complicated code which are difficult to understand or to predict (i look at you, multithreading). If you don't understand what or why something happens you just don't have the full picture yet.
However we have a much less complete picture of your issue since we only know what you have written in your question.
Hey Bunny, thanks for your detailed response.
I want to first apologize, I didn't mean to say that $$anonymous$$athf Clamp is bugged. I didn't make it clear that I knew I was doing something wrong, so I apologize for that. I am new to coding in general, so I have learned a lot from your response. I wasn't sure if I should post the whole code or not since it would make the post long, but I have edited my post to include the whole script, as well as made it clear that I don't think $$anonymous$$athf Clamp is bugged.
I'll have to get back to you on your suggestions, I don't have much time right now. But thank you so much thus far! You are a legend.
Do you use an orthographic camera? If you use a perspective camera, this line does not do what you might expect:
mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
This line when used with a perspective camera will always just return the camera position. ScreenToWorldPoint takes a Vector3 as parameter where the z value specifies the distance from the camera in world units. Since you directly pass in Input.mousePosition, the z values will be 0. At 0 distance from a perspective camera the frustum would shrink to a single point.
Since you said the dragging does work sometimes i guess you use an orthographic camera?
Yes, I use an othographic camera. I've updated my post to include a couple of screenshots of what's happening on the Editor's side.
I printed the boundaries and the transform position, and everything is looking right, assu$$anonymous$$g I did that correctly. $$anonymous$$ario (the other commenter helping me) said he couldn't replicate my code because it worked. However, no matter how many times I try from scratch, I can't get the serialized mathf clamp to work, so I'm pretty confused on what I'm doing wrong.
Your answer