Gravity not working in unity RigidBody 2D transform - c#

I made sprite and applied rigidbody 2d component, it's working fine as it should, now i wrote this piece of code but, when i start playing the game it working for some period of time but after that, gravity seems be null, means my rigidbody does not come down when i leave the keys
// Update is called once per frame
void Update () {
if (Input.GetKey (KeyCode.LeftArrow)) {
posX--;
} else if (Input.GetKey (KeyCode.RightArrow)) {
posX++;
}
if (Input.GetKey (KeyCode.UpArrow)) {
posY++;
} else if (Input.GetKey (KeyCode.DownArrow)) {
posY--;
}
angle -= Input.GetAxis ("Horizontal");
angle = Mathf.Clamp (angle, -10, 10);
}
void FixedUpdate()
{
transform.eulerAngles = new Vector3 (0,0,angle);
transform.position = new Vector2 (posX * Time.deltaTime, posY * Time.deltaTime);
}
}
what i want to do is move the helicopter left right up and down(which user can control) but when user is not interacting, i want gravity to work as default and helicopter will come down due to gravity, how to achieve that?

You are overwriting the position on every frame, so it doesn't meter what Unity calculates on its physics, you overwrite when you do this:
transform.position = new Vector2 (posX * Time.deltaTime, posY * Time.deltaTime);
I don't know what you want to achieve, but maybe it will work if after this you re-apply a gravity force with traforme.AddForce(), using the object's mass and the gravity acceleration constant.

You should use AddForce instead of Changing x and Y axes.
You can see the example here,
AddFource Example

Related

Unity Simple Character Controller Script not working as expected

Im scratching my head over this one, really cant figure it out.
Im trying to implement the player movement from this example:
https://www.youtube.com/watch?v=LNidsMesxSE
Starts at minute 4:25 and ends at minute 5:20
This script tries translating all that to unity.So I started all the way over from scratch and just want to make a simple movement script.
You can plug this into any Unity version, throw the script onto and object with a CharacterController component, add a child object with a mesh that will tilt, the main object will rotate around its Y axis and move.
I do recommend using a simple T pose character or atleast a long capsule so you can better see what is happening than when you would be using a cube to test this.
The weird glitches im having is that the object randomly spasms out even though im always only adding extremely small rotations and movements every frame. And 95% of the time it doesnt happen, so I havent been able to pinpoint exactly what is causing this.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterMove : MonoBehaviour
{
public float speed = 200f;
public float rotationSpeed = 180f;
public float tiltFactor = 8f;
public bool normalizeVelocity = false;
CharacterController cc;
Vector3 velocity;
Transform armatureBody;
void Start()
{
cc = GetComponent<CharacterController>();
armatureBody = transform.GetChild(0);
}
void Update()
{
velocity = new Vector3(Input.GetAxis("Horizontal"), 0,
Input.GetAxis("Vertical"));
}
void FixedUpdate()
{
if ((velocity != Vector3.zero))
{
var ccVelocity = cc.velocity; // CharacterController velocity. This might be the problem, but without it I cannot rotate the object towards the actual forward velocity.
Quaternion toRotation;
toRotation = Quaternion.LookRotation(ccVelocity, Vector3.up);
transform.rotation = Quaternion.RotateTowards(transform.rotation, toRotation, rotationSpeed * Time.deltaTime);
if (Input.GetKey(KeyCode.S)) print("new toRotation: " + toRotation);
armatureBody.localEulerAngles = new Vector3(velocity.z * tiltFactor, 0, -velocity.x * tiltFactor); // Tilt Body towards velocity This causes the weirdest and most consistest twitching bugs when the tilt is backwards so the object is moving backwards, maybe because im using LookRotation to look backwards?
}
velocity = Quaternion.Euler(0, transform.eulerAngles.y, 0) * velocity; // forward is always forward
cc.SimpleMove(velocity * Time.deltaTime * speed);
}
}
This script does 4 things,
get the velocity from player input.
rotate the main Object(this script) towards the velocity
add tilt towards the velocity, to the child armatureBody, this is a t Pose character in my case.
move the main Object this script is on.
Any help would be appreciated.
I tried removing the vector3 != Zero check, I tried normalizing the vectors, and I tried using a different Quaternion rotation method, but all with the same faulty results.
Check in Update() if Input.forward > threshold if so rotate to velocity. Dont rotate to velocity when only going sideways or backwards, so we can now strafe sideways and walk backwards when standing still or run and rotate to our velocity with the AD keys when running.
void Update()
{
velocity = new Vector3(Input.GetAxis("Horizontal"), 0,
Input.GetAxis("Vertical"));
if (velocity.z > 0.2f)
{
forwardVelocityThreshold = true;
}
else forwardVelocityThreshold = false;
}
Then in our FixedUpdate() we check for that bool and apply the rotateToVelocity if true.
Adjust the following if statement:
if (ccVelocity != Vector3.zero && forwardVelocityThreshold)
{
toRotation = Quaternion.LookRotation(ccVelocity, Vector3.up);
transform.rotation = Quaternion.RotateTowards(transform.rotation, toRotation, rotationSpeed * Time.fixedDeltaTime);
}
Now it works as intended, I also changed the deltaTime to FixedDeltaTime as suggested by Voidsay in the comments, although I have heard conflicting things about this. Some say FixedUpdate always uses fixedDeltaTime even if you are using deltaTime, other say no, always use fixedDeltaTime in FixedUpdate.

