- Home /
The question is answered, right answer was accepted
How to stop an object of going to far
look, I have this scripts, that detects where the cursor is, and teleport the object scope is (its basically to make the player aim in 2d with a sprite of a scope, its in my profile pic. The thing is, my script also detects the distance between the player and the scope,and i would like to make it so that the scope can go further than a certain distance for the player, so basically that distance is the range of the weapon
scoop.position = Camera.main.ScreenToWorldPoint(new Vector3(
Input.mousePosition.x,
Input.mousePosition.y,
-Camera.main.transform.position.z
));
distance = (scoop.position - gameObject.transform.position).magnitude;
(Ignore the fact that the player is a chicken) Until now i have been "showing" the player the range with that circle, what i want to do actually is make the scope sorta rotate around the player if it gets to far, but make it so it can move frely if it isn´t too far.
In advance thanks for the answer, I love this community even if I barely know how to program
Just for clarification, the ⊙ is where your cursor is. The big circle is the area you want your duck to be able to teleport. You want the ⊙ to stay inside of the big circle, even if your mouse goes outside of it?
and, its a chicken, have a little respect for him/her
@AllTheGoodNamesWereTaken would like your answer too if you don´t $$anonymous$$d ^^
Answer by ricky_lee_ · Feb 15, 2021 at 03:59 AM
I had a go at the maths for you to try, I'm not that fantastic at coding but I think this should be close.
Vector2 ScoopVector; // World position of the Scoop
Vector2 ChickenVector; // World position of the chicken
float angle; // maths
float realativeX; // more maths
float relativeY; // much more maths
float distance;
float weaponRange = 1f;
void Update()
{
// Work out the world position of the mouse (put into scoop vector)
ScoopVector = new Vector2(
Camera.main.ScreenToWorldPoint(Input.mousePosition).x,
Camera.main.ScreenToWorldPoint(Input.mousePosition).y
);
// Work out the world position of the chicken
ChickenVector = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y);
// Calculate the distance between them
distance = (ScoopVector - ChickenVector).magnitude;
// If the distance is too far, change the x and y values
if (distance > weaponRange)
{
// The maths
realativeX = (ScoopVector.x - transform.position.x);
relativeY = (ScoopVector.y - transform.position.y);
angle = Mathf.Atan2(realativeX, relativeY);
// New x/y coordinates
ScoopVector.x = weaponRange * Mathf.Sin(angle);
ScoopVector.y = weaponRange * Mathf.Cos(angle);
// Finally apply the position offset from your Chicken
scoop.GetComponent<Transform>().position = ScoopVector + ChickenVector;
}
else
{
// Apply the position (no adjustment needed)
scoop.GetComponent<Transform>().position = ScoopVector;
}
}
Incase this doesnt help, I was thinking of a vague idea you could maybe try, using 'LookAt'. If the scoop was a child of the chicken, and you used 'lookAt' to rotate it with the mouse The local axis of the scoop should move with the rotation:
Then all you need is the distance value you already made to set a local y axis offset some thing like:
if (distance <= Range){
localOffset.y = distance;
}
else{
localOffset.y = Range;
}
Incidentally, there's also a more efficient way to write part of this, trading Atan2() and a Sqrt() for a multiplication and optional Sqrt().
// The main from-to vector
Vector3 playerToTarget = scoopVector - transform.position;
// sqr$$anonymous$$agnitude, for a cheaper calculation when the condition isn't met
if(playerToTarget.sqr$$anonymous$$agnitude > weaponRange * weaponRange)
{
// normalize the from-to vector and multiply by
// weapon range to reset the length of the vector
scoop.position = transform.position + (playerToTarget.normalized * weaponRange);
}
I can´t thank all of you enough, its only been 4 hours and i got my answer, now im going to test the code, and if it works im closing the answer
The scope disapears, I thinks this is due to that is behind the background(i mean the main camera background(because i didn´t add one myself yet) any ideas on how to fix this?
Answer by MUG806 · Feb 16, 2021 at 09:32 AM
Very simple solution for you, as everything posted is overcomplicated:
//calculate the target scope position as before, but store it in a variable
Vector3 targetScopePosition = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,Input.mousePosition.y,-Camera.main.transform.position.z));
//calculate vector from player to scope
Vector3 toScope = targetScopePosition - transform.position;
//limit the distance to the scope to the desired weapon range
toScope = Vector2.ClampMagnitude(toScope, weaponRange);
//use the limited vector to find the correct limited target position
targetScopePosition = transform.position + toScope;
//Set the scope to the target position, but keep its z position so it doesnt get lost behind anything.
scoop.position = new Vector3(targetScopePosition.x, targetScopePosition.y, scoop.position.z);
Assuming you already have your scope in your "scoop" variable and stored the distance limit in "weaponRange"
I still have my last problem Since the cursor its separate from the scope, the cursor(even if not visible) keeps going outside of range, it wouldn be a problem except this means that it takes longer to get inside the circle. I will put a gif to show you(you dont have to solve this, you´ve done more than enough and I wouldn´t have any of the code if not for your answers, but just to let you know) https://answers.unity.com/storage/attachments/176048-ezgifcom-crop.gif
In that case you want to not use the hardware cursor at all, and just add movement to the scope as the player moves the mouse.
You want to remove this line:
Vector3 targetScopePosition = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,Input.mousePosition.y,-Camera.main.transform.position.z));
and replace it with this:
//get the current scope position
Vector3 targetScopePosition = scoop.position;
//add how far the player moved their mouse this frame, multiply it by a sensitivity value, and multiply it by the deltaTime to account for framerate.
targetScopePosition += new Vector3(Input.GetAxisRaw("$$anonymous$$ouse X"), Input.GetAxisRaw("$$anonymous$$ouse Y")) * aimSensitivity * Time.deltaTime;
You will also need to add this to the top of your class so you can tweak the sensitivity in the inspector:
public float aimSensitivity = 1f;
full script ends up looking like this:
public class ScopeAim : $$anonymous$$onoBehaviour {
public Transform scoop = null;
public float weaponRange = 10;
public float aimSensitivity = 1f;
private void Update() {
//get the current scope position
Vector3 targetScopePosition = scoop.position;
//add how far the player moved their mouse this frame, multiply it by a sensitivity value, and multiply it by the deltaTime to account for framerate.
targetScopePosition += new Vector3(Input.GetAxisRaw("$$anonymous$$ouse X"), Input.GetAxisRaw("$$anonymous$$ouse y")) * aimSensitivity * Time.deltaTime;
//calculate vector from player to scope
Vector3 toScope = targetScopePosition - transform.position;
//limit the distance to the scope to the desired weapon range
toScope = Vector2.Clamp$$anonymous$$agnitude(toScope, weaponRange);
//use the limited vector to find the correct limited target position
targetScopePosition = transform.position + toScope;
//Set the scope to the target position, but keep its z position so it doesnt get lost behind anything.
scoop.position = new Vector3(targetScopePosition.x, targetScopePosition.y, scoop.position.z);
}
}
yeah it doesn´t work, the scope doesn´t move with the mouse, it just stays in place