How to make gameobject not fall using rigidbody but without disabling gravity - c#

Hi I am using a rigidbody component attached to my game Object and I don't want to disable gravity but the game object keeps on falling. Moreover the enemy capsule just falls below the ground in my game. Im a little new to unity. The game I am making is with the help of the (Learning c# by developing games unity 2021) this is the 6th version.
The script for the player behaviour is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerBehavoiur : MonoBehaviour
{
public float MoveSpeed = 10f;
public float RotateSpeed = 75f;
public int hp = 0;
/// <summary>
/// stores a rigidbody component for a gameobject
/// </summary>
private Rigidbody _rb;
// Start is called before the first frame update
void Start()
{
_rb = GetComponent<Rigidbody>();
_rb.useGravity = true;
}
private float _hInput1;
private float _vInput1;
// Update is called once per frame
void Update()
{
/*MoveForward(_hInput1);
RotateUpWards(_vInput1);
*/
}
/*public void MoveForward(float _vInput)
{
_vInput = Input.GetAxis("Vertical") * MoveSpeed;
this.transform.Translate()
}
public void RotateUpWards(float _hInput)
{
_hInput = Input.GetAxis("Horizontal") * RotateSpeed;
this.transform.Translate(Vector3.forward * _hInput * Time.deltaTime);
}
*/
void FixedUpdate()
{
SetVerticalDirection();
SetHorizontalDirection();
//makes the object move by horizontal input in the up direction
Vector3 rotation = Vector3.up * _hInput1;
/*this is the rotation of the game object
* moving up and then going at a fixed frame rate
*/
Quaternion angleRotation = Quaternion.Euler(rotation * Time.fixedDeltaTime);
//this takes vertical input and addes the position and makes it move forward
//the vertical input is the vertical axis whihc moves at a defined rate tht we can define
_rb.MovePosition(this.transform.position +
this.transform.forward * _vInput1 * Time.fixedDeltaTime);
/*the move rotation moves using the rigibody rotation times the
* horizontal input times and moves up and rotates at the rotate speed rate
*/
_rb.MoveRotation(_rb.rotation * angleRotation);
}
void SetVerticalDirection()
{
_vInput1 = Input.GetAxis("Vertical") * MoveSpeed;
}
void SetHorizontalDirection()
{
_hInput1 = Input.GetAxis("Horizontal") * RotateSpeed;
}
/*Horizontal: ad
* Vertical: ws
*/
}

In the Inspector, you can set gravity scale to 0. Or set the mass to 0. If none works, go to the Rigdid Body and use the Constraints and freeze the y position. this will stop it from falling

I am also currently studying this book. You should check the third box in the RigidBody Freeze Rotation.

Related

Using rigidbody why is my gameObject falling all the time

