So I'm currently learning Unity 3D but I stuck on a problem.
So Iv'e done this code that the player moves with WASD keys. The movement works fine.
I tried to aply some rotation, that way the player can turn back or move to different positions.
But the problem is, I put the rotarion and the player turns but when he does he swap W for S, so basically if I turn back, when I press W to go forward he go backward and when I press S instead of going Backward he goes Forward.
I don't to make a lot of changes in my code because I think it's very "basic" right now and easy to understand. So if someone can explain what I'm doing wrong I would appreciate.
using System.Collections.Generic;
using UnityEngine;
//[RequireComponent(typeof(Rigidbody))]
public class PlayerMov : MonoBehaviour
{
//Player mov speed
float MovSpeed = 10f;
//Player jump, jumpforce, check if is on the ground and rb(rigidbody component)
public Vector3 jump;
public float jumpForce = 2.0f;
public bool isGrounded;
Rigidbody rb;
public float TurnSpeed = 100f;
void Start()
{
rb = GetComponent<Rigidbody>();
jump = new Vector3(0.0f, 2.0f, 0.0f);
}
void OnCollisionStay()
{
isGrounded = true;
}
void Update()
{
if (Input.GetKey(KeyCode.W))
{
transform.position -= Vector3.forward * MovSpeed * Time.deltaTime;
//transform.Translate(Vector3.forward * MovSpeed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.A))
{
transform.position -= Vector3.left * MovSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.S))
{
transform.position -= Vector3.back * MovSpeed * Time.deltaTime;
//transform.Translate(-Vector3.forward * MovSpeed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.D))
{
transform.position -= Vector3.right * MovSpeed * Time.deltaTime;
transform.Rotate(Vector3.up * TurnSpeed * Time.deltaTime);
}
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
rb.AddForce(jump * jumpForce, ForceMode.Impulse);
isGrounded = false;
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(Vector3.up * TurnSpeed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(Vector3.up * TurnSpeed * Time.deltaTime);
}
Why not use the Translate method? Please see its documentation. You can define a which space you want the transform to move in (global or local)
https://docs.unity3d.com/ScriptReference/Transform.Translate.html
As a side note: why check for each separate key? Using Input.GetAxis("Horizontal") and Input.GetAxis("Horizontal") vertical would be simpler.
Related
The rotation speed of my character is different while testing in the editor and in Built version of the game. By a pretty significant amount. This is the script in question.
using UnityEngine;
public class PlayerCam : MonoBehaviour
{
public float SensX;
public float SensY;
public Transform orientation;
float xRotation;
float yRotation;
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
void Update()
{
float mouseX = Input.GetAxisRaw("Mouse X") * Time.deltaTime * SensX;
float mouseY = Input.GetAxisRaw("Mouse Y") * Time.deltaTime * SensY;
yRotation += mouseX;
xRotation -= mouseY;
orientation.rotation = Quaternion.Euler(0, yRotation, 0);
transform.rotation = Quaternion.Euler(xRotation, yRotation, 0);
}
}
If I stop multiplying it by Time.deltaTime it seems to work fine but then I cannot stop the rotation from happening when I want to pause the game in menu's using Time.timeScale = 0
If I change it from Update() to FixedUpdate() the rotation is extreemly jittery and doesn't work at all
Sorry for what is probably a dumb mistake but I don't understand what I am doing wrong.
I'm using a 3d character controller for my player but I can't figure out how to stop it from being able to jump up steep slopes. I've looked around and could only find one video that fixes the issue but after the character slides down the slope it stays locked in the slide movement function and I'm not really sure why. I've edited out the code that doesn't matter for clarity, pls lmk if u know how to fix this!
Heres the code:
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
public float speed = 12f;
public float gravity = -9.81f;
public float jumpHeight = 3f;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
//SLOPES
private float groundRayDistance = 1;
private RaycastHit slopeHit;
public float slopeSlideSpeed;
Vector3 velocity;
bool isGrounded;
// Update is called once per frame
void Update()
{
HandleMovement();
HandleAnimations();
if(OnSteepSlope())
{
SteepSlopeMovement();
}
}
private void HandleMovement()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if (isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
move = transform.right * x + transform.forward * z;
controller.Move(move * speed * Time.deltaTime);
if (Input.GetButtonDown("Jump") && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity = AdjustVelocityToSlope(velocity);
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
private Vector3 AdjustVelocityToSlope(Vector3 velocity)
{
var ray = new Ray(transform.position, Vector3.down);
if(Physics.Raycast(ray, out RaycastHit hitInfo, 0.2f))
{
var slopeRotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal);
var adjustedVelocity = slopeRotation * velocity;
if(adjustedVelocity.y < 0)
{
return adjustedVelocity;
}
}
return velocity;
}
private bool OnSteepSlope()
{
if (!isGrounded) return false;
if (Physics.Raycast(transform.position, Vector3.down, out slopeHit, (controller.height / 2) + groundRayDistance))
{
float slopeAngle = Vector3.Angle(slopeHit.normal, Vector3.up);
if (slopeAngle > controller.slopeLimit) return true;
}
return false;
}
private void SteepSlopeMovement()
{
Vector3 slopeDirection = Vector3.up - slopeHit.normal * Vector3.Dot(Vector3.up, slopeHit.normal);
float slideSpeed = speed + slopeSlideSpeed + Time.deltaTime;
velocity = slopeDirection * -slideSpeed;
velocity.y = velocity.y - slopeHit.point.y;
}
OnSteepSlope() wasnt returning false so I put the return false statement in an else loop, I also changed how I was moving the character in SteepSlopeMovement by using controller.Move() instead of directly changing the velocity. It works great now
I see you've got dot product check inside of SteepSlopeMovement might be useful to draw some rays with gizmos of the player's down and the normal of the surface. Then you can adjust the threshold value for when you can jump.
(Parameter values are not being sent from script to blend tree resulting in not following animation with movement.) I have animations set up in a blend tree that has a 1d type blend tree. I have it set to custom thresholds with an idle animation as the base state then the blend tree has three motions: a strafe left, right, and a walk forward. When I move forward the player does not do the animations told in the tree and I am almost certain it is the script.
I am also using Unity 1212.1.2f1 and for my scripts I have been using Microsoft Visual Studio if it matters.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
public float speed = 12f;
public float gravity = -9.81f;
public float jumpHeight = 3f;
public float rotationSpeed = 75.0f;
public Animator anim;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
Vector3 velocity;
bool isGrounded;
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
float translation = Input.GetAxis("Vertical") * speed;
float rotation = Input.GetAxis("Horizontal") * rotationSpeed;
translation *= Time.deltaTime;
rotation *= Time.deltaTime;
if (isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
if ((Input.GetButtonDown("Jump")) && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move * speed * Time.deltaTime);
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
{
anim.SetFloat("Vertical", Input.GetAxis("Vertical"));
anim.SetFloat("Horizontal", Input.GetAxis("Horizontal"));
}
}
}
first i think you could try to make a new var :
private Rigidbody2D rg;
then add this in Start ()
rg = Player.GetComponent<Rigidbody2D>();
and Update () with this
anim.SetFloat("Vertical", rg.velocity.x);
anim.SetFloat("Horizontal", rgvelocity.x);
and sure made 2 Vertical and Horizontal in Animator parameters
I have a game object that moves and rotates. I want the camera to stay behind the object all the time, so when the user presses w, it will look like the gameobject moves forward.
This is my skript for the camera movement.
public Transform target;
public Vector3 offset;
public void FixedUpdate()
{
transform.position = target.TransformPoint(offset);
transform.LookAt(target);
}
But I camera is not rotating around the player fast enough, so it looks like he is moving sidewards.
This is my player movement script, but I don't see any mistake in there.
public float smoothSpeed = 0.125f;
public float forwardSpeed;
public float sideSpeed;
// Start is called before the first frame update
void Start()
{
}
void FixedUpdate()
{
if (Input.GetKey("w"))
{
Vector3 movement = transform.rotation * Vector3.forward / (100 / forwardSpeed);
transform.Translate(movement);
}
else if (Input.GetKey("s"))
{
Vector3 movement = transform.rotation * Vector3.back / (100 / sideSpeed);
transform.Translate(movement);
}
else if (Input.GetKey("a"))
{
Vector3 movement = transform.rotation * Vector3.left / (100 / sideSpeed);
transform.Translate(movement);
}
else if (Input.GetKey("d"))
{
Vector3 movement = transform.rotation * Vector3.right / (100 / sideSpeed);
transform.Translate(movement);
}
else if (Input.GetKey("e"))
{
transform.Rotate(0, 1, 0);
}
else if (Input.GetKey("q"))
{
transform.Rotate(0, -1, 0);
}
}
Thanks for your help]1
When the object moves sidewards it should move forwards.
Here are my settings in Unity:
I add a CharacterController to Player.But when I test the jump function,I find that the Player will move upwards immediately.
if (Player.isGrounded)
{
if (jump)
{
Move.y = JumpSpeed;
jump = false;
Player.Move (Move * Time.deltaTime);
}
}
Move += Physics.gravity * Time.deltaTime * 4f;
Player.Move (Move * Time.fixedDeltaTime);`
You are calling Player.Move() twice in one frame. This might be an issue.
You are adding gravity to Move vector, which means it will always go upward when you call this code.
naming a variable like Move is not a good convention. It creates confusion while reading because there is already a method of same name. change it to moveDirection.
Here is sample code:
public class ExampleClass : MonoBehaviour {
public float speed = 6.0F;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
private Vector3 moveDirection = Vector3.zero;
CharacterController controller;
void Start()
{
controller = GetComponent<CharacterController>();
}
void Update() {
if (controller.isGrounded) {
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
if (Input.GetButton("Jump"))
moveDirection.y = jumpSpeed;
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
}
hope this helps.