moving 2d object unity - c#

I have 1 year experience of coding in C++ , but just yesterday i've started learning Unity.I saw it needs C# so this won't be too different.Right now , I am trying to move a 2d object , but i really want to understand how it works and not just copy some lines of code.So , this is how they do it :
//
float horizontal = Input.GetAxis("Horizontal");
//which i assume gets the x coordonate of my object;
myRigidBody.velocity = new vector2(horizontal , myRigidBody.velocity.y);
//
And i don't think i get the idea of this code.I read that velocity takes 2 values (x,y) but i am not quite sure what it is doing with them.And getAxis takes a value from [-1,1] which i also don't understand.If you could help me i'd be grateful.

Input.GetAxis("Horizontal"); returns the current value for the axis named Horizontal as defined in Unity's Input manager.
Also, new vector2(horizontal, myRigidBody.veloicty.y); is probably a typo, because the type of Rigidbody.velocity is Vector3. And Vector2 is an object that has an implicit conversion to Vector3.
Anyway, myRigidBody.velocity = new Vector2(horizontal , myRigidBody.velocity.y); creates an instance of a Vector2 type where the x component is horizontal, and the y component is the current y component of the rigidbody's velocity, and then it assigns that Vector2 to the rigidbody's velocity.

GetAxis("Horizontal") returns the values from left (-1,0,0) and right (1,0,0) when you press the arrows keys. Anyway, you'll get the values interpolated and not a sudden change. Try the code below and see how it looks on the inspector
public float horizontal;
private void Update()
{
horizontal = Input.GetAxis("Horizontal");
}
As for the velocity, you "force change" the velocity of the rigidbody in any direction you want x,y (horizontal,vertical axis). You can also multiply your axis values with a speed variable.

Related

Unity 3D - How to gllobaly rotate one object based on second