1.There is a error I am constantly getting. Not a programing error but a error in the sense that my game Object is constantly falling on the ground.
2.Every time I click on a and d(left and right) it moves horizontally.
The script I created with the help of my book L(earning c# by developing games with unity 2021 ) is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerBehavoiur : MonoBehaviour
{
public float MoveSpeed = 10f;
public float RotateSpeed = 75f;
public int hp = 0;
//stores a rigidbody
private Rigidbody _rb;
// Start is called before the first frame update
void Start()
{
_rb = GetComponent<Rigidbody>();
}
private float _hInput1;
private float _vInput1;
// Update is called once per frame
void Update()
{
/*MoveForward(_hInput1);
RotateUpWards(_vInput1);
*/
}
/*public void MoveForward(float _vInput)
{
_vInput = Input.GetAxis("Vertical") * MoveSpeed;
this.transform.Translate()
}
public void RotateUpWards(float _hInput)
{
_hInput = Input.GetAxis("Horizontal") * RotateSpeed;
this.transform.Translate(Vector3.forward * _hInput * Time.deltaTime);
}
*/
void FixedUpdate()
{
SetVerticalDirection();
SetHorizontalDirection();
//makes the object move by horizontal input in the up direction
Vector3 rotation = Vector3.up * _hInput1;
/*this is the rotation of the game object
* moving up and then going at a fixed frame rate
*/
Quaternion angleRotation = Quaternion.Euler(rotation * Time.fixedDeltaTime);
//this takes vertical input and addes the position and makes it move forward
//the vertical input is the vertical axis whihc moves at a defined rate tht we can define
_rb.MovePosition(this.transform.position +
this.transform.forward * _vInput1 * Time.fixedDeltaTime);
/*the move rotation moves using the rigibody rotation times the
* horizontal input times and moves up and rotates at the rotate speed rate
*/
_rb.MoveRotation(_rb.rotation * angleRotation);
}
void SetVerticalDirection()
{
_vInput1 = Input.GetAxis("Vertical") * MoveSpeed;
}
void SetHorizontalDirection()
{
_hInput1 = Input.GetAxis("Horizontal") * RotateSpeed;
}
/*Horizontal: ad
* Vertical: ws
*/
}
This code controls the player motion using the input manager for taking vertical and horizontal issue

Destroy not destroying after delay

Hi I am currently learning from the book (Learning c# by developing games with unity 2021).
1.Right now in the game I have created a bullet object this object is supposed to be destroyed after being created.
2.But since I want to display it in the scene for a time I created a floating point to see how much time I can give. I applied these are parameters in the destroy utility function.
problem:-
1.Instead of destroying it after a certain time it deleted it entirely after it was created.
This is a problem the code I wrote to create the bullet is attached to my player.
2.It deletes the prefab in the starting of the game itself
Player action:-
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerBehavoiur : MonoBehaviour
{
//this is a bullet made and used
public GameObject Bullet;
//the speed with the bullet
public float BulletSpeed = 100f;
//checks if our player is shooting
private bool _isShooting;
//stores the desired distance to ground
public float distanceToGround = 0.1f;
//creates a reference variable of type layermask
public LayerMask GroundLayer;
//gets the collider stored in a variable that will be used to access it
private CapsuleCollider _col;
void Update()
{
/*MoveForward(_hInput1);
RotateUpWards(_vInput1);
*/
_isJumping |= Input.GetKeyDown(KeyCode.Space);
PrintIfJumping(_isJumping);
//this sets it to a method that checks if the key in the
//arguments pressed down on
IsFalling |= Input.GetKeyDown(KeyCode.G);
//scans for mouse input and sets the isShooting field to that value
//if that value is true or when the mouse is clicked then run the shoot method
//this is through prefabs which are are used
_isShooting |= Input.GetMouseButtonDown(0);
}
void PrintIfJumping(bool _isJumping)
{
if (_isJumping == true)
{
Debug.Log("Time to take a leap of faith!");
}
else
{
Debug.Log("Im on the ground this sucks!");
}
}
void Start()
{
_rb = GetComponent<Rigidbody>();
_rb.useGravity = true;
//sets isJumping to keycode.space which checks wether the key space is pressed
//gets the collider component and stores inside a variable for later use
_col = GetComponent<CapsuleCollider>();
}
void SetVerticalDirection()
{
_vInput1 = Input.GetAxis("Vertical") * MoveSpeed;
}
void SetHorizontalDirection()
{
_hInput1 = Input.GetAxis("Horizontal") * RotateSpeed;
}
public float MoveSpeed = 10f;
public float RotateSpeed = 75f;
public int hp = 0;
/// <summary>
/// stores a rigidbody component for a gameobject
/// </summary>
private Rigidbody _rb;
public float JumpVelocity = 5f;
private bool _isJumping;
private bool IsFalling;
public float FallVelocity;
/// <summary>
/// Start is called before the first frame update
/// </summary>
private float _hInput1;
private float _vInput1;
/// <summary>
/// Update is called once per frame
/// </summary>
/*public void MoveForward(float _vInput)
{
_vInput = Input.GetAxis("Vertical") * MoveSpeed;
this.transform.Translate()
}
public void RotateUpWards(float _hInput)
{
_hInput = Input.GetAxis("Horizontal") * RotateSpeed;
this.transform.Translate(Vector3.forward * _hInput * Time.deltaTime);
}
*/
void FixedUpdate()
{
SetVerticalDirection();
SetHorizontalDirection();
//makes the object move by horizontal input in the up direction
Vector3 rotation = Vector3.up * _hInput1;
/*this is the rotation of the game object
* moving up and then going at a fixed frame rate
*/
Quaternion angleRotation = Quaternion.Euler(rotation * Time.fixedDeltaTime);
//this takes vertical input and addes the position and makes it move forward
//the vertical input is the vertical axis whihc moves at a defined rate tht we can define
_rb.MovePosition(this.transform.position +
this.transform.forward * _vInput1 * Time.fixedDeltaTime);
/*the move rotation moves using the rigibody rotation times the
* horizontal input times and moves up and rotates at the rotate speed rate
*/
_rb.MoveRotation(_rb.rotation * angleRotation);
//performs a jump if object is in collision with ground and isJumping
if(IsGrounded() && _isJumping)
{
/*while(JumpVelocity > 0)
{
--JumpVelocity;
}
*/
_rb.AddForce(Vector3.up * JumpVelocity, ForceMode.Impulse);
}
Fall(IsFalling);
Shoot(_isShooting, Bullet);
}
private bool IsGrounded() {
//this defines the bottom of the capsule or the end
Vector3 capsuleBottom = new Vector3(_col.bounds.center.x, _col.bounds.min.y, _col.bounds.center.z);
//this checks if a object is touching start or bottom of a capsule and the raduis is distance to ground
//this sets the ground layer to the phy-system
bool grounded = Physics.CheckCapsule(_col.bounds.center, capsuleBottom, distanceToGround, GroundLayer, QueryTriggerInteraction.Ignore);
return grounded;
}
public void Fall(bool grounded)
{
bool Gpressed = Input.GetKeyDown(KeyCode.G);
Debug.Log("G is pressed");
Debug.LogFormat("The down direction is {0}", Vector3.down);
if (Gpressed ==true & grounded == false)
{
_rb.AddForce(Vector3.down * FallVelocity, ForceMode.Impulse);
}
else
{
Debug.Log("No falling allowed!");
}
}
public void Shoot(bool _isShooting,GameObject Bullet)
{
if (_isShooting == true)
{
//this is the instance of the prefab bullet which is created using the unity editor
//builds
GameObject newBullet = Instantiate(Bullet, this.transform.position + new Vector3(1, 0, 0), this.transform.rotation);
//create a new bullet rigidbody which captures the component rb
Rigidbody BulletRB = newBullet.GetComponent<Rigidbody>();
//set the velocity (speed x direction) basically
//so we want our bullet to go forward x a certian speed so...
BulletRB.velocity = this.transform.forward * BulletSpeed;
}
_isShooting = false;
}
/*Horizontal: ad
* Vertical: ws */
}
Its pretty long I know just read the shoot function and the stuff in update on shooting
So the bullet behaviour is:-
public class BulletBehaviour : MonoBehaviour
{
float OnScreenDelay = 3f;
void Start()
{
Destroy(this.gameObject,OnScreenDelay);
}
// Update is called once per frame
void Update()
{
}
public void Scale(float x, float y, float z)
{
this.transform.localScale = new Vector3(x, y, z);
}
}

Character not moving in horizontal axis

I'm writing a 2D platform game with Visual Studio Code and Unity. So far, I have established the animations that I will use later in the main character and the enemy. With the main character I have defined the "horizontal move" and the "vertical move". However when I run the game, the character moves up, but it doesn't move left or right.
This is the code that I have for the main character:
public class Hero : Monobehaviour
{
public float vel =10f;
public Animator anim;
private Vector2 moveVelocity;
float horizontalMove = 0f;
private Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
horizontalMove = Input.GetAxisRaw("Horizontal") * vel;
Vector2 moveInput = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
moveVelocity = moveInput.normalized * vel;
}
void FixedUpdate()
{
Vector2 v = new Vector2 (vel, 0);
rb.velocity = v;
rb.MovePosition(rb.position + moveVelocity * Time.fixedDeltaTime);
}
}
Can someone please tell me what I'm missing?
It should work if you change your code to this:
void Update()
{
if(Input.GetKeyDown(KeyCode.D))
{
rb.AddRelativeForce(Vector2.right * (vel*Time.deltaTime));
}
else if(Input.GetKeyDown(KeyCode.A))
{
rb.AddRelativeForce(Vector2.left * (vel*Time.deltaTime));
}
}
Since you have a rigidbody attached to your game object, it would make sense to add relative force to the object when a user presses D/A instead of just changing the object's transform position. This should work.
Essentially, you can set the horizontal move up in the input manager under Edit > project settings > input. Double-check if the horizontal axis is set up to the left and right button.

Can't rotate and move at the same time

I'm currently developing an FPS shooter in Unity 3D. I'm fairly new to Unity and I've been having a bit of trouble with my player movement script. Individually everything seems to work, I can rotate and move the player freely, however when I try doing the two simultaneously my player seems to lock and won't rotate.
Sometimes jumping or moving to higher ground on the terrain seems to fix the issue, however I ran a few checks with gravity disabled, no colliders, and with the player well above ground, so the problem seems to be with the script. I've also done a bit of debugging and the Rotate() code does run, just the rotation amount doesn't seem to change.
Here is the player movement script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class PlayerMov : MonoBehaviour
{
[SerializeField]
private Camera cam;
[SerializeField]
private float speed = 5f;
[SerializeField]
private float looksensitivity = 4f;
[Header("Camera View Lock:")]
[SerializeField] //min and max amount for looking up and down (degrees)
private float lowlock = 70f;
[SerializeField]
private float highlock = 85f;
private Rigidbody rb;
private float currentrotx; //used later for calculating relative rotation
public Vector3 velocity;
public Vector3 rotation; // rotates the player from side to side
public float camrotation; // rotates the camera up and down
public float jmpspe = 2000f;
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
CalcMovement();
CalcRotation();
Rotate();
}
void FixedUpdate()
{
Move();
}
private void CalcRotation()
{
float yrot = Input.GetAxisRaw("Mouse X"); //around x axis
rotation = new Vector3(0f, yrot, 0f) * looksensitivity;
float xrot = Input.GetAxisRaw("Mouse Y"); //around y axis
camrotation = xrot * looksensitivity;
}
private void CalcMovement()
{
float xmov = Input.GetAxisRaw("Horizontal");
float zmov = Input.GetAxisRaw("Vertical");
Vector3 movhor = transform.right * xmov;
Vector3 movver = transform.forward * zmov;
velocity = (movhor + movver).normalized * speed;
}
void Move()
{
//move
if (velocity != Vector3.zero)
{
rb.MovePosition(rb.position + velocity * Time.fixedDeltaTime);
}
//jump
if (Input.GetKeyDown(KeyCode.Space))
{
//add double jump limit later!
rb.AddForce(0, jmpspe * Time.deltaTime, 0, ForceMode.Impulse);
}
}
void Rotate()
{
//looking side to side
rb.MoveRotation(rb.rotation * Quaternion.Euler(rotation));
// camera looking up and down
currentrotx -= camrotation;
currentrotx = Mathf.Clamp(currentrotx, -lowlock, highlock);
cam.transform.localEulerAngles = new Vector3(currentrotx, 0, 0);
}
}
Here are the relevant components attached to my player:
(The player has a couple more components attached but I ran tests without them and the problem still occurs)
Like I said I'm a bit of a unity novice, so i'm sure I missed something small but I just can't seem to place my finger on it, I've been stuck on this for a while so any help is much appreciated.
SOLVED:
It seems the problem I had was because I was running the scene from my laptop and not a desktop which I assume is what the Unity input was built for.