How to cap velocity in Unity 3D using AddForce with ForceMode.VelocityChange

I am working on a player controller and having trouble with limiting the character's velocity. The character seems to accelerate indefinitely.
I am updating the character's velocity using rb.AddForce(movement * movementSpeed, ForceMode.VelocityChange), where movement is a normalized Vector3 (with values only for x and z) and movementSpeed is a public float giving the desired movement speed. I realize that it would be trivial to cap the character's velocity by setting it directly but I'm under the impression that setting rb.velocity directly is bad practice (which I'm not entirely sure is true).
My fixed update function:
private void FixedUpdate()
{
Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
movement.Normalize();
rb.AddForce(movement * movementForce, ForceMode.VelocityChange);
}
I have tried adding a conditional statement checking if the velocity is greater than the desired maximum and, if true, adding a force in the opposing direction. This results in stuttering. The character's velocity is reset to 0 and forced to accelerate again.
Vector3 currMovement = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
float currMagnitude = currMovement.magnitude;
if (currMagnitude > movementSpeed) {
rb.AddForce(currMovement * (-1 * movementSpeed / currMagnitude), ForceMode.VelocityChange);
}
Any help would be greatly appreciated?
TL;DR
How to cap velocity when using rb.AddForce(movement, ForceMode.VelocityChange)?
Do I even need to use rb.AddForce or can I directly set rb.velocity?
I don't see anything wrong with setting the velocity directly, especially when it comes to capping velocity. I think people tend to visualize velocity better when they're adding a force in a direction rather than directly setting it, but no, in short, I don't think it's bad practice.
Have a look at Unity's Mathf.Clamp documentation. I'd do something like:
private void FixedUpdate()
{
Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
movement.Normalize();
rb.AddForce(movement * movementForce, ForceMode.VelocityChange);
rb.velocity = new Vector3(Mathf.Clamp(rb.velocity.x, -SomeMaximumVelocity, SomeMaximumVelocity),
rb.velocity.y,
Mathf.Clamp(rb.velocity.z, -SomeMaximumVelocity, SomeMaximumVelocity));
}

Unity C#: Issue with rotating, now facing wrong direction

I have a character/rigidbody and 'she' can turn around. When I press Play in Unity, if I move forward/backward, that's fine, she moves forward/backward. It's a good start.
But then if I turn her left or right, then go forward/backward, she now moves sideways.
She is a rigidbody component set as a parent in the scene.
Surely it's not difficult to do, but I can't figure out how to set her rotation so that when she turns, she will move 'forward' when I press the button to move her forward! There are plenty of first-person-shooter games where you can turn and move 'forward' and the player goes in the correct direction.
My rotation script at the moment is this:
Vector3 EulerAngleVelocity;
public float rotateSpeed = 250.0f;
void Update() {
if (Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.DownArrow))
{
MoveVector = PoolInput();
Move();
}
if (Input.GetKey(KeyCode.RightArrow))
{
EulerAngleVelocity = new Vector3(0, rotateSpeed, 0);
Quaternion deltaRotation = Quaternion.Euler(EulerAngleVelocity * Time.deltaTime);
rigidbody.MoveRotation(rigidbody.rotation * deltaRotation);
}
}
private void Move()
{
rigidbody.AddForce((MoveVector * moveSpeed));
}
private Vector3 PoolInput()
{
Vector3 dir = Vector3.zero;
dir.x = joystick.Horizontal();
dir.z = joystick.Vertical();
if (dir.magnitude > 1)
dir.Normalize();
return dir;
}
You're moving your joystick and adding that direction in relation to the WORLD instead of in relation to your player. If you want to add force relative to the orientation of the RigidBody probably what you want to use is rigidBody.AddRelativeForce (documentation) instead of simply rigidBody.AddForce.
Your problem isn't your rotation code, it's your movement code. You're applying a motion in world-space, not local-space ('object'-space).
For example, if you're using Vector3.Forward, you will want to use transform.Forward instead.

Camera shaking on rotating player while crouching in unity

I am having a problem with the camera following the player. When the player moves, the camera shakes and this effect is more noticeable when the player is in the crouched position. I am using root motion for the player with animations by mixamo.
Player Script:
Transform cameraT;
void Start () {
cameraT = Camera.main.transform;
}
void FixedUpdate ()
{
float sideMotion = Input.GetAxis("SideMotion");
float straightMotion= Input.GetAxis("StraightMotion");
if (Mathf.Abs(sideMotion) > 0 || Mathf.Abs(straightMotion) > 0)
{
transform.eulerAngles = new Vector3(transform.eulerAngles.x,
cameraT.eulerAngles.y);
}
}
Camera Script:
public float distanceFromPlayer=2f;
public float mouseSensitivity=6;
public Transform player;
public Vector2 pitchConstraint= new Vector2(-30,80);
Vector3 rotationSmoothVelocity;
Vector3 currentRotation;
public float rotationSmoothTime = 0.2f;
float yaw; //Rotation around the vertical axis is called yaw
float pitch; //Rotation around the side-to-side axis is called pitch
private void LateUpdate()
{
yaw += Input.GetAxis("Mouse X") * mouseSensitivity;
pitch -= Input.GetAxis("Mouse Y") * mouseSensitivity;
pitch = Mathf.Clamp(pitch, pitchConstraint.x, pitchConstraint.y);
currentRotation = Vector3.SmoothDamp
(currentRotation, new Vector3(pitch, yaw), ref rotationSmoothVelocity, rotationSmoothTime);
transform.eulerAngles = currentRotation;
transform.position = player.position - transform.forward * distanceFromPlayer;
}
For public transform I just added an empty game object to player chest level and parented it to the player. I got the rotating camera smoothly trick from an online tutorial but that exact thing won't work on player rotation though.
A character controller is attached to player without any rigidbody or collider.
You are going to want to use Lerp on the camera in order to smooth its motion from one position to another. The Scripting API has a good example of Vector3.Lerp.
So in your case, you could add a public variable for smoothing position as well. Something like positionSmoothTime. Then make a "Desired Position" variable, we'll call it destPosition.
Vector3 destPosition = player.position - transform.forward * distanceFromPlayer;
transform.position = Vector3.Lerp(transform.position, destPosition, positionSmoothTime);
This should effectively smooth it to where the stuttering should go away. Another thing that will help that someone else mentioned is using a part of the body that moves less (Like the head) as the target. This combined with the Lerp function will give you a smooth camera movement.
Another large help would be to move things into the Update() function. The reason being is FixedUpdate() doesn't get called every frame. So you could potentially get stutter as a result. If you move everything into Update() it will update every frame and help smooth things out. If you do this though you will need to multiply all movement by Time.deltaTime as shown in the example below.
Vector3 destPosition = (player.position - transform.forward * distanceFromPlayer) * Time.deltaTime;
For more examples, check the links to each function to see Unity's documentation on it. It has examples of everything I've shown here.

Change Character Direction While Jumping

I'm making a 2D platformer and I followed a tutorial to build my character. This character works fine except that when jumping, it doesn't allow for changing direction midair. How can I add to this to make my character able to change direction mid-jump?
The code used for the basic movement is below:
void Update()
{
CharacterController controller = GetComponent<CharacterController>();
float rotation = Input.GetAxis("Horizontal");
if(controller.isGrounded)
{
moveDirection.Set(rotation, 0, 0);
moveDirection = transform.TransformDirection(moveDirection);
//running code
if(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) //check if shift is held
{ running = true; }
else
{ running = false; }
moveDirection *= running ? runningSpeed : walkingSpeed; //set speed
//jump code
if(Input.GetButtonDown("Jump"))
{
jump();
}
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
EDIT: Forgot to include the code for jump(), that's probably kind of important...
void jump()
{
moveDirection.y=jumpHeight;
transform.parent=null;
}
You are updating the moveDirection vector only when the character is grounded:
if(controller.isGrounded)
when player jumps isGrounded is set to false, so moveDirection won't be updated (except for gravity).
I suppose you don't want to affect the velocity of the character while is jumping (unless it is supposed to fly or walk in the air). I guess you want to change its orientation while it's jumping, so you can directly modify transform making it rotate accordingly to your input.
Something like:
else
{
float amountOfRotation = Input.GetAxis("...") * rotationScaleFactor;
transform.RotateAround(transform.position, transform.up, Time.deltaTime * amountOfRotation);
}
EDIT
I've never used it but I think CharacterController is designed for being moved only when the object is grounded. So if you want to move it while it's on the air, don't use the Move method but edit directly the transform of your GameObject:
else
{
float additionalForwardSpeed = Input.GetAxis("...") * speedScaleFactor;
transform.Translate(transform.forward * Time.deltaTime * additionalForwardSpeed ); //translate
}
the code above should increase the speed of your object in local forward direction.

Categories

Resources