Clamp player movement correctly - c#

I have the following code to clamp player movement. It works but i have a problem. For example if the player is at position -3.05 and if I hold the button to move left the player still moves over the -3.05 limit to about -3.56. Once i let go of the button it bounces back to -3.05. Same goes for the right side. I do not want it to go over the limits no matter what.
Vector3 tmpPos = transform.position;
tmpPos.x = Mathf.Clamp(tmpPos.x, -3.05f, 3.05f);
transform.position = tmpPos;
The following is the way i add movement to the player:
rigidbody.AddForce (movement * speed * Time.deltaTime);

You should not mix up transform operation with rigidbody unless it's marked isKinematic. So instead of transform.position, try clamping rigidbody.position inside of FixedUpdate.
void FixedUpdate(){
Vector3 pos = rigidbody.position;
pos.x = Mathf.Clamp(pos.x, minX, maxX);
rigidbody.position = pos;
}
However, since you're using AddForce to move your object, a much simpler way is to make empty game objects with box collider on the left and right of the object, which then will limit your object movement like invisible walls.

Try using rigidbody.MovePosition(tmpPos); instead of setting transform.position.

I solved my problem. Instead of using the AddForce to move the object
rigidbody.AddForce (movement * speed * Time.deltaTime);
I use rigidbody.position to move the object. I use Mathf.Clamp to limit the movement before applying it to rigidbody.position.

Related

How to make objects rotate the same using transform.rotate in unity

I have several objects that pass through a circular trigger collider, I have made it so when the objects enter the collider they start rotating using transform.Rotate() and when they exit the collider they stop rotating. My problem is that every objects has a different rotation by the time they exit the collider. Is there any way to make them rotate consistently?
void Update()
{
if(rotate==true)
{
transform.Rotate(rotation);
}
direction = (carrot.position - transform.position).normalized;
transform.position += new Vector3(speed * direction.x * Time.deltaTime, speed * direction.y * Time.deltaTime, 0);
}
Here is my code, I simply made it so when the object enters the collider, rotate becomes true and when it exits, rotate becomes false. rotation is a Vector 3 variable that does not change.
You could try rotating the object within FixedUpdate.
This should give you some determinism.

How to use transform.forward that only acknowledges one axis of rotation?

I am making a rolling ball game, and the way I want it to work is based on constant forward movement and rotation based turning.
I'm using force, which then has the ball roll forward.
My Issue here is that I would like the ball to move forward based on where it's "facing". Using Vector3.forward only moves it according to world space and transform.forward will start going backwards because the ball rolls over, upside down.
How can I make it so transform.forward ignores my forward turning, only being effected by the sideways turning?
"forward" is hard to imagine on a sphere.
You add speed when rotating around the X-axis (ball moves "forward")
For direction control, you rotate around global Y-axis.
The transform.forward will spin around the object. But the transform.right (local x-axis so to say) stays stable.
So we only need the Vector3.Cross Product of the transform.right and the global Vector3.Up.
Vector3 forward = Vector3.Cross(transform.right, Vector3.up);
You can use vector math for this. Take the cross product between the local right and the world up:
private static Vector3 GetRollingForward(Vector3 localRight)
{
return Vector3.Cross(localRight, Vector3.up);
}
// ...
void Update()
{
Debug.DrawLine(transform.position, transform.position
+ GetRollingForward(transform.right));
}

Unity: RigidBody2D, how to move GameObject in straight lines (no curves)

