- Home /
The question is answered, right answer was accepted!
Problem with Mathf.Clamp and Mouse Follow Script
I am attempting to have my character's arm follow the player's mouse. I have two problems.
First is I cannot figure out how to lessen the distance the player's mouse must be from the character's arm for the character's arm to copy its movement. That is not the most clearly worded description so I've attached a link to a video that demonstrates the problem.
Second is that I also have added a Math.Clamp min and max so the player cannot windmill the character's arm but I have not figured out how to stop the arm from snapping to the max rotation when it approaches the min rotation. instead of just stopping rotating and staying at "0" degrees it snaps to 90. Thanks in advance for your time.
Below I also have attached the mouse follow script and the script that defines the mouse the "Game Cursor" Script.
ttps://www.youtube.com/watch?v=MIcUjkDGIRY
Thankyou for your time!`
public static class GameCursor { public static Vector2 WorldPosition { get { float distance; var ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (_gamePlane.Raycast(ray, out distance)) return ray.GetPoint(distance); // Ray did not hit plane return Vector2.zero; } } private static Plane _gamePlane = new Plane(Vector3.forward, 0); }
using UnityEngine;
public class PointAtCursor : MonoBehaviour
{
public Vector3 targetPosition;
public float maxLength;
public GameObject ArmR;
void Start ()
{
}
private void Update()
{
if (Input.GetKey (KeyCode.E)) {
Follow ();
}
if (Input.GetKeyUp (KeyCode.E)) {
}
print (transform.eulerAngles.z);
Vector3 clampedRotation = transform.eulerAngles;
// Clamp the z value
clampedRotation.z = Mathf.Clamp(clampedRotation.z, -0 ,90);
// assign the clamped rotation
ArmR.transform.rotation = Quaternion.Euler(clampedRotation);
if(ArmR.transform.eulerAngles.z == 0){
Debug.Log ("AT0");
}
if(ArmR.transform.eulerAngles.z == 90){
Debug.Log ("AT90");
}
}
void Follow(){
ArmR.transform.up = -GameCursor.WorldPosition;
}
private void OnDrawGizmos()
{
Gizmos.DrawIcon(GameCursor.WorldPosition, "wallll", true);
}
}
Answer by LCStark · Sep 21, 2018 at 06:36 AM
I believe the problem lies in your use of transform.eulerAngles
. It always returns the rotation angles within the 0-360 degree range, so when your z
rotation is < 0, it actually returns a 360 + z
value (e. g. if your z
rotation is -5 degrees, transform.eulerAngles.z
will show 355 degrees). Doesn't your print (transform.eulerAngles.z);
show that?
You could fix that by manually re-mapping the angle values.
Vector3 clampedRotation = transform.eulerAngles;
if (clampedRotation.z > 180.0f) clampedRotation.z = 360.0f - clampedRotation.z;
// Clamp the z value
clampedRotation.z = Mathf.Clamp(clampedRotation.z, -0 ,90);
I added an offset and some other stuff and its working just about perfectly! Thanks so much for your help.
Nice! It looks good. You're welcome! You can mark my answer as the answer to your question, so it is closed.
Hey, Sorry to keep harassing you! but, the GameCursor Script you wrote, I'm having a hard time adding a layermask to it because it doesn't seem to line up with the documentation in the API. I thought i was supposed to add the layermask to (_gamePlane.Raycast(ray, out distance,layermask)) there but unity is telling me there is no overload method for raycast takes three arguments...
float distance;
int layer$$anonymous$$ask = 1<<9; //setting layer mask to layer 9
mask = ~mask; //setting the layer mask to ignore layer(~)
//adding in the layermask to raycast will ignore 9th layer
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (_gamePlane.Raycast(ray, out distance))
return ray.GetPoint(distance);
//Vector3 point = ray.origin + (ray.direction * distance);
// Ray did not hit plane
return Vector2.zero;
No problem! Assu$$anonymous$$g your _gamePlane
object is of type Plane
, Plane.Raycast function has only one version - the one that takes the Ray
as the first parameter and reference to a float value that stores the distance to intersection as the second. The method that can also take a layer$$anonymous$$ask
parameter is actually Physics.Raycast, specifically this version: public static bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance = $$anonymous$$athf.Infinity, int layer$$anonymous$$ask = DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal);
.
So, your call should look something like that:
RaycastHit hit;
if (Physics.Raycast(ray, out hit, $$anonymous$$athf.Infinity, layer$$anonymous$$ask))
return ray.GetPoint(hit.distance);
EDIT
Apparently RaycastHit
already stores the impact point, so the GetPoint
function is not required here. You can simply use return hit.point;
.
Follow this Question
Related Questions
I need help with this code for clamping my cam 0 Answers
Multiple Cars not working 1 Answer
How to clamp rotation between negative and positive value 2 Answers
Distribute terrain in zones 3 Answers