Top down acceleration and deceleration using quartic easing curve - c#

I've tried to figure out a good way to do this for a while now and decided I would bite the bullet and ask.
I've been moving my character around using this code snippet:
Vector2 desiredVelocity = input.movementAxis * Mathf.Max(stats.movementSpeed.Value, 0f);
float maxSpeedChange;
if (input.movementAxis != Vector2.zero)
maxSpeedChange = acceleration;
else
maxSpeedChange = deceleration;
velocity.x = Mathf.MoveTowards(velocity.x, desiredVelocity.x, maxSpeedChange);
velocity.y = Mathf.MoveTowards(velocity.y, desiredVelocity.y, maxSpeedChange);
It uses Unity's MoveTowards function to cause the character to accelerate and decelerate. However, MoveTowards is built off of Lerp, and I don't want to use a basic Lerp function for the acceleration curve. I want to try a quartic curve and see how that feels but I have no idea how to integrate that into this setup. Is there some way I could modify my code to allow for this? Ideally I don't want any more variables outside this scope if it's possible.
Thanks!

Related

From to Rotation Glitching My Character Controller

So I am making a character controller which uses Quaternion.FromToRotation to align the player with the gravity center in this piece of code:
this_body.transform.rotation *= Quaternion.FromToRotation(this_body.transform.up,gravity_up);
And when I am on certain parts of the sphere planet it starts flipping out everywhere, like in this video, and I don't know how to remedy this, although maybe the gravity implementation could be the problem, or the character controller, although I think using relative force should not mess with it.
Gravity Implementation:
float distance = direction.magnitude;
float forceMagnitude = G * (obj.GetComponent<MultiAttractor>().rb.mass * rb.mass) / Mathf.Pow(distance, 2);
Vector3 force = direction.normalized * forceMagnitude;
rb.AddForce(force);
My character controller script is a bit long so I don't think I should bore you with it, although if needed I could provide it.
This is for anyone who is having issues with using Quaternion.FromToRotation with a rigid body character controller:
I did not dig much into your problem but you are manipulating the rotation directly in the code with Quaternion.FromToRotation and also with physics. I think you need to stick to one of the two, because using both might lead to unexpected behaviours. If you introduce a "raw" rotation modification, the physics engine deals with it. – rustyBucketBay
Basically just use physics rotation like Rigidbody.rotation for rotating things like Transform.Rotate or if you want to rotate physics objects like you are adding force, but instead of moving things it rotates things, then use Rigidbody.AddTorque, or just don't use any physics rotations with other types of rotation as it can cause problems, as stated by rustyBucketBay

flutter why do I need to subtract an object's position from another object's position to find direction?

I am playing around with cubes and making a box aim at a cube in unity, but to use quaternion.LookRotation I need to subtract the long box's position from the cube's position, I don't get why. What if I just use quaternion.LookRotation with the cube's position.
void Update()
{
Vector3 directionToFace = cube.position - transform.position;
transform.rotation = Quaternion.LookRotation(directionToFace);
// Idk why but this line worked too : transform.rotation = Quaternion(directionToFace);
}
When I use just the cube's position to aim at, it aims slightly higher but when I subtract it it aims exactly at the cube, and also what's the use of using Quaternion.LookRotation, using just Quaternion works fine too.
cube.position - transform.position is a direction (actually a verctor .. a direction usually is additionally normalized) from your transform.position towards the cube.position.
Only using the cube.position would rather be a direction from the World's origin 0,0,0 towards the cube.
So in case your transform.position is coincidentally currently placed on (or close to) 0,0,0 anyway it might result in (almost) the same direction.
But using cube.position - transform.position is correct in a general usage regardless of if your transform.position matches exactly the world origin 0,0,0.
Unless you have your own implementation of a method called Quaternion taking a Vector3 as parameter your given code would not even compile with Quaternion(directionToFace).
There is no such method we know about.
Also the constructor of Quaternion does not take a Vector3. So it also wouldn't compile if you used new like
transform.rotation = new Quaternion(directionToFace);

How to make a 2D real-time Strategy camera controller in unity?

