So I am making a simple 2d endless mobile game. In the game, the player object (spaceship) moves upwards continuously and then the player can use either left or right to move the player to avoid obstacles.
As a newbie I am finding it very difficult to achieve a very smooth motion in the player movement. I have watched many tutorials including the unity official tutorials about moving an object. They all use simple techniques like:
rigidbody.velocity = (new Vector2 (0.0f, 1.0f)) * speed in the fixedupdate function
or transform.Translate (velocity * Time.deltaTime * speed) in the update function
or rigidBody.MovePosition (rigidbody.position + velocity * Time.fixedDeltaTime) in the fixed update or
just just changing the transform.position over time in the update function.
But none of these techniques or code that I have used have helped me to achieve that very smooth motion in the player movement that I want. No matter what I try I still get lags in the player movement. I have also tried switching the rigidbody.iskinematic on and of and changing the rigidbody interpolation but I am still not able to achieve a smooth movement in in 2d games that we see such as ios games shredd or split the dot. I thought that it might be my computer that was very slow or something that is why I am not getting a smooth movement but I transported my project onto my friends computer which is twice as fast and I still have the same results. I also striped all that decided to erase all the code that is in the player controller scripts and just focus on the code for moving the player but the results has not changed.
I am thinking that it is because I am just using a very simple and inefficient code to move the player or it might have something to do with changing some settings in unity. So the question is what is the most efficient way to achieve a very smooth player movement in unity. (Codebase and unity settings.)
Currently I am just using rigidbody.velocity = (new Vector2 (0.0f, 1.0f)) * speed to move the player and I have made the camera a child object of the player for simplicity.
Thank you.
I would use Vector3.Lerp to interpolate the transform.position. This essentially mathematically smooths out the translation between the two positions.
Something else I've experienced is that the editor is sometimes more laggy than the end product, so I recommend building the game and testing it out to see if that is the case.
Finally, if you are using transform.position to move the object, ensure that the numbers are fairly small. Big numbers obviously make the object jump around a lot more.
Related
I'm currently trying to make a game to put my relatively new coding knowledge to test. I figured I learn a lot quicker by just doing things and seeing what happens. I'm currently working on a plane and the last couple of days I made a functional camera system (to rotate around the player based on the mouse) and some animations of the plane. I'm currently trying to create a movement system in which the down key rotates the player up. I noticed however that my AddForce function doesn't do what I want it to do. I'd like the plane to move in the Z axis depending on the current rotation of said plane instead of it just heading into the Z angle of the world.
I'm currently working on this snippet:
//Acceleration
if (gameObject.CompareTag("Player") && playerRb.velocity.z > -349)
{
playerRb.AddRelativeForce(0, 0, -playerSpeed, ForceMode.Acceleration);
}
else if (gameObject.CompareTag("Player") && playerRb.velocity.z < -349)
{
playerRb.velocity = new Vector3(playerRb.velocity.x, playerRb.velocity.y, -350);
}
//
//Movement
//Up/down controls
if (gameObject.CompareTag("Player") && Input.GetKey(KeyCode.DownArrow))
{
transform.Rotate((0.07f * playerSpeed) * Time.deltaTime, 0, 0);
}
As you can see I already tried AddRelativeForce as another topic mentioned but that doesn't seem to work for me. The moment it hits an edge it just falls down into the abyss regardless of it's rotation.
Additionally, I was considering using another AddForce function on the rotate as it doesn't leave the ground (considering it keeps hitting the floor with its tail), is there any way to apply a force on an object from a specific position/angle? (such as the front of the plane).
Thanks in advance!
I think the reason your plane is acting strange is not because of your addrelative force call -- it's because you are setting velocity. playerRb.velocity = new Vector3(playerRb.velocity.x, playerRb.velocity.y, -350); assigns the velocity to push you -350 in the world's z axis, which probably isn't what you want. Velocity is in the global space. Remove that and see what happens.
On a more general note, If you're using physics, try to use only forces and torquees. Using transform.Rotate to change a rigidbody's rotation while physics is active will just make your life difficult, and make the rigidbody do strange things. I do change the velocity of rigidbodies sometimes, but not in every frame. I just don't know enough about physics to mess with velocities that way.
Also, make sure you're doing these things in a FixedUpdate function, since that is where input that affects physics is supposed to be checked.
I am trying to fire projectiles from a player who is moving at very high speeds. The issue is that the bullets do not seem to inherit the angular velocity. If the player is moving in a straight line at 500 U/s, then the bullet correctly inherits that velocity and adds its own speed onto that:
GameObject bullet = Instantiate(projectile, gun.transform.position, gun.transform.rotation);
bullet.GetComponent<Rigidbody>().velocity = r.velocity + bullet.transform.forward *bulletSpeed;
However, if the player is turning really quickly, it does not inherit the rotational velocity, and the bullet looks like it veers off to the side.
How can I implement this? I tried assigning the angular velocity of the player to the bullet, but this just caused the bullet to spin while moving in the same direction.
Some extra details:
I am using rigidbody.MoveRotation() to rotate my player, but I manually calculated angularVelocity to assign it to the bullet
I tried moving the player with AddTorque(), but could not produce any results with the bullets
The immediate problem is that the projectile isn't part of the physics simulation until the moment you create and launch it, meaning the rotation of the player up to that point will not be able to influence its movement. I suppose this could work if you created the projectile at the start, attached it to the gun with a weak joint, then broke the joint and added to its velocity when it was fired - but it really would be simpler if you just "faked" it.
Applying Circular Motion
This is similar to a classic circular motion example you'd find in a physics textbook. When your bullet travels in a circle around the player (inside the gun), its normal path (if released) would be tangent to the circular path around the player. So when the bullet is fired (and hence released from the circular path), that angular velocity of the player would translate into a linear velocity of the bullet. Here's a simple diagram I put together that represents the situation with a ball on a string, being spun in a circle:
Getting the Tangential Velocity of the Bullet
You don't want to be applying any kind of angular velocity to the projectile after it has been launched - as you saw, this will only spin the projectile on its own axis. Rather, you want to apply an additional velocity vector to the projectile, which is tangent to the rotation of the player (and perpendicular to the facing of the bullet). So how do we do this?
Well, as per this website, the formula for tangential velocity at any point on something spinning in a circle is:
velocity = angularVelocity x radius
A key point to remember is that the angularVelocity is in radians, not degrees.
So, let's put this all together. Here's a general idea of how you might code this:
FireGun() {
// Assumes the current class has access to the rotation rate of the player
float bulletAngularVelocityRad = Mathf.Deg2Rad(rotationRateDegrees)
// The radius of the circular motion is the distance between the bullet
// spawn point and the player's axis of rotation
float bulletRotationRadius =
(r.transform.position - gun.transform.position).magnitude;
GameObject bullet =
Instantiate(projectile, gun.transform.position, gun.transform.rotation);
// You may need to reverse the sign here, since bullet.transform.right
// may be opposite of the rotation
Vector3 bulletTangentialVelocity =
bulletAngularVelocityRad * bulletRotationRadius * bullet.transform.right;
// Now we can just add on bulletTangentialVelocity as a component
// vector to the velocity
bullet.GetComponent<Rigidbody>().velocity =
r.velocity + bullet.transform.forward * bulletSpeed + bulletTangentialVelocity;
}
Hope this helps! It's never a bad idea to read up on some basic kinematics/mechanics when you're working with game physics, since sometimes relying on the game physics is actually more complicated than just devising your own solution.
I am desperately looking everywhere for a solution to this problem but did not find any possibility yet, maybe you can help me out:
I am making a simple test in which a kind of cylinder can rotate itself and moving on a flat platform by friction. I have rigid body, mesh collider attached already and a script to control the rotation. It can be moving fast or slow depends on its rotation speed.
The script is as follow:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour {
public float rollingSpeed;
public float gravity;
// Update is called once per frame
void FixedUpdate()
{
transform.Rotate(rollingSpeed, 0.0f, 0.0f);
GetComponent<Rigidbody>().AddForce(0.0f, -gravity, 0.0f);
}
}
The problem is when I run the Play mode, this cylinder is rotating itself but staying in the same position! (in fact it is moving back and forth very slightly), I really dont know what is the cause, I tried to increase the friction parameters, add physical materials, and even adding a second force downward (like gravity) but it doesnt work.
Can anyone please have a solution for this? Thank you guys so much!
Rotate is just transform eular coordinate without any force, use AddTorque instead for physical movement.
For example,
GetComponent<Rigidbody>().AddTorque(new Vector3(1, 0, 0) * rollingSpeed * Time.deltatime);
Read more, Unity Doc.
To add a tips about basic physics on Unity.
Please remember when you are working with Transform, it means NO physics. You are just changing its position and rotation.
To work with physics, is always Rigidbody.
I know it could be a basic question for Unity developers. But I am struggling to find answers for this problem. I want to move all objects in my game screen based on device acceleration. I only think of 2 possibles solutions:
1st: change the whole world gravity based on device tilt
2nd: apply the forces to all objects or change the velocity of all objects (I tried changing the velocity but the game got lagging)
Is there any good way to make 2D game objects smoothly move based on device tilt?
You can do this by modifying Physics2D.gravity. It will change the gravity of all GameObjects in the scene.
Physics2D.gravity = Input.acceleration * 50; would have worked but because Input.acceleration has low, mid and high values, it wont work. So you can't assign Input.acceleration directly to Physics2D.gravity.
You need to turn on you device then use Debug.Log(Input.acceleration) to view the low, middle and high values of each axis then you can use if statement and temporary Vector2 value to get what 2D value to assign to Physics2D.gravity.
Also for any GameObject you want the accelerometer to affect more, less or not at-all, you can modify the RigidBody Gravityscale of that GameObject.
The gravity applied to all rigid bodies in the scene can be changed by setting Physics2D.gravity.
Note: Make sure you also set rigidbody.useGravity = true (for gravity to affect the objects).
Example:
Physics2D.gravity = new Vector2(x, y);
Physics.gravity Unity API
Input-acceleration Unity API
Place this in the update() block of any element.
Physics2D.gravity is a "global" value that takes a Vector2 for value.
Debug.Log(Input.acceleration);
Physics2D.gravity = new Vector2(Input.acceleration.x*1.5f, Input.acceleration.y*1.5f);
(You may edit/remove the multiplying floats in each input acceleration property, I added them just for some exponential gravity speed.)
Note:
This will impact all the rigidbodies.
I'm developing a 2.5D mobile game with Unity. In order to move the character back and forward I'm using a piece of code inside the update function:
void Update () {
if (shouldMove==true){
transform.Translate(Vector3.forward * 3 * Time.deltaTime);
}
}
So that code works pretty well when the game is running at 60 fps, but when the fps go down to 30 or less, the character starts to vibrate while moving. I've tried to test the same code with a plane terrain and it worked well, so maybe the problem is the collision between the character's and the terrain's colliders. However, I don't understand why if the fps are high it works well. I've tried both capsule collider and a mesh collider but no one has worked. What do you think? Should I try to use another code?
Edit 1: I'm using a capsule collider and a rigidbody. Should I use a Character Controller?
Sam Bauwens is absolutely right in his response, however, this issue normally is caused due to an excess of objects (specially those which are animated). This can worsen the performance a lot.
You should try to delete some of the objects and try if your character still vibrates. If it doesn't, that means that I'm right. Of course, you won't want to delete objects of your scene, so, you can add an asset such as SmartLOD that deletes the geometry of those objects that are not shown on screen and thus enhances your game's performance.
Hope it helps.
I had a similar problem with a ball that vibrates on the ground. It was caused by gravity which is pulling the gameobject towards the ground, then it collides on the ground and bounces. If your problem is the same as me, you have to either tune the Fixed Timestep (Edit => Project settings => time) and/or Bounce Threshold (Edit => Project Settings => Physics).
By increasing Bounce Threshold, you're going to increase the minimum speed below which an object won't bounce, so that the force of gravity won't be big enough to make the ball's velocity exceed the bounce threshold.
By reducing Physics time step, you reduce the impact of gravity for each time step because the time steps are smaller and therefore the amount of velocity added to the gameobject for each timestep is smaller.
EDIT: you can also look at sleep velocity (Edit => Project Settings => Physics), because if it is higher that the gravity velocity, the object shouldn't vibrate.