I have got a very large problem with rotation in Unity. What I want:
I have two 3D objects. Just one is for player manipulating, second object Transform.rotation and Transform.position is dependent on object number one with scale of 1/10. It means if I will move first object from (0,0,0) to (10,30,90) then obj.2 will move from (0,0,0) to (1,3,9). It's simple. But I have got LARGE problem with rotation.
I can't make rotation on normal transform because it's based on "local position".
Below I present my problem with simplest 2D object situation:
As you can see when I rotate red object +90 degrees the second object rotate +9 degrees and the axes become different in relation to the world. After more transformations in 3D world it make a large mess. For example after some transformations if I will want to rotate 3D object from me (like using accelerator on motocycle) on first make second object rotating from left to right (because it's based on object axis).
Of course using Transform.Rotate instead of Transform.localRotate (or Transform.EulerAngles instead of Transform.localEulerAngles) is not a solutions because it's means only if objects are childrens (it this this case are not).
WHAT I FOUND:
Using Transform.Rotate(Xdegree,Ydegree,Zdegree, Space.World) is solution for rotating second object !
What I need:
Xdegree, Ydegree and Zdegree from first (manipulated by player) object.
Transform.EulerAngles and Transform.Rotation DOESN'T work because it's returns "local objects" rotations.
So... I know that if 3D obj.2 rotation is (0;30;0) and i use obj2.Rotate(45,0,0) then the obj.2 rotation will be (~37.76;~39.23;~26.56) and it's okay. But I dont know how to convert the other way (from "local" rotation XYZ to degrees that I can use on Transform.Rotate() (of course I will divided this values (xyz) by 10 at the end because I have got 1/10 moving scale))
If you need one GameObject to have 1/10 of the rotation and position of another, you could use something like:
//the player-controlled cube
public Transform t1;
//the 1/10 cube
public Transform t2;
void Update(){
//set the position of t2 to 1/10 of the position of t1
t2.position = 0.1f * t1.position;
//get the axis and angle of t1's rotation
t1.rotation.ToAngleAxis(out float angle, out Vector3 axis);
//t2 should be rotated in the same direction (axis), but with 1/10th of the angle
t2.rotation = Quaternion.AngleAxis(angle * 0.1f, axis);
}
Edit: To allow resetting delta rotation and changing targets, you could do something like this. Note: this glitches when it wraps more than a full circle, I'm not an expert on Quaternions so you'd have to figure it out yourself.
//the player-controlled cube
public Transform t1;
//the 1/10 cube
public Transform t2;
private Vector3 t1originalPosition;
private Quaternion t1originalRotation;
private Vector3 t2originalPosition;
private Quaternion t2originalRotation;
void Start()
{
ResetTarget(t1);
}
void Update()
{
if (t1 != null)
{
//set the position of t2 to 1/10 of the position of t1
t2.position = t2originalPosition + 0.1f * (t1.position - t1originalPosition);
Quaternion t1Rotation = t1.rotation * Quaternion.Inverse(t1originalRotation);
//get the axis and angle of t1's rotation
t1Rotation.ToAngleAxis(out float angle, out Vector3 axis);
//t2 should be rotated in the same direction (axis), but with 1/10th of the angle
t2.rotation = Quaternion.AngleAxis(angle * 0.1f, axis) * t2originalRotation;
}
}
public void ResetTarget(Transform target = null)
{
t2originalPosition = t2.position;
t2originalRotation = t2.rotation;
t1 = target;
t1originalPosition = t1.position;
t1originalRotation = t1.rotation;
}
Use quaternions instead of the euler angles (xyz rotation angles). And simply give the global rotation value (quaternion) of one object to the other.
To add together quaternions, you just multiply them together.

Unity 3D Make Objects Follow Player

I am trying to make objects follow player with offset without delay on Z-axis but delayed on X-axis. When player entered a object(coin) trigger, i am adding this object to a list and i am updating each one’s position using this code. Each coin has previous and next coin that current coin follows.
{
foreach (Coin coin in coins)
{
Vector3 desiredPos = new Vector3(
coin.previous.transform.position.x,
coin.previous.transform.position.y,
coin.previous.transform.position.z + .15f);
Vector3 smoothedPos = Vector3.Lerp(
coin.transform.position,
desiredPos,
smoothness);
coin.transform.position = smoothedPos;
}
}
I want to get this result
https://youtube.com/shorts/PHAg8Pqf0mA?feature=share
This is what i got
https://youtube.com/shorts/fzukzL_0r74?feature=share
But as you can see coins struggling some times. It is not updating their positions properly. I dont want to make it child because i need to move them on x-axis with delay.
I’ll be appreciated if you can help me.
You are using Vector3.Lerp which lerps all x y and z. If you want to lerp only on x axis, you should use Mathf.Lerp on the x instead:
var x = Mathf.Lerp(x, desiredPos.x, smoothness);

How do I make Rigidbody2D.MovePosition move a gameobject in local space?

I found a way to find what the title says for Rigidbody but not for Rigidbody2D, since the original method involves using Transform.TransformDirection(), which only functions on Vector3 while Rigidbody2D.MovePosition functions on Vector2. I essentially need a bullet to move forward, with two more bullets moving forward but rotated at a 45 degree angle difference.
How would i go about doing this?
Your question reminded me of a game I made for a game jam a while ago so I checked the code, and it seems I used Quaternion.AngleAxis to rotate the bullets.
I'm assuming you have a reference to the prefab you want to clone (in this example, it's projectilePrefab), as well as a firePoint Transform that represents the position you want to shoot from and the rotation of the middle projectile.
// Middle Bullet
GameObject mBullet = Instantiate(projectilePrefab, firePoint.position, firePoint.rotation);
var mRb = mBullet.GetComponent<Rigidbody2D>();
middleRb.AddForce(mRb.transform.up * velocity, ForceMode2D.Impulse);
// Left Bullet
GameObject lBullet = Instantiate(projectilePrefab, firePoint.position, firePoint.rotation);
// Rotate here
lBullet.transform.up = Quaternion.AngleAxis(-45, Vector3.forward) * firePoint.transform.up;
var lRb = lBullet.GetComponent<Rigidbody2D>();
lRb.AddForce(lBullet.transform.up * velocity, ForceMode2D.Impulse);
// Right Bullet
GameObject rBullet = Instantiate(projectilePrefab, firePoint.position, firePoint.rotation);
// Rotate here
rBullet.transform.up = Quaternion.AngleAxis(45, Vector3.forward) * firePoint.transform.up;
var lRb = lBullet.GetComponent<Rigidbody2D>();
lRb.AddForce(lBullet.transform.up * velocity, ForceMode2D.Impulse);
Let me know if you run into any issues with this code, I can't test it right now.
I'm assuming you have a bullet prefab, and that you are instantiating 3 bullets at once, but want 2 of them to be at -45 and 45 degrees respectively.
//bullet is whatever prefab you have
var bl = Instantiate(bullet);
var bl = Instantiate(bullet);
bl.transform.rotation = //Set rotation here to 45 deg
var bl = Instantiate(bullet);
bl.transform.rotation = //Set rotation here to -45 deg
Between Vector2 and Vector3 exists an implicit conversion and vise versa. Both types can more or less be used exchangeable which will either create a Vector3 where z is simply 0 or create a Vector2 only using the x and y and simply ignoring the z.
You can simply pass a Vector3 as parameter to Rigidbody2D.MovePosition and it will implicitly convert it to a Vector2 ignoring the Z component.

