using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movement : MonoBehaviour
{
public Rigidbody rb;
public float MouseSensitivity;
public float MoveSpeed;
public float jumpForce;
void Start ()
{
}
void Update()
{
//Look around
rb.MoveRotation(rb.rotation * Quaternion.Euler(new Vector3(0, Input.GetAxis("Mouse X") * MouseSensitivity, 0)));
//Move
rb.MovePosition(transform.position + (transform.forward * Input.GetAxis("Vertical") * MoveSpeed) + (transform.right * Input.GetAxis("Horizontal") * MoveSpeed));
//Jump
if (Input.GetKeyDown("space"))
{
print("clicked");
rb.AddForce(Vector3.up * jumpForce);
}
}
}
this is my code and a picture of the player object when I'm trying to jump it doesn't work but it does print clicked I tried to do many things but nothing worked so if you know how to solve the issue please tell me
RigidBody.AddForce has a second parameter of type ForceMode that defaults to ForceMode.Force. That particular ForceMode is only good for continual application of force (like a rocket's thruster). For a feature like jumping, you'll either want to use ForceMode.Impulse or ForceMode.VelocityChange.
// Pick one or the other
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
rb.AddForce(Vector3.up * jumpForce, ForceMode.VelocityChange);
Also, make sure your jumpForce value isn't tiny or it'll be an unnoticeably small "jump."
Firstly, physics calculations should generally be calculated inside of FixedUpdate(). This is described in the unity documentation here.
Edit: To make it more clear for the comment on my post. Input should be located inside of the Update() method whilst physics calculations should generally be calculated inside of the FixedUpdate() method.
If it is decided that you want to register input inside of Update() and physics calculations, based on that input, inside of FixedUpdate() then you would use a boolean switch.
Looking at your code I would say that either:
The mass of your Rigidbody is high and your jumpForce variable is too low, trying increasing the value of the jumpForce variable to see if the GameObject moves.
Your Rigidbody has the Is Kinematic checkbox selected.
AddForce is defaulting the ForceMode to ForceMode.Force, try using a different force mode like ForceMode.Impulse to deliver a quick force to the GameObject. In your case this would look like rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
Hope this helps.
Related
I'm creating a movement function for my character(which I've done many times but this time it's not working correctly) and here's my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(CharacterController))]
[RequireComponent(typeof(Animator))]
public class Movement : MonoBehaviour {
public CharacterController controller;
public float moveSpeed;
public float jumpForce;
public float gravityScale;
public Animator animator;
private bool shiftPressed = false;
private void Update()
{
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
shiftPressed = true;
else
shiftPressed = false;
if(shiftPressed)
{
moveSpeed = 20f;
} else
{
moveSpeed = 10f;
}
Vector3 moveDirection = new Vector3(Input.GetAxisRaw("Horizontal") * moveSpeed, 0.0f, Input.GetAxis("Vertical") * moveSpeed);
if(Input.GetKey(KeyCode.Space) && controller.isGrounded)
{
moveDirection.y = jumpForce;
}
if (moveDirection != Vector3.zero)
animator.SetFloat("Speed", moveSpeed);
else if (moveDirection == Vector3.zero)
animator.SetFloat("Speed", 0f);
else if (moveDirection != Vector3.zero)
animator.SetFloat("Speed", moveSpeed);
if(moveDirection != Vector3.zero)
transform.rotation = Quaternion.LookRotation(moveDirection);
moveDirection = Camera.main.transform.TransformDirection(moveDirection);
moveDirection.y = moveDirection.y + (Physics.gravity.y * Time.deltaTime * gravityScale);
controller.Move(moveDirection * Time.deltaTime);
}
}
As you can see that there is no function to go up in the y axis except the jump function. Mysteriously, when I press the 'S' key or 'downArrow' the player moves -z as he should but ironically he moves in +y axis as well. To ensure there is no y axis function I tried making jump function a comment but did the same way still. I thought it might be some character specific problem so I tried adding the code to a cube(thinking it to be my animation mistake) but it didn't helped at any point. I ensured the character controller is set nicely(collider and stuff); I've attached screenshots.
Please help!
Thanks in advance.
The problem has already been stated by several here, but it seems you still do not understand the issue, concluding from your reactions.
This line will always make your character move up.
moveDirection.y = moveDirection.y + (Physics.gravity.y * Time.deltaTime * gravityScale);
You are trying to use gravity (which is a force) in conjunction with manipulating transform. In Unity, you either do one of the two, not both. This will lead to undesired and hard to fix results.
If you want to use forces in your code, then i suggest the follow:
Add a RigidBody to your character. Check the "use gravity" checkbox.
Get the RigidBody in your controller script by calling and add force to it to move it.
var rb = getComponent<RigidBody>();
rb.AddForce(10f);
Do note that if you add force, you can add it continuosly in the Update method, or just once by passing a second paramater "forcemode".
rb.AddForce(10, ForceMode.Impulse); // add instant force, using mass
// Or
rb.AddForce(10, ForceMode.VelocityChange); // add instant force, ignoring mass
// Or
rb.AddForce(10, ForceMode.Force); // add continuous force, using mass
// Or
rb.AddForce(10, ForceMode.Acceleration); // add continous force, ignoring mass
Let me guess.. your character keeps moving up by about the current downwards slope of the camera?
As your code stands, as an example, if your Camera's is Vector3(10,0,0) and if you're trying to move Vector3(5, 0, 5), you've asked the movement vector to be transformed to world space, based off of the camera transform. So, your new movement vector will be something like Vector3(5,1,5). This should do the trick:
var worldDirection = Camera.main.transform.TransformDirection(moveDirection);
moveDirection = new Vector3(
worldDirection.x,
moveDirection.y + (Physics.gravity.y * Time.deltaTime * gravityScale),
worldDirection.z );
moveDirection.y = moveDirection.y + (Physics.gravity.y * Time.deltaTime * gravityScale);
This line always sets "y", and is modified/set as the last function prior to the ultimate statement. It is here, you should validate and verify all factors that has influence the final calculation of "y".
You must validate that each of the variables are calculated to your expected values:
moveDirection.y
Physics.gravity.y
Time.deltaTime
gravityScale
Each will influence the final value of moveDirection.y. Once you have verified each individual value, the final y value will make sense to you. If any of these values are not what you expect, you have a bug in the calculation of that variable.
Happy hunting!
First of all: Sorry for my bad English, I'm Dutch.
I'm trying to create a player object that can walk forward and backwards (with the up and down keys), and rotate the player with the right and left keys. But when I press the left or right key, the position of the player changes, it looks like it rotates around a certain point. But it should rotate and stay on the same place, like I do when I turn around.
I have some other small programs, with the same 'move script' and the same inputmanager settings. There it works fine, so I have no idea why it doesn't work this time.
This is my move script, but this script works fine with other programs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveScript : MonoBehaviour
{
public float speed = 3f;
public float rotate = 50f;
private Rigidbody rb;
// Update is called once per frame
private void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
if (Input.GetButton("Up"))
transform.Translate(Vector3.forward * speed * Time.deltaTime);
if (Input.GetButton("Down"))
transform.Translate(-Vector3.forward * speed * Time.deltaTime);
if (Input.GetButton("Right"))
transform.Rotate(Vector3.up, rotate * Time.deltaTime);
if (Input.GetButton("Left"))
transform.Rotate(-Vector3.up, rotate * Time.deltaTime);
if (gameObject.GetComponent<Rigidbody>().velocity.y < 0.01)
{
if (Input.GetButtonDown("Jump"))
rb.AddForce(0, 225, 0);
}
}
}
The InputManager settings (also the same as other programs where it works fine):
If someone wants a screenshot of something else of my program, you can always ask it of course. I have no idea what the problem could be, if it isn't in the script or the inputmanager.
Following the comments in the OP, the solution should be to use:
if (Input.GetButton("Right"))
transform.localEulerAngles = transform.localEulerAngles + new Vector3(xRotation, 0, 0) * Time.deltaTime;
if (Input.GetButton("Left"))
transform.localEulerAngles = transform.localEulerAngles - new Vector3(xRotation, 0, 0) * Time.deltaTime;
Where xRotation is a float with the amount you want to rotate per second when and while one of the rotation keys is down.
(PS: Don't have unity open right now, so + and - might be inverted, but should be something like that.)
I've been programming like an hour or so, then i realice that in unity 5 the charactercontroller.isGrounded doesn't work. Could anyone give me a answer?
This is the code i had
public float playerSpeed = 3f;
public float realSpeed = 3f;
public float jumpSpeed= 7f;
public float sprintSpeed= 5f;
public float gravity = 20f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
CharacterController CC = GetComponent<CharacterController>();
if(Input.GetKey(KeyCode.W)){
transform.Translate(Vector3.forward * playerSpeed* Time.deltaTime);
}
if(Input.GetKey(KeyCode.S)){
transform.Translate(Vector3.back * playerSpeed* Time.deltaTime);
}
if(Input.GetKey(KeyCode.D)){
transform.Translate(Vector3.right * playerSpeed* Time.deltaTime);
}
if(Input.GetKey(KeyCode.A)){
transform.Translate(Vector3.left * playerSpeed* Time.deltaTime);
}
if(Input.GetKey(KeyCode.Space) && CC.isGrounded){
transform.Translate(Vector3.up * jumpSpeed* Time.deltaTime);
}
if (Input.GetKey(KeyCode.LeftShift)) {
playerSpeed = sprintSpeed;
} else {
playerSpeed = realSpeed;
}
}
}`
So you're trying to make your character jump but only when it's on the ground?
I had this problem before a well. My solution was to make an empty gameobject and place it as a child of your character and a little bit and then put a collider as a trigger on your empty object.
Then you can have collision detection on your empty object to detect whether it is ontriggerstay on just the bottom side. It also compensates for little bumps and stuff.
According to your code you are not using any character controller. You are just changing the position of Object by using translate which will never collide with your ground. Where as to use character controller you have to provide a move direction with gravity to character controller so that its will use character controller to move your player. Gravity vector will pull your character downward and collide with ground then isGrounded will be true. Check Character Controller implementation in this unity script reference for detail.
I can't seem to get my rigidbody to move left and right. The code looks fine and very similar to what everyone else has posted!
The debug statement is getting called but my character is not moving left and right.
Thanks for the help.
public float speed = 4.0f;
void Update()
{
float moveDirection = Input.GetAxis("Horizontal");
if (Input.GetKeyDown("d"))
{
Debug.Log("pressed d");
rb.AddForce(new Vector2(Time.deltaTime * speed * moveDirection, 0), ForceMode2D.Force);
}
I just tested it using an 3D environment, but that shouldn't matter. So after all I'm pretty sure you've got way to less force applied to AddForce.
So try increasing speed to about 40000, then you should be able to notice the AddForce being applied.
If you want to keep the speed value low, you could of course just add a multiplier here:
rb.AddForce(new Vector2(Time.deltaTime * speed * moveDirection * 10000f, 0), ForceMode2D.Force);
A nice one line option would be to use transform translate.
void Update ()
{
transform.Translate(Vector3.right * speed * Input.GetAxis("Horizontal") * Time.deltaTime);
}
AddForce will not work on a Rigidbody which is kinematic. Verify and set isKinematic to false in your Rigidbody component.
If this is already false, trying increasing the force value as suggested by d4Rk.
Does anyone have a good jumping script for 2d games in unity? The code I have works but still is far from jumping, it looks like it is flying.
using UnityEngine;
using System.Collections;
public class movingplayer : MonoBehaviour {
public Vector2 speed = new Vector2(10,10);
private Vector2 movement = new Vector2(1,1);
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float inputX = Input.GetAxis ("Horizontal");
float inputY = Input.GetAxis ("Vertical");
movement = new Vector2(
speed.x * inputX,
speed.y * inputY);
if (Input.GetKeyDown ("space")){
transform.Translate(Vector3.up * 260 * Time.deltaTime, Space.World);
}
}
void FixedUpdate()
{
// 5 - Move the game object
rigidbody2D.velocity = movement;
//rigidbody2D.AddForce(movement);
}
}
Usually for jumping people use Rigidbody2D.AddForce with Forcemode.Impulse. It may seem like your object is pushed once in Y axis and it will fall down automatically due to gravity.
Example:
rigidbody2D.AddForce(new Vector2(0, 10), ForceMode2D.Impulse);
The answer above is now obsolete with Unity 5 or newer. Use this instead!
GetComponent<Rigidbody2D>().AddForce(new Vector2(0,10), ForceMode2D.Impulse);
I also want to add that this leaves the jump height super private and only editable in the script, so this is what I did...
public float playerSpeed; //allows us to be able to change speed in Unity
public Vector2 jumpHeight;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update ()
{
transform.Translate(playerSpeed * Time.deltaTime, 0f, 0f); //makes player run
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space)) //makes player jump
{
GetComponent<Rigidbody2D>().AddForce(jumpHeight, ForceMode2D.Impulse);
This makes it to where you can edit the jump height in Unity itself without having to go back to the script.
Side note - I wanted to comment on the answer above, but I can't because I'm new here. :)
Use Addforce() method of a rigidbody compenent, make sure rigidbody is attached to the object and gravity is enabled,
something like this
gameObj.rigidbody2D.AddForce(Vector3.up * 10 * Time.deltaTime); or
gameObj.rigidbody2D.AddForce(Vector3.up * 1000);
See which combination and what values matches your requirement and use accordingly.
Hope it helps