This is weird.
I've been learning more in depth about Rigidbody, and I can't for the life of me, make it jump. I'm copying exactly what I see on youtube tutorials, and it works for the youtubers, but not for me.
In more C# english - I was trying to .AddForce(ForceMode.TriedEverything) on the y axis, via user Input. It won't work consistently. sometimes it's higher, sometimes lower, most times nothing at all. this is weird. and I didn't even put isGrounded or any other limitation. Simply "addforce if user input". This is case no 1
Case 2 is much simpler, and NEVER works: it's based on setting the velocity to a new vector with only the y axis manipulated. I'll sharethe code. the “jumpForce” is set to 12, but i've tried 500 too. no difference. This case does have a “grounded” condition, but it didn't work without it as well. Anyway, both print statements get executed.
Both cases were tested in Update and in FixedUpdate, no differences.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMotor : MonoBehaviour
{
public LayerMask layerMask = default;
public bool grounded;
[SerializeField] float moveSpeed = 7f;
[SerializeField] float jumpForce = 12f;
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
float x = Input.GetAxisRaw("Horizontal") * moveSpeed;
float y = Input.GetAxisRaw("Vertical") * moveSpeed;
Vector3 movePosition = transform.right * x + transform.forward * y;
Vector3 newPosition = new Vector3(movePosition.x, rb.velocity.y, movePosition.z);
grounded = Physics.CheckSphere(new Vector3(transform.position.x, transform.position.y - 1, transform.position.z), 0.4f, layerMask);
if (Input.GetKeyDown(KeyCode.Space)&& grounded)
{
print("reached if statement");
rb.velocity = new Vector3(rb.velocity.x, jumpForce, rb.velocity.z);
print("jumpingjumping");
}
rb.velocity = newPosition;
}
void FixedUpdate()
{
}
}
Thanks folks.
The problem is the order of your code. You are setting the newPosition variable before the jump statement so the y velocity is 0, then you are setting the y velocity to the jump velocity but after that you set the velocity to the newPosition which still has a velocity of 0 because it was set before the jump statement. Here is the working code:
public LayerMask layerMask = default;
public bool grounded;
[SerializeField] float moveSpeed = 7f;
[SerializeField] float jumpForce = 12f;
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
float x = Input.GetAxisRaw("Horizontal") * moveSpeed;
float y = Input.GetAxisRaw("Vertical") * moveSpeed;
Vector3 movePosition = transform.right * x + transform.forward * y;
grounded = Physics.CheckSphere(new Vector3(transform.position.x, transform.position.y - 1, transform.position.z), 0.4f, layerMask);
if (Input.GetKeyDown(KeyCode.Space) && grounded)
{
print("reached if statement");
rb.velocity = new Vector3(rb.velocity.x, jumpForce, rb.velocity.z);
print("jumpingjumping");
}
Vector3 newPosition = new Vector3(movePosition.x, rb.velocity.y, movePosition.z);
rb.velocity = newPosition;
}
void FixedUpdate()
{
}
Hope this helped you!
Related
I'm new to Unity and I'm trying to make it so the player can't jump while they're already jumping using IsGrounded which should check if they're on the ground, but instead if press space then IsGrounded true. It might be an issue within Unity itself but im not sure. Thanks!
The code:
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
float xInput, yInput;
[SerializeField] private LayerMask lm;
private Rigidbody2D rb;
private BoxCollider2D bc;
// Start is called before the first frame update
void Start()
{
}
private void Awake()
{
rb = transform.GetComponent<Rigidbody2D>();
bc = transform.GetComponent<BoxCollider2D>();
}
// Update is called once per frame
void Update()
{
if (IsGrounded() && Input.GetKeyDown(KeyCode.Space))
{
float jumpVelocity = 25f;
rb.velocity = Vector2.up * jumpVelocity;
Debug.Log("IsGrounded");
}
xInput = Input.GetAxis("Horizontal");
transform.Translate(xInput * moveSpeed, 0, 0);
PlatformerMove();
}
void PlatformerMove()
{
rb.velocity = new Vector2(moveSpeed * xInput, rb.velocity.y);
}
private bool IsGrounded()
{
RaycastHit2D rc = Physics2D.BoxCast(bc.bounds.center, bc.bounds.size, 0f, Vector2.down * .1f, lm);
return rc.collider != null;
}
}```
You are using a
Physics2D.BoxCast(bc.bounds.center, bc.bounds.size, 0f, Vector2.down * .1f, lm);
Now if you look at the parameters of Physics2D.BoxCast
public static RaycastHit2D BoxCast(
Vector2 origin, Vector2 size,
float angle, Vector2 direction,
float distance = Mathf.Infinity,
int layerMask = Physics2D.AllLayers,
float minDepth = -Mathf.Infinity,
float maxDepth = Mathf.Infinity
);
You are passing in
origin = bc.bounds.center
size = bc.bounds.size
direction = Vector2.down (the magnitude doesn't matter for a distance!)
distance = lm (I think you note the issue now) => I suppose this is a layermask -> some rather big integer -> you shoot very far -> probably always hit the something
layerMask = Physics2D.AllLayers
In general, since it is a Boxcast this means you are shooting a box into space and check if on its way it is hitting something.
If that's intended you would rather pass in
RaycastHit2D rc = Physics2D.BoxCast(bc.bounds.center, bc.bounds.size, 0f, Vector2.down, 0.1f, lm);
Otherwise I suppose you rather would want to use Physics2D.OverlapBox instead which rather checks for an overlap in a fixed position/area without shooting it anywhere
RaycastHit2D rc = Physics2D.OverlapBox(bc.bounds.center, bc.bounds.size, 0f, lm);
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
CharacterController characterController;
[SerializeField] private float speed = 5.0f;
public float jumpSpeed = 8.0f;
public float gravity = 20.0f;
private Vector3 moveDirection = Vector3.zero;
private void Start()
{
characterController = GetComponent<CharacterController>();
}
private void Update()
{
var horizontal = Input.GetAxis("Horizontal");
var vertical = Input.GetAxis("Vertical");
transform.Translate(new Vector3(horizontal, 0, vertical) * (speed * Time.deltaTime));
if (characterController.isGrounded)
{
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0.0f, Input.GetAxis("vertical"));
moveDirection *= speed;
if (Input.GetButton("Jump"))
{
moveDirection.y = jumpSpeed;
}
}
moveDirection.y -= gravity * Time.deltaTime;
characterController.Move(moveDirection * Time.deltaTime);
}
}
I was new in game development when I am making an game but I got the problem that the character is not able to jump and when I try to move the character it keeps floating on the air.
This code here works for me
if (Input.GetButtonDown("Jump"))
{
rb.velocity = new Vector3(rb.velocity.x, jumpHeight, 0);
//jumpheight is set at 14, and my gravity scale is at 4
}
you will have to reference your 'rb' like:
public Rigidbody2D rb;
then drag your players rigidbody into the new Rb that shows up on the script.
rb.velocity adds a velocity of the original x velocity and sets the y velocity to 14, and z velocity = 0.
Hope this answers your question
I have this script below and I want my player to always move towards the rotation angle, which doesn't happen. It only changes direction when I click.
My purpose is for the player to move at all times and towards the rotation which should be controlled by mouse position/mouse x axis (kind of like auto-run, but always change rotation based on mouse, not just move right or left).
I've tried about 10 different methods, nothing worked so far...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovementController : MonoBehaviour
{
public float speed = 4;
public float rot = 0f;
public float rotSpeed = 80;
public float gravity = 8;
private Camera cam;
Vector3 moveDir = Vector3.zero;
CharacterController controller;
Animator anim;
// Start is called before the first frame update
void Start()
{
controller = GetComponent<CharacterController> ();
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
float horizontalSpeed = 8.0f;
//Get the mouse delta. This is not in the range -1...1
float h = horizontalSpeed * Input.GetAxis("Mouse X");
float z = horizontalSpeed * Input.GetAxis("Mouse Y");
transform.Rotate(0, h, 0);
//Move Input
if(controller.isGrounded){
if(Input.GetMouseButtonUp(1))
{
anim.SetInteger ("condition", 1);
moveDir = new Vector3 (0,0,1) * speed;
// moveDir *= speed;
moveDir = transform.TransformDirection(moveDir);
}
if(Input.GetMouseButtonDown(1))
{
anim.SetInteger("condition", 0);
moveDir = Vector3.zero;
}
}
moveDir.y -= gravity * Time.deltaTime;
controller.Move(moveDir * Time.deltaTime);
}
}
Transform.LookAt
Just get a cursor position and that's it
Vector3 direction = target.position - player.transform.position;
Quaternion finalPlayerRotation = Quaternion.LookRotation(direction);
player.transform.rotation = finalPlayerRotation;
This also works in some cases:
Vector3 direction = target.position - player.transform.position;
player.transform.right /*You may need to change the Right to upper, -upper, -Right depend on the player rotation and the target position*/ = direction;
the only problem that i face that the player only jump when they build momentum and i dont want that i want player jump by pressing space while standing or moving i tried velocity.y=jumphight which doesnt work too
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovment : MonoBehaviour
{
public CharacterController controller;
public float speed = 12f;
public float gravity = -9.81f;
Vector3 velocity;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
bool isGrounded;
public float JumpHight = 3f;
void Update()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if(isGrounded && velocity.y<0)
{
controller.slopeLimit = 45.0f;
velocity.y = -2f;//when player is grounded it just put some gravity to him all the time
}
float x = Input.GetAxis("Horizontal");//moves left and right
float z = Input.GetAxis("Vertical");//moves up and down
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move*speed*Time.deltaTime);
if(Input.GetButtonDown("Jump") && controller.isGrounded)
{
velocity.y = Mathf.Sqrt(JumpHight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
you could use an addforce on the rigidbody with a ForceMode force , and if you don't want your physic depending on the fps use FixedUpdate instead of update
GetComponent<Rigidbody>().AddForce(Vector3.up,ForceMode.Force);
Vector3 velocity;
public float gravity = -9.82f;
public float JumpHeight = 3f;
if(Input.GetButtonDown("Jump")
{
velocity.y = Matf.Sqrt(JumpHeight * -2f * gravity);
}
You could also do what the other person said, the reason this person's line of code might not have worked it due to how weak it is. Here is an updated version of said code.
GetComponent<Rigidbody>().AddForce(Vector3.up * 10f ,ForceMode.Impulse);
The reason I am using the * is to increase the "up" variable since it means Vector3(0f, 1f, 0f); and using the ForceMode.Impulse to make it more volatile and stronger.
Hope this code helps you in your game making,
Kind Regards. SB
Here's my code. Currently, the player moves forwards relative to a fix plane. Rotating the player/camera has no affect on which direction they travel when I press the "go forward" key.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MainController : MonoBehaviour
{
public float speed;
float jumpSpeed = 0.5f;
bool isGrounded;
private Rigidbody rb;
public GameObject player;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
}
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
if (Input.GetButtonDown("Jump") || Input.GetAxis("Right Trigger") > 0f && isGrounded)
{
rb.AddForce(Vector3.up * jumpSpeed, ForceMode.Impulse);
isGrounded = false;
}
if (isGrounded)
{
rb.AddForce(movement * speed * Time.deltaTime);
}
else
{
rb.AddForce((movement/4) * speed * Time.deltaTime);
}
}
void OnCollisionStay()
{
isGrounded = true;
}
void OnCollisionExit()
{
isGrounded = false;
}
}
How do I make it so that the player moves relative to the camera's direction?
It's because RigidBody.AddForce() adds force in absolute direction, no matter which direction the gameobject is looking.
You should try using RigidBody.AddRelativeForce(), like:
if (isGrounded)
{
rb.AddRelativeForce(movement * speed * Time.deltaTime);
}
I think there is a better way to do this, but see if it results in the expected behavior:
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 looking = (transform.rotation * Vector3.forward).normalized;
Vector3 perpendicular = Vector2.Perpendicular(new Vector2(looking.x, looking.z));
perpendicular.z = perpendicular.y;
perpendicular.y = looking.y;
Vector3 vertical = moveVertical * looking;
Vector3 horizontal = moveHorizontal * perpendicular;
Vector3 movement = vertical - horizontal;
...
}