Unity - rigidbody MovePosition slows down reaching the target - c#

I have a problem. I want my enemy to follow the player and try to hit it with the full speed but I cant achieve it. It appears to have faster speed value when its far away and slows down while getting closer to the player.
How to make it move at the same speed?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Dotty : MonoBehaviour
{
[SerializeField] Transform playerTarget;
Vector3 direction;
Rigidbody2D rb;
float speed = 2.2f;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
direction = playerTarget.position - transform.position;
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
rb.rotation = angle;
}
private void FixedUpdate() {
rb.MovePosition(transform.position + direction.normalized * speed);
}
}

first of all change this line :
rb.MovePosition(transform.position + direction.normalized * speed);
to this:
rb.MovePosition(transform.position + direction.normalized * speed * Time.fixedDeltaTime);
and the reason it slows down is probably because the target "Z" position is not "0" (same as player "Z" position).

Related

Unity - Player movement problem, you can fly

If you dont collide with something you can fly! its really strange, please help me if you can.
i dont know how to fix it cause i am new in it.
Here is a script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player_Movement : MonoBehaviour
{
public float speed = 4.0f;
public float gravity = -9.8f;
private CharacterController _charCont;
// Use this for initialization
void Start()
{
_charCont = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
float deltaX = Input.GetAxis("Horizontal") * speed;
float deltaZ = Input.GetAxis("Vertical") * speed;
Vector3 movement = new Vector3(deltaX, 0, deltaZ);
movement = Vector3.ClampMagnitude(movement, speed); //Limits the max speed of the player
// movement.y = gravity;
movement *= Time.deltaTime; //Ensures the speed the player moves does not change based on frame rate
movement = transform.TransformDirection(movement);
_charCont.Move(movement);
}
}
I don't know that CharacterController but it sounds like it takes the global movement vector.
After
movement = transform.TransformDirection(movement);
you should erase the Y component
movement.y = 0;

Why does transform.forward when equal to 0 when multiplied not equal to 0?

Im making movement for my camera in unity. The starting position for my camera is 0,0,0. When i press the W key the code i take the current position and multiply it by a movement speed and equal it to another vector 3 to then update the postion of the position of the camera. It works great but i cant understand why when i think about.
If my camera is initialised at 0,0,0 then why does transform.forward * movementSpeed not always eqaul 0?
This is the same for all directions i just used W as an example
Any help would be greatly appreciated as im new to unity. Thanks
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraMovement : MonoBehaviour
{
private Vector3 newPosition;
[SerializeField] private float movementSpeed;
[SerializeField] private float movementTime;
// Start is called before the first frame update
void Start()
{
newPosition = transform.position;
Debug.Log(transform.position); //prints 0.0,0.0,0.0
Debug.Log(transform.forward * movementSpeed); //prints 0.0,0.0,0.3
}
// Update is called once per frame
void Update()
{
handleKeyboardInput();
}
void handleKeyboardInput()
{
if (Input.GetKey(KeyCode.W))
{
newPosition += (transform.forward * movementSpeed);
}
if (Input.GetKey(KeyCode.A))
{
newPosition += (transform.right * -movementSpeed);
}
if (Input.GetKey(KeyCode.S))
{
newPosition += (transform.forward * -movementSpeed);
}
if (Input.GetKey(KeyCode.D))
{
newPosition += (transform.right * movementSpeed);
}
transform.position = Vector3.Lerp(transform.position, newPosition, Time.deltaTime * movementTime);
}
}
The reason your code works is becuase transform.forward and transform.right refer to the forward and right directions of you player. When you add transform.forward * speed to your newPosition, you are adding the forward direction of the player but with a magnitude (length) of your speed.
If you want to try to understand it better, you can use print(transform.forward) or print(transform.forward * speed) or do Debug.drawRay(transform.position, transform.forward)
Your code is multiplying transform.forward(0,0,1) or transform.right, both of them are not zero vectors, instead they represent the specified direction.
Vector3.forward is (0,0,1) if you want zero use Vector3.zero.

How can you move by how fast the frame rate is in unity?

So I have some code for movement in my unity 3d game like:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FPSMovement : MonoBehaviour
{
[SerializeField] float speed;
[SerializeField] float sprintMultiplier = 1.5f;
Rigidbody rb;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
float x = Input.GetAxisRaw("Horizontal");
float z = Input.GetAxisRaw("Vertical");
Vector3 moveBy = transform.right * x + transform.forward * z;
float actualSpeed = speed;
if (Input.GetKey(KeyCode.LeftShift)) {
actualSpeed *= sprintMultiplier;
}
rb.MovePosition(transform.position + moveBy.normalized * actualSpeed * Time.deltaTime);
}
}
But when the frame rate is lower you move faster then when the framerate is higher. I can't find a answer on how to fix it. I can attach a video if it is necessary. Thanks.
You have Time.deltaTime, in rb.MovePosition(transform.position + moveBy.normalized * actualSpeed * Time.deltaTime); which is the time between frames. Since lower fps causes more time between frames, it will increase your speed. This is used to make the player travel for same amount of time under different fps.

