I'm working on a very basic side scrolling platformer in Unity 3D. The player is a cube, you can move left and right, you can jump. I can't get the movement correct as the character moves too slow.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public float walkSpeed = 15f;
public float jumpSpeed = 15f;
public float gravity = 50f;
Rigidbody rb;
bool pressedJump = false;
Vector3 movementInput;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
movementInput = new Vector3(Input.GetAxis("Horizontal"), 0f, 0f);
}
void FixedUpdate()
{
WalkHandler();
JumpHandler();
GravityHandler();
}
void WalkHandler()
{
rb.velocity = new Vector2(0f, rb.velocity.y);
rb.velocity = movementInput * walkSpeed * Time.fixedDeltaTime;
}
void JumpHandler()
{
if (Input.GetButtonDown("Jump"))
{
if (!pressedJump)
{
pressedJump = true;
Vector3 jumpVector = new Vector3(0f, jumpSpeed, 0f);
rb.velocity = rb.velocity + jumpVector;
}
}
else
{
pressedJump = false;
}
}
void GravityHandler()
{
rb.AddForce(Vector3.down * gravity * rb.mass);
}
}
More context I originally had this implemented and it worked. Very smooth movement and jumping. I tragically lost that game due to my own actions. So I'm trying to recreate it. Here is a video of the original movement and jumping I'm looking to recreate:
My Progress so Far
Note: The values for walkSpeed, jumpForce and gravity were what was used previously.
Losing the first game was pretty soul crushing so any help would be great.
OK so I'm not sure how to recreate this using velocity but this seems to work:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public float walkSpeed = 15f;
public float jumpSpeed = 15f;
public float gravity = 50f;
Rigidbody rb;
bool pressedJump = false;
float hAxis;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
hAxis = Input.GetAxisRaw("Horizontal");
}
void FixedUpdate()
{
WalkHandler();
JumpHandler();
GravityHandler();
}
void WalkHandler()
{
rb.velocity = new Vector2(0f, rb.velocity.y);
Vector3 movement = new Vector2(hAxis * walkSpeed * Time.deltaTime, 0f);
rb.MovePosition(transform.position + movement);
}
void JumpHandler()
{
if (Input.GetButtonDown("Jump"))
{
if (!pressedJump)
{
pressedJump = true;
Vector3 jumpVector = new Vector3(0f, jumpSpeed, 0f);
rb.velocity = rb.velocity + jumpVector;
}
}
else
{
pressedJump = false;
}
}
// Check if the object is grounded
bool CheckGrounded()
{
return true;
}
void GravityHandler()
{
rb.AddForce(Vector3.down * gravity * rb.mass);
}
}
Ignore the CheckGrounded method
Related
public class PlayerMove : MonoBehaviour
{
public float speed;
private float yVelocity;
public CharacterController player;
public float jumpHeight =10.0f;
public float gravity = 1.0f;
//public float gravityScale = 1;
private void Start()
{
player = GetComponent<CharacterController>();
}
void Update()
{
Vector3 direction= new Vector3(0, 0, 1);
Vector3 velocity= direction * speed;
if (player.isGrounded == true)
{
if (Input.GetKeyDown(KeyCode.Space))
{
yVelocity = jumpHeight;
}
}
else
{
yVelocity -= gravity;
}
velocity.y = yVelocity;
player.Move(velocity * Time.deltaTime);
}
}
I tried Rigidbody & much more script but my player doesn't jump if my player jump then my doesn't move left or right sometimes my player stocked in ground.. tell me the right way of script where I can use
For the left/right movements you can try this simple code :
using UnityEngine;
public class PlayerMove : MonoBehaviour
{
public float speed;
private float yVelocity;
public CharacterController player;
public float jumpForce = 10.0f;
public float moveForce = 5.0f;
public float gravity = 1.0f;
private void Start()
{
player = GetComponent<CharacterController>();
}
void Update()
{
Vector3 direction = new Vector3(0, 0, 1);
Vector3 velocity = direction * speed;
// Add left/right movement
if (Input.GetKey(KeyCode.LeftArrow))
{
velocity += Vector3.left * moveForce;
}
else if (Input.GetKey(KeyCode.RightArrow))
{
velocity += Vector3.right * moveForce;
}
if (player.isGrounded)
{
if (Input.GetKeyDown(KeyCode.Space))
{
yVelocity = jumpForce;
}
}
else
{
yVelocity -= gravity;
}
velocity.y = yVelocity;
player.Move(velocity * Time.deltaTime);
}
}
You can also look at this post Moving player in Subway Surf like game using left/right swipe
I'm very new to unity and have followed a brackeys tutorial to get this. My movement script works, but the player is always facing the wrong direction, and I am unable to change this. I've made an empty gameobject, parented the model to it and put the script into it, but it still won't rotate.
Movement script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class MovementSystem : MonoBehaviour
{
private CharacterController controller;
public float positiveZForce = 200f;
public float negativeZForce = 175f;
public float xForce = 175f;
public float yForce = 125f;
Rigidbody rb;
public bool isGrounded;
void Start() {
rb = GetComponent<Rigidbody>();
}
void OnCollisionEnter(Collision other) {
if (other.gameObject.CompareTag("Ground")) {
isGrounded = true;
}
}
void FixedUpdate()
{
if (Input.GetKey("w")) {
rb.AddForce(0, 0, positiveZForce * Time.deltaTime);
}
if (Input.GetKey("s")) {
rb.AddForce(0, 0, -negativeZForce * Time.deltaTime);
}
if (Input.GetKey("a")) {
rb.AddForce(-xForce * Time.deltaTime, 0, 0);
}
if (Input.GetKey("d")) {
rb.AddForce(xForce * Time.deltaTime, 0, 0);
}
if (Input.GetKey("space")) {
if (isGrounded) {
rb.AddForce(0, yForce, 0);
isGrounded = false;
}
}
}
}
The most direct solution would be to call
transform.LookAt(transform.position + rb.velocity);
in your FixedUpdate function. This will cause your gameObject to rotate to face in the direction of its motion.
I am making a 2D camera follow script where if the player enters a collider it will test if that has the layer "waypoint" and if so the camera will go to the center of the gameobject with that collider in a smooth transition; however, when I try to test if the player is colliding with OnCollisionEnter2D it doesn't execute, I also tried OnTriggerEnter2D and that doesn't work either. I tested each with "is trigger" true, and false, and with a rigidbody set to kinematic. the only thing I haven't tried is adding a rigidbody with kinematic false, but I don't want to go through the trouble of having to make physics not effect the player with kinematic true.
Camera script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CamFollow : MonoBehaviour
{
public Transform player;
public Transform playerFrame;
public List<GameObject> waypoints;
private bool hasWaypoints;
private bool inWaypoint;
private int waypointIn;
// Start is called before the first frame update
void Start()
{
hasWaypoints = true;
if (waypoints.Count == 0)
{
hasWaypoints = false;
}
inWaypoint = false;
waypointIn = 0;
}
// Update is called once per frame
void Update()
{
if (hasWaypoints)
{
if (inWaypoint)
Move(waypoints[waypointIn].transform.position);
else
MoveInFrame(player.position);
}
else
{
MoveInFrame(player.position);
}
}
void MoveInFrame(Vector3 moveTo)
{
Vector3 playerFrameRelative = playerFrame.position - transform.position;
transform.position = Vector3.MoveTowards(transform.position, moveTo - playerFrameRelative, 10);
transform.position = new Vector3(transform.position.x, transform.position.y, -10);
}
void Move(Vector3 moveTo)
{
transform.position = Vector3.MoveTowards(transform.position, moveTo, 10);
transform.position = new Vector3(transform.position.x, transform.position.y, -10);
}
public void Coll(Collider2D collision)
{
inWaypoint = true;
waypointIn = waypoints.IndexOf(collision.gameObject);
}
public void setWaypoint(bool b)
{
inWaypoint = b;
}
}
Player script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public float speed = 9.53f;
public float jumpPower = 2.46f;
public float gravity = 0.65f;
public bool startsBackwards;
public GameObject camera;
public LayerMask layerMask;
private float upSpeed;
private int jumps;
private RaycastHit2D hit;
private Vector3 direction;
void Start()
{
if (startsBackwards)
direction = Vector3.left;
else
direction = Vector3.right;
}
void Update()
{
if (jumps < 3)
{
if (Input.GetKeyDown("w") || Input.GetKeyDown("up") || Input.GetKeyDown("space"))
{
upSpeed = jumpPower + gravity;
jumps--;
}
}
transform.Translate(direction * speed * Time.deltaTime);
upSpeed = upSpeed - gravity;
if (upSpeed < 0)
{
hit = Physics2D.BoxCast(transform.position, new Vector2(1, 1), 0, Vector2.down, -upSpeed, layerMask.value);
if (hit)
{
transform.Translate(Vector3.down * hit.distance);
jumps = 0;
upSpeed = 0;
}
else
transform.Translate(Vector3.up * upSpeed);
}
if (upSpeed > 0)
{
//hit = Physics2D.BoxCast(transform.position, new Vector2(1, 1), 0, Vector2.up, upSpeed);
if (false)
transform.Translate(Vector3.up * hit.distance);
else
transform.Translate(Vector3.up * upSpeed);
}
}
void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "Reverse")
{
if (direction == Vector3.right)
direction = Vector3.left;
else
direction = Vector3.right;
}
if (camera.GetComponent<CamFollow>().waypoints.Contains(collision.gameObject))
camera.GetComponent<CamFollow>().Coll(collision);
else
camera.GetComponent<CamFollow>().setWaypoint(false);
Debug.Log("worked!");
}
}
Help me please!!
This is a screenshot of the Input settings in the editor there is no crouch and no left shift to make the player moving faster.
This is my script name character controller. attached to the FPSController(Player).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterController : MonoBehaviour
{
public float moveSpeed = 10.0f;
public float jumpForce = 2.0f;
void Start()
{
}
// Update is called once per frame
void Update ()
{
float translatioin = Input.GetAxis("Vertical") * moveSpeed;
float straffe = Input.GetAxis("Horizontal") * moveSpeed;
translatioin *= Time.deltaTime;
straffe *= Time.deltaTime;
transform.Translate(straffe, 0, translatioin);
if (Input.GetKeyDown("escape"))
{
Cursor.lockState = CursorLockMode.None;
}
transform.Translate(0, jumpForce * Input.GetAxis("Jump") * Time.deltaTime, 0);
}
}
I want to add crouch and left shift for faster moving.
This script is only for controlling the mouse looking around and lock state of the mouse cursor attached to the main camera(Player child).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class camMouseLook : MonoBehaviour
{
Vector2 mouseLook;
Vector2 smoothV;
public float sensitivity = 5.0f;
public float smoothing = 2.0f;
public bool mouseDown = false;
public bool cursorLock = false;
public HandleMouseCursor handleMouseCursor;
GameObject character;
// Use this for initialization
void Start ()
{
if(cursorLock == false)
{
Cursor.lockState = CursorLockMode.None;
handleMouseCursor.setMouse();
}
else
{
Cursor.lockState = CursorLockMode.Locked;
}
character = this.transform.parent.gameObject;
}
// Update is called once per frame
void Update ()
{
if (Input.GetMouseButton(0) && mouseDown == true)
{
MouseLook();
}
else
{
if (mouseDown == false)
{
MouseLook();
}
}
}
private void MouseLook()
{
if (cursorLock == false)
{
Cursor.lockState = CursorLockMode.None;
handleMouseCursor.setMouse();
}
else
{
Cursor.lockState = CursorLockMode.Locked;
}
var md = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
md = Vector2.Scale(md, new Vector2(sensitivity * smoothing, sensitivity * smoothing));
smoothV.x = Mathf.Lerp(smoothV.x, md.x, 1f / smoothing);
smoothV.y = Mathf.Lerp(smoothV.y, md.y, 1f / smoothing);
mouseLook += smoothV;
mouseLook.y = Mathf.Clamp(mouseLook.y, -90f, 90f);
transform.localRotation = Quaternion.AngleAxis(-mouseLook.y, Vector3.right);
character.transform.localRotation = Quaternion.AngleAxis(mouseLook.x, character.transform.up);
}
}
You can change speed of your movement in your CharacterController script.
Just create a variable for crouch speed and multiplay it to your translation vector.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterController : MonoBehaviour
{
public float moveSpeed = 10.0f;
public float crouchSpeed = 20;
public float jumpForce = 2.0f;
void Start()
{
}
// Update is called once per frame
void Update ()
{
float finalMoveSpeed = moveSpeed;
// you can add more IF statements for more actions like walking, running, jumping,...
if(Input.GetKey(KeyCode.KeyCode.LeftShift))
finalMoveSpeed = crouchSpeed ;
float translatioin = Input.GetAxis("Vertical") * finalMoveSpeed ;
float straffe = Input.GetAxis("Horizontal") * finalMoveSpeed ;
translatioin *= Time.deltaTime;
straffe *= Time.deltaTime;
transform.Translate(straffe, 0, translatioin);
if (Input.GetKeyDown("escape"))
{
Cursor.lockState = CursorLockMode.None;
}
transform.Translate(0, jumpForce * Input.GetAxis("Jump") * Time.deltaTime, 0);
}
}
I am new to Unity and have been having a hard time adding running and animations (I have the animations and they are set up in animator) to my FPS controller script. Can someone please help me add running and animations? I would be extremely grateful.
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
Animator anim;
float RotateX;
float RotateY;
public static bool GamePaused;
[SerializeField]
[Header("Game Objects")]
public GameObject Camera;
public GameObject PauseMenu;
public GameObject Player;
[Header("Movement Settings")]
public float WalkSpeed = 5.0f;
public float RunSpeed = 10.0f;
[Header("Rotation Settings")]
public float RorationSpeed;
public float MaxYAxis = 60.0f; // right
public float MinYAxis = -48.0f; // left
public bool Grounded;
private void Start()
{
anim = GetComponent<Animator>();
}
void Update()
{
transform.Translate(Vector3.forward * Input.GetAxis("Vertical") * WalkSpeed * Time.deltaTime);
transform.Translate(Vector3.right * Input.GetAxis("Horizontal") * WalkSpeed * Time.deltaTime);
RotateX += Input.GetAxis("Mouse X") * RorationSpeed;
RotateY += Input.GetAxis("Mouse Y") * RorationSpeed;
RotateY = Mathf.Clamp(RotateY, MinYAxis, MaxYAxis);
Camera.transform.localRotation = Quaternion.Euler(-RotateY, 0f, 0f);
transform.rotation = Quaternion.Euler(0f, RotateX, 0f);
}
}
Here is what I have to trigger the different animations in the animator, but the animation follows through when I release the key rather than switching immediately upon release.
if (Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.A) ||
Input.GetKeyDown(KeyCode.S) || Input.GetKeyDown(KeyCode.D) ||
Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.LeftArrow) ||
Input.GetKeyDown(KeyCode.DownArrow) || Input.GetKeyDown(KeyCode.RightArrow))
{
anim.SetBool("IsWalking", true);
}
if (Input.GetKeyUp(KeyCode.W) || Input.GetKeyDown(KeyCode.A) ||
Input.GetKeyDown(KeyCode.S) || Input.GetKeyDown(KeyCode.D) ||
Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.LeftArrow) ||
Input.GetKeyDown(KeyCode.DownArrow) || Input.GetKeyDown(KeyCode.RightArrow))
{
anim.SetBool("IsWalking", false);
}
What I can suggest is that you use the horizontal and vertical axes, rather than hard-coded key presses.
More specifically, first of all (if you have not already) in the animator window create an idle state and a walking animation state. You will need somehow to transition between the two states. To do that you will need to create a new bool parameter (let's name it "isWalking" as you did) and create a new condition between the idle and the walking state. For example, set to transition between "idle" to "walking" when isWalking is true and transition between "walking" to "idle" when isWalking is false.
Now in your PlayerController script in the update or fixed update you can add the following code
horizontalMovement = Input.GetAxis("Horizontal");
verticalMovement = Input.GetAxis("Vertical");
//normalize vector so movement in two axis simultanesly is balanced.
moveDirection = (horizontalMovement * transform.right + verticalMovement * transform.forward).normalized;
/* based on your code although a rigid body solution or character controller would have been more robust */
transform.Translate(moveDirection * WalkSpeed * Time.deltaTime);
if (horizontal != 0 || vertical != 0)
{
animator.setFloat("isWalking",true);
}
else
{
animator.setFloat("isWalking",false);
}
However this solution is working is implemented based on the code you provided. If you want to switch in a more robust and easy to maintain script you can use this free controller that uses a rigidbody and has animations already installed and working.
https://github.com/PanMig/First-Person-Unity-Camera
Here is my working script with walking, running, jumping and animation triggers.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
Animator anim;
float RotateX;
float RotateY;
Rigidbody rb;
public static bool GamePaused;
public bool isGrounded;
[SerializeField]
[Header("Game Objects")]
public GameObject Camera;
public GameObject PauseMenu;
public GameObject Player;
[Header("Movement Settings")]
public float DefaultSpeed = 5.0f;
public float WalkSpeed = 5.0f;
public float RunSpeed = 10.0f;
public float jumpForce = 2.5f;
public Vector3 jump;
[Header("Rotation Settings")]
public float RorationSpeed = 3.0f;
public float MaxYAxis = 60.0f;
public float MinYAxis = -48.0f;
private void Start()
{
anim = GetComponent<Animator>();
rb = GetComponent<Rigidbody>();
jump = new Vector3(0.0f, 1.0f, 0.0f);
}
void Update()
{
Rotation();
Movement();
Bool();
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
rb.AddForce(jump * jumpForce, ForceMode.Impulse);
isGrounded = false;
}
}
void Rotation()
{
RotateX += Input.GetAxis("Mouse X") * RorationSpeed;
RotateY += Input.GetAxis("Mouse Y") * RorationSpeed;
RotateY = Mathf.Clamp(RotateY, MinYAxis, MaxYAxis);
Camera.transform.localRotation = Quaternion.Euler(-RotateY, 0f, 0f);
transform.rotation = Quaternion.Euler(0f, RotateX, 0f);
}
void Movement()
{
transform.Translate(Vector3.forward * Input.GetAxis("Vertical") * WalkSpeed * Time.deltaTime);
transform.Translate(Vector3.right * Input.GetAxis("Horizontal") * WalkSpeed * Time.deltaTime);
if (Input.GetKeyDown(KeyCode.LeftShift))
{
WalkSpeed = RunSpeed;
}
if (Input.GetKeyUp(KeyCode.LeftShift))
{
WalkSpeed = DefaultSpeed;
}
}
void Bool()
{
if (Input.GetKeyDown(KeyCode.W))
{
anim.SetBool("IsWalkingForward", true);
}
if (Input.GetKeyDown(KeyCode.A))
{
anim.SetBool("IsWalkingLeft", true);
}
if (Input.GetKeyDown(KeyCode.S))
{
anim.SetBool("IsWalkingBack", true);
}
if (Input.GetKeyDown(KeyCode.D))
{
anim.SetBool("IsWalkingRight", true);
}
if (Input.GetKeyDown(KeyCode.UpArrow))
{
anim.SetBool("IsWalkingForward", true);
}
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
anim.SetBool("IsWalkingLeft", true);
}
if (Input.GetKeyDown(KeyCode.DownArrow))
{
anim.SetBool("IsWalkingBack", true);
}
if (Input.GetKeyDown(KeyCode.RightArrow))
{
anim.SetBool("IsWalkingRight", true);
}
if (Input.GetKeyUp(KeyCode.W))
{
anim.SetBool("IsWalkingForward", false);
}
if (Input.GetKeyUp(KeyCode.A))
{
anim.SetBool("IsWalkingLeft", false);
}
if (Input.GetKeyUp(KeyCode.S))
{
anim.SetBool("IsWalkingBack", false);
}
if (Input.GetKeyUp(KeyCode.D))
{
anim.SetBool("IsWalkingRight", false);
}
if (Input.GetKeyUp(KeyCode.UpArrow))
{
anim.SetBool("IsWalkingForward", false);
}
if (Input.GetKeyUp(KeyCode.LeftArrow))
{
anim.SetBool("IsWalkingLeft", false);
}
if (Input.GetKeyUp(KeyCode.DownArrow))
{
anim.SetBool("IsWalkingBack", false);
}
if (Input.GetKeyUp(KeyCode.RightArrow))
{
anim.SetBool("IsWalkingRight", false);
}
}
void OnCollisionStay()
{
isGrounded = true;
}
void OnCollisionExit()
{
isGrounded = false;
}
}