Stabilize object on one axis only

i am trying to stabilize my object to not fall aside. This code works pretty good, but it also stabilize the object to not fall forward or backward.
Is there any possibility to restrict this to only one axis?
var deltaQuat = Quaternion.FromToRotation(_rBody.transform.up, Vector3.up);
deltaQuat.ToAngleAxis(out var angle, out var axis);
_rBody.AddTorque(-_rBody.angularVelocity * 2f, ForceMode.Acceleration);
_rBody.AddTorque(axis.normalized * angle * 5f, ForceMode.Acceleration);
Use the contrints in the rigidbody component:
As I understand your goal is to constraint the rotation on a certain local axis.
You could probably do it somewhat similar to this post just not for positions but rotations going through Rigidbody.angularVelocity.
// get the angularVelocity but in local space relative to the current rigidbody orientation
var localAngularVelocity = Quaternion.Inverse(rigidbody.rotation) * rigidbody.angularVelocity;
// get the euler space representation
var localAngularEulers = localAngularVelocity.eulerAngles;
// now constraint according to your needs e.g. on the local forward axis
localEulerAngles.z = 0;
// now convert back and assign
rigidbody.angularVelocity = rigidbody.rotation * Quaternion.Euler(localAngularEulers);
Note: Typing on smartphone so can't test it right now but I hope the idea gets clear

Why does Physics2D produce different results for AddForce() versus velocity?

Why does Gravity in Physics2D engine for Unity2D act different when these two following lines of codes are implemented alternately?
For example, I have attached to my player sprite a Player Controller C# script:
private float speed = 500f;
RigidBody2D playerChar = null;
And then to make my character walk:
Vector2 vec = new Vector2 (Input.GetAxis("Horizontal"), 0);
playerChar.AddForce(vec * speed);
And the Gravity is set to 50
Result 1: My character avatar falls down normally.
Meanwhile when I do:
Vector2 vec = new Vector2 (Input.GetAxis("Horizontal"), 0);
playerChar.velocity = (vec * speed);
And the Gravity is still set to 50
Result 2: My character now takes a long time to fall (it slowly "floats" down).
Why is that?
This is because you're forcing the y component of the rigidbody's velocity to zero.
When you add force, it adds, it doesn't replace.
When you set the velocity, you're specifically setting it to a Vector2 that has a y value of 0, gravity then kicks in on the fixed update cycle and adds a small amount of gravity, causing your player to fall slowly. Then Update happens again and you force the y value back to 0 once more.

Categories

Resources