How can I make my smooth third person movement stop jittering?

So I have been stuck on player movement for 15 hours total. My player jitters while it moves. I notice that the jitters aren't bad if:
A) I put CamPos code in the same lateUpdate() Function as PlayerMovement code
B) If I lower the fixed timestep under Time in project settings (makes jitter less notable)
I want to make it so that my player doesn't jitter using the right methods. My player has isKinematic off because it causes him to go through walls. I move using rigidbody movePosition because I don't know how to use rb.velocity to make the player move in the same direction as the camera.
I am using a camera for the third person and using rigidbody for movement.
Here's my current code on the player PlayerMovement:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float speed;
public Rigidbody rb;
public Transform camPos;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
camPos = Camera.main.transform;
}
private void FixedUpdate()
{
if (Input.GetKey("w"))
rb.MovePosition(transform.position + (camPos.forward * speed));
if (Input.GetKey("s"))
rb.MovePosition(transform.position + (-camPos.forward * speed));
if (Input.GetKey("d"))
rb.MovePosition(transform.position + (camPos.right * speed));
if (Input.GetKey("a"))
rb.MovePosition(transform.position + (-camPos.right * speed));
}
}
Here's my current code on the camera CamPos:
//Hakeem Thomas
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CamPos : MonoBehaviour
{
public Transform target;
public float smoothTime = 0.5F;
private Vector3 velocity = Vector3.zero;
public GameObject player;
private float mouseX, mouseY;
public int mouseX_Speed, mouseY_Speed;
//mouseSensitivity
public int turnSpeed;
void getMouseXY()
{
mouseX += Input.GetAxis("Mouse X") * smoothTime;
mouseY -= Input.GetAxis("Mouse Y") * smoothTime;
}
void LateUpdate()
{
getMouseXY();
// Define a target position above and behind the target transform
Vector3 targetPosition = target.TransformPoint(new Vector3(0, 1.5f, -2.5f));
// Smoothly move the camera towards that target position
transform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref velocity, smoothTime);
transform.LookAt(target);
target.rotation = Quaternion.Euler((mouseY * mouseY_Speed), (mouseX * mouseX_Speed), 0);
player.transform.rotation = Quaternion.Euler(0, (mouseX * turnSpeed), 0);
}
}
I also tried using Vector3's and input Axis to move, but it makes the player move in an awkward way(Controls tied to one direction). I also tried using cinemachine and turned off all my scripts on my camera to make sure the camera wasn't jittering.
Rigidbody is the physic representation of your gameobject. The thing is you doesn't use the velocity / movement of the gameobject using dirrectly the rb.MovePosition().
But it is fine ! according to the documentation you have to enable the rigidbody "interpolation" to create a smooth transition between frames.
Hope i helped you and it will works for you !
Edit
dont forget to multiply your vector by Time.fixedDeltaTime inside FixedUpdate()

How to rotate camera around player in unity c#

I need to rotate the camera around my player gameobject while holding the left mouse button. How would I approach this?
Also, I've read a bit on Vector 3, but I don't have a full understanding of it. Anybody who could explain it would be greatly appreciated.
I've looked at youtube videos and this one is exactly the concept I was looking for. I was just having trouble applying it to my code.
I'm on a bit of a time crunch, exams are nearing and my teacher hasn't explained most things that are explained in the video.
// This is my code inside the camera which follows the ball/player
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ScriptBallCam : MonoBehaviour
{
public GameObject player;
private Vector3 offset;
void Start()
{
offset = transform.position - player.transform.position;
}
void LateUpdate()
{
transform.position = player.transform.position + offset;
}
//End of code inside camera
//Code inside of player/ball
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ScriptBall : MonoBehaviour
{
public float speed;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
rb.AddForce(movement * speed);
}
// end code
Results I'm expecting are exactly shown at 1:22 in
https://www.youtube.com/watch?v=xcn7hz7J7sI
Try this. The script goes on your camera.
Basically this script works by first getting the direction your mouse has moved in. In this case the X axis Mouse X (left/right direction). Then we take our rotation speed turnSpeed, and use it to rotate around the player by that amount of degrees using Quaternion.AngleAxis. Finally we make sure that the camera is always looking at the player by using transform.LookAt
using UnityEngine;
using System.Collections;
public class OrbitPlayer : MonoBehaviour {
public float turnSpeed = 5.0f;
public GameObject player;
private Transform playerTransform;
private Vector3 offset;
private float yOffset = 10.0f;
private float zOffset = 10.0f;
void Start () {
playerTransform = player.transform;
offset = new Vector3(playerTransform.position.x, playerTransform.position.y + yOffset, playerTransform.position.z + zOffset);
}
void FixedUpdate()
{
offset = Quaternion.AngleAxis (Input.GetAxis("Mouse X") * turnSpeed, Vector3.up) * offset;
transform.position = playerTransform.position + offset;
transform.LookAt(playerTransform.position);
}
}
There is a lot of information on this topic over here:
https://answers.unity.com/questions/600577/camera-rotation-around-player-while-following.html

Categories

Resources