I have been looking around for ages about how to do a Real-time Strategy camera for Unity in 2D. What I mean is that you should be controlling the camera with W, A, S, D and where ever I look its only 3D. I have been trying to write my own scripts but the camera never works and I am in dire need for help. I have tried so much but as a beginner on Unity, I really need help with this. If you can give me anything about how to get started in this matter I will be so happy.
Do you think I should use the Force method or that I should use another one that unity already has installed? I also tried using vectors but when I looked around everyone was using Vector 3 which only is for 3D unity.
You can attach a single script to your camera.
public float speed =10.0f;
void Update()
{
Vector3 a = transform.position
if(Input.GetKeyDown("W"))
{
a.position.y += speed *Time.deltaTime
}
if(Input.GetKeyDown("S"))
{
a.position.y -= speed *Time.deltaTime
}
transform.position =a;
}
You can adjust the speed to your needs. You can do this for other keys. Note GetKeyDown is called when a key is being held down. Hope this helps.
Make a direction vector with Vector3 direction = new Vector3();
Manipulate the vector in the directions you want, based on the key:
if (Input.GetKey(KeyCode.A))
direction += Vector3.left;
Adding the "built-in" Vector3.left will point the direction of the vector to the left, and you can add the other keys on top of that to get a final direction.
Then you can use transform.Translate() to move the gameObject (in this case you attached it to your camera) by passing the direction you calculated based on the keys being pressed as a parameter. Then multiply to get direction * speed * Time.deltaTime;

Unity 2D launch gameObject at a specific angle without affecting speed

I am working on a game where i need to shoot the ball at an angle and power defined by 2 sliders (1 angle slider, 1 power slider). I currently have this code to control the launching of the ball:
public void shoot()
{
float angle = angleSlider.GetComponent<Slider>().value;
float power = powerSlider.GetComponent<Slider>().value;
gameObject.SetActive(false);
ball.GetComponent<Rigidbody2D>().simulated = true;
Vector2 releaseVector = Quaternion.AngleAxis(angle, transform.up) * transform.forward;
ball.GetComponent<Rigidbody2D>().velocity = releaseVector * (power/3);
}
with this current code it works almost perfect apart from one thing. When the angle is like between 30 and 60, the ball is launched well but if i set it to 0 degrees the ball would barely move and on the contrary if i set it to 90 degrees, the ball launches with much more power. How can i set a constant speed for all degrees so that the speed is only affected by the power slider only please? Thanks.
Typically, you shouldn't set the velocity of a rigidbody directly. Per the Unity docs...
In most cases you should not modify the velocity directly, as this can result in unrealistic behaviour.
Instead, you usually want to impart a physical impulse to the ball using an API like AddForce or AddRelativeForce
That is easy.. You have to normalize the releaseVector.
ball.GetComponent<Rigidbody2D>().velocity = releaseVector.normalized * (power/3);
Then adjust the power to what you want. That way you will have the direction u wanted and speed depends on the power value.
If you want to know what normalize do, you can find more information here;
https://docs.unity3d.com/ScriptReference/Vector3.Normalize.html

Unity 2D scripted friction equation

I am working on the friction for a square object for after it is done being pushed by the player. The block's movements are controlled purely through script using transform.Translate(velocity) each frame and only a boxcollider2D. I am speculating that because i am controlling the block's movements each frame manually is the reason i can't seem to get the boxcolliders2D's physics material 2D friction to work.
Basically, I am trying to recreate the built in physics similar to rigidbodies by using transform.translate, or use the built in physics if possible. So far, i've landed on something like this
newVelocity.x -= ( 1 / (newVelocity.x * newVelocity.x));
In an attempt to reduce the velocity.x each frame until it hits 0 and shorts out. Obviously, this falls apart when the velocity.x becomes a decimal number. I'm stumped on what i should be doing to achieve a friction similar to rigid bodies where it slows down a little at first and then much faster towards the end as it stops. Any and all help appreciated, thanks in advance!
You could compare the signs of the velocity before and after calculating the change in velocity, and set the velocity to zero when the sign changes, like so:
newVelocity.x -= ( 1 / (newVelocity.x * newVelocity.x));
if(Mathf.Sign(previousVelocity.x) != Mathf.Sign(newVelocity.x)) {
newVelocity.x = 0f;
}
One thing, though, is that normal friction is not calculated using the above equation, it's calculated as follows:
newVelocity.x -= frictionCoefficient*Time.fixedDeltaTime;
And with this, you wouldn't need to compare the velocity to the previous velocity as you can just say if the velocity is low, it's zero. You could still compare the previous velocity sign stuff if you wanted to though, but this is probably more efficient
if(newVelocity.x < 0.01f) {
newVelocty.x = 0f;
}

Categories