Hello all, I'm very new to and very confused by Unity.
I'm creating a top-down, gravity-free test game, similar to PacMan (i.e. think of the movement of characters in straight lines).
Currently, I'm trying to move an object in straight lines (without curvature) (see image).
My GameObject has RigidBody2D attached, as well as Linear, Angular and Gravity set to 0.
I'm currently controlling my GameObject by adding force:
private Rigidbody2D _playerRB2D;
public float _speed;
private void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector2 movement = new Vector2(moveHorizontal, moveVertical);
_playerRB2D.AddForce(movement * _speed);
}
The idea is that the game object won't get to slow down, so is constantly in motion (in straight lines). Collision with objects is obviously important too!
Any help or information to look at will help a lot, thank you!
Unity has a built-in physics engine that calculates movement based on velocity (and collisions, etc.) By using Rigidbody2D.AddForce, you are adding to your rigidbody's velocity. This means that if you press the up arrow and then the right arrow, the velocity from pressing the up arrow remains, causing a diagonal velocity and curved path. If you want straight lines, you can use Rigidbody2D.velocity or just use Transform.translate.
_playerRB2D.velocity = movement * _speed;
Edit: You said that collisions were important, so keep the rigidbody
or remove the rigidbody2D component and use
transform.Translate(movement * _speed);
The idea is basically to reset the force being applied on the rigidBody2D on each changed direction.
In fact, you would have to test if the direction input from horizontal is greater than vertical for x axis, and the inverse for y axis , and thus if it is true, change the opposite to 0f.
You would have normally:
Vector2 movement = new Vector2(moveHorizontal < moveVertical ? moveHorizontal: 0f, moveVertical < moveHorizontal ? moveVertical: 0f);
_playerRB2D.velocity = movement * speed;
Edit: By testing the input value, you can move your RigidBody2D with a analogic controller, and thus being straight as you wished !

How to smooth transform position?

I'm looking for solution to smooth transform position of my object.
To moving to new position I'm using that code
transform.position += Vector3.left * Time.deltaTime * 100f;
The effect of moving is to fast, so I want to make it more smooth. There is any option to change this code for better effect? Like the small bricks in this video when ball destroy big brick
https://youtu.be/mqj7eYna3Ds
You can also use this:
transform.Translate(Vector3.left * Time.deltaTime * 100f);
This should make it a bit smoother. Just remember if you would ad a velocity to the object, Transform.Translate wil not work nice!
if you want more float like movement you can give a Addforce to the attached rigidbody.
rigidbody.AddForce(transform.left * 10, Forcemode.Impulse);
Note: If you use Translate there wil not be any acceleration!
Rigidbody.AddExplosionForce may solve your problem but you cannot put the collision point as the origin. you may have to move your origin of an explosion a little bit below than the collision point. Let me know if it solves the issue.
https://docs.unity3d.com/ScriptReference/Rigidbody.AddExplosionForce.html
Using AddForce or manipulating the velocity variable on the Rigidbody is better if you want smooth movement.
However, if your object doesn't have a rigidbody, then you can just use the functions provided with the Transform class (e.g: Rotate(), Translate(), SetPositionAndRotation())
You can use this block of code to smooth out the movement of the player
public Transform player;
public Vector3 targetPosition;
public float smoothFactor = 2;
void Update()
{
player.transform.position = Vector3.Lerp(player.transform.position, targetPosition, Time.deltaTime * smoothFactor);
}

Move object twoards its rotation

Look into picures its z-axis not ahead so instead on using forward i am using this line of code to translate my object on keys
robotObj.transform.position += Vector3.right * Time.deltaTime * Input.GetAxis("Vertical") * -1;
An this line of code to rotate it.
robotObj.transform.Rotate(0f, Input.GetAxis("Horizontal") * speed, 0f);
but the problem is object is not moving towards it direction
Put an empty gameobject as parent of your robotObj and use the script you made to move the empty gameobject.
But make sure the z-axis is facing the x-axis of the robotObj!
If you want to move your object according to its looking direction (for you it is the red axis), then I would suggest you rotate your object first and then use transform.right as movement direction, like
transform.position += transform.right* Time.DeltaTime * Input.GetAxis("Vertical")
Note: transform.right take the object's local blue axis and projects it into world space (ref: https://docs.unity3d.com/ScriptReference/Transform-right.html)
Note 2: Edited to use transform.right although I would suggest putting your GameObject into another, empty GameObject to achieve the blue axis pointing forward, so you can use transform.forward, as it is more intuitive.

Categories

Resources