How can I apply scripts in new camera which is child of a gameobject

Earlier I was facing problem regarding the unity camera problem it always stuck on 0,0,0.08 and also find a solution so I first create an empty gameobject and then drag the camera in that empty gameobject but after doing this the scripts which I applied to the gameobject is working fine but the script which I place in camera is not working at all
Camera Script
public float MovementAmplitude = 0.1f;
public float MovementFrequency = 2.25f;
void Update()
{
transform.position = new Vector3(
transform.position.x,
Mathf.Cos(transform.position.z * MovementFrequency) * MovementAmplitude,
transform.position.z
);
}
Player Script
public float speed = 4.5f;
public float JumpingForcec = 450f;
void Update()
{
transform.position += speed * Vector3.forward * Time.deltaTime;
if (Input.GetKeyDown("space"))
{
Debug.Log("SPace is pressed");
Debug.Log(GetComponent<Rigidbody>());
GetComponent<Rigidbody>().AddForce(Vector3.up * JumpingForcec);
}
}
First of all when dealing with a Rigidbody (or the Physics in general) you shouldn't set a position directly through the Transform component but rather use Rigidbody.position or in your case for a smooth movement even rather Rigidbody.MovePosition, both in FixedUpdate.
In general anything related to the Physics (so also everything using Rigidbody) should be done in FixedUpdate while the check for GetKeyDown has to be done in Update.
PlayerScript
public class PlayerScript : MonoBehaviour
{
public float speed = 4.5f;
public float JumpingForcec = 450f;
// If possible reference this in the Inspector already
[SerializeField] private Rigidbody rigidBody;
private bool jumpWasPressed;
private void Awake()
{
if (!rigidBody) rigidBody = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
rigidBody.MovePosition(transform.position + speed * Vector3.forward * Time.deltaTime);
if (!jumpWasPressed) return;
Debug.Log("SPace was pressed");
rigidBody.AddForce(Vector3.up * JumpingForcec);
jumpWasPressed = false;
}
private void Update()
{
// Note that currently you can multijump .. later you will want to add
// an additional check if you already jump again
if (Input.GetKeyDown(KeyCode.Space)) jumpWasPressed = true;
}
}
Make sure that Is Kinematic is disabled in the Rigidbody component! Otherwise AddForce is not processed.
If isKinematic is enabled, Forces, collisions or joints will not affect the rigidbody anymore.
The camera movement I would move to LateUpdate in order to make sure it is the last thing calculated after the other Update calls have finished. Especially after all user input has been processed (in your case maybe not that relevant since movement is processed in FixedUpdate but in general).
Second problem: Here you are not taking the changed Y position by jumping into account so rather add the "wobbling" effect to the player's transform.position.y and rather use the localPosition for the Camera:
public class CameraScript : MonoBehaviour
{
public float MovementAmplitude = 0.1f;
public float MovementFrequency = 2.25f;
// reference the player object here
public Transform playerTransform;
private float originalLocalPosY;
private void Start()
{
if(!playerTransform) playerTransform = transform.parent;
originalLocalPosY = transform.localPosition.y;
}
private void LateUpdate()
{
transform.localPosition = Vector3.up * (originalLocalPosY + Mathf.Cos(playerTransform.position.z * MovementFrequency) * MovementAmplitude);
}
}
Maybe you want to disable the wobbling effect during a jump later, though ;)
Try to put all the update stuff in the same method, it should work both (theorically, not tested) so you have to fix your code in order to get what you want:
void Update() {
// Camera update
transform.position = new Vector3(
transform.position.x,
Mathf.Cos(transform.position.z * MovementFrequency) * MovementAmplitude,
transform.position.z
);
// Player update
transform.position += speed * Vector3.forward * Time.deltaTime;
if (Input.GetKeyDown("space"))
{
Debug.Log("SPace is pressed");
Debug.Log(GetComponent<Rigidbody>());
GetComponent<Rigidbody>().AddForce(Vector3.up * JumpingForcec);
}
}
Hope this helps you, cheers!

Categories