I am not sure why but I am starting a new project in which a player moves with WASD and points towards the mouse pointer. This is all the code I have so far as It is only early into development but any help would be nice. Here is a little pic of what I currently have on my player...
ANY HELP WILL BE AMAZING!
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float moveSpeed = 5f;
public Rigidbody2D rb;
Vector2 movement;
// Update is called once per frame
void Update()
{
movement.x = Input.GetAxisRaw("Horizontal");
movement.y = Input.GetAxisRaw("Vertical");
Vector3 mousePosition = Input.mousePosition;
mousePosition = Camera.main.ScreenToWorldPoint(mousePosition);
Vector2 direction = new Vector2(
mousePosition.x - transform.position.x,
mousePosition.y - transform.position.y
);
transform.up = direction;
}
private void FixedUpdate()
{
rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
}
}
Set the gravity scale to 0 or set Rigidbody2D body type to Kinematic.
Kinematic rigidbodies can only be moved via script and are not participated in regular physics unlike dynamic rigidbody. So if you don't want some 'automatic' behaviors always use kinematic body type, otherwise if only problem is automatic 'moving down' issue then set gravity scale to 0 and that's all.
I think both will work in your case. And also here is some further info
Related
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()
I Have a gun that spawn a projectile that bounces of colliders (a Ricochet). It is supposed to be shooting to the direction of where the gun is facing but what I am getting is the projectile always shoots 45 degrees upwards to the right I know this is because of my constant declared vector 2.
I tried using Vector2.up but it prevents the projectile to do the ricochet effect because it always wants to go upwards.
How should I implement those things? I just want the projectile to shoot to the direction where my gun is facing and bounces of on colliders. This is a 2D game btw. I have my codes attached below so you can see. Thanks!
Projectile Script:
private Rigidbody2D rb;
public static bool canMove = true;
void Start()
{
rb = GetComponent<Rigidbody2D>();
rb.velocity = new Vector2(10f, 10f);
}
void Update()
{
//transform.Translate(Vector2.up * speed * Time.deltaTime);
if (canMove)
{
rb.isKinematic = false;
}
else if (!canMove)
{
rb.isKinematic = true;
}
}
Gun Script:
float offset = -90f;
public GameObject projectile;
public Transform shotPoint;
public GameObject child;
void Start()
{
}
void Update()
{
Vector3 diff = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
float rotZ = Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(0f, 0f, rotZ + offset);
if (Input.GetMouseButtonDown(0))
{
Instantiate(projectile, shotPoint.position, transform.rotation);
Projectile.canMove = true;
}
}
The Rigodbody.velocity is in World-Space coordinates.
When you pass in
rb.velocity = new Vector2(10f, 10f);
it will go in world space 10 in X and 10 in Y direction.
In order to pass it in as local coordinates in general you can not always rely on Tramsform.InverseTransformDirection as suggested here since the Transform component. In this specific case it might work but in general you set velocities in FixedUpdate and in that moment the Transform component might not be updated yet!
But the Rigidbody2D component is so in general you can use Rigidbody2D.GetRelativeVector in order to convert a local vector relative to the Rigidbody into world coordinates:
// Might also be Vector.up depending on your setup
rb.velocity = rb.GetRelativeVector(Vector2.right * speed);
Note: it would be better you make
[SerializeField] private Rigidbody2D rb;
and already reference it via the Inspector. Then you can get rid of the expensive GetComponent call.
Because you are telling it to do so.
rb.velocity = new Vector2(10f, 10f);
10 to the right, and 10 upwards.
Unless your projectile has a constant force applied to it, like a missile, get rid of everything related to forces or velocity in the projectile script. It will do you no good.
Then, on the gun script:
//...
if (Input.GetMouseButtonDown(0)) {
var projectileInstance = Instantiate(projectile, shotPoint.position, transform.rotation);
var rigidbody = projectileInstance.GetComponent<Rigidbody2D>();
rigidbody.velocity = transform.TransformDirection(yourDirectionVector);
Projectile.canMove = true;
}
Where Transform.TransformDirection is what makes yourDirectionVector, which is a direction relative to the gun, be transformed into one relative to world-space.
enter image description hereI have made controls for my character to move along the X axis. They seem to be working fine but my character keeps moving left and I'm not sure why or what I have missed.I have posted code from the two separate scripts
I have rechecked his code several times.I have checked to see if my arrow keys, numpad keys and WASD are sticking or any other.
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class PlayerMotor : MonoBehaviour
{
private Vector3 velocity = Vector3.zero;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
//gets a movement vector
public void Move (Vector3 _velocity)
{
velocity = _velocity;
}
//run every physics iteration
void FixedUpdate()
{
PerformMovement();
}
//perform movement based on velocity variable
void PerformMovement ()
{
if (velocity != Vector3.zero)
{
rb.MovePosition(rb.position + velocity * Time.fixedDeltaTime);
}
}
}
And the controller:
using UnityEngine;
[RequireComponent(typeof(PlayerMotor))]
public class PlayerController : MonoBehaviour
{
[SerializeField] //makes speed show up in inspector even if set to private
private float speed = 5f;
private PlayerMotor motor;
void Start ()
{
motor = GetComponent<PlayerMotor>();
}
void Update()
{
//Calculate movement velocity as a 3D vector
float _xMov = Input.GetAxisRaw("Horizontal");
float _zMov = Input.GetAxisRaw("Vertical");
Vector3 _movHorizontal = transform.right * _xMov;
Vector3 _movVertical = transform.forward * _zMov;
//final movement vector
Vector3 _velocity = (_movHorizontal + _movVertical).normalized * speed;
//apply movement
motor.Move(_velocity);
}
}
I expect 0 output when not pressing buttons but it seems to make me move to the left at speed of 5
You have a controller connected and reporting a slight movement in one direction. Use Input.GetAxis instead of Input.GetAxisRaw to let Unity handle deadzone detection. This way, nearly neutral inputs will be treated as neutral inputs.
void Update()
{
//Calculate movement velocity as a 3D vector
float _xMov = Input.GetAxis("Horizontal");
float _zMov = Input.GetAxis("Vertical");
Vector3 _movHorizontal = transform.right * _xMov;
Vector3 _movVertical = transform.forward * _zMov;
//final movement vector
Vector3 _velocity = (_movHorizontal + _movVertical).normalized * speed;
//apply movement
motor.Move(_velocity);
}
I am trying to make a game where a ball will be ricocheting off several different colliders on screen. Based on what I researched I got some code that seemed to make sense at first but does not seem to work at all. I am testing it out just by having the ball fall down onto a 2D floor with a box collider attached to it. However once it collides with the floor it just stops there and doesn't bounce back up. I tried disabling "Queries Start in Colliders" in the project settings and offsetting the origin position of the RaycastHit2D so that it would not detect the collider its attached to but that still didn't work. I don't think the RaycastHit2D is working at all because it doesn't even display anything in the console. Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyBehavior : MonoBehaviour {
Rigidbody2D rigidbody;
public Vector2 startPos;
public float speed;
public float hitOffset;
Vector3 vector = new Vector3(0, 5,0); //used to offset origin point of RaycastHit2D hit
private void OnEnable()
{
rigidbody = GetComponent<Rigidbody2D>();
this.transform.position = startPos;
}
private void Update()
{
transform.Translate(Vector2.down * speed * Time.deltaTime);
RaycastHit2D hit = Physics2D.Raycast(transform.position + vector, - transform.up, speed * Time.deltaTime + hitOffset);
Debug.DrawRay(transform.position, -transform.up, Color.red);
Ray2D ray = new Ray2D(transform.position, -transform.up);
if (hit)
{
Debug.Log(speed * Time.deltaTime + hitOffset);
Debug.Log(hit.collider.name);
Vector2 reflectDir = Vector2.Reflect(ray.direction,hit.normal);
float rotation = Mathf.Atan2(reflectDir.y, reflectDir.x) * Mathf.Rad2Deg;
transform.eulerAngles = new Vector3(0, 0, rotation);
}
}
}
Is my math bad? Any help is very appreciated, thanks.
I am currently making a 2D top down survival game. I have coded the player controller and it works good other than one issue that bugs the crap out of me! My character doesn't stop moving (or decelerates very slowly) whenever I stop pressing the movement keys. How can I make it so that it stops immediately, if not nearly immediately? Any tips help thanks!
Here is the code i'm using!
using UnityEngine;
using System.Collections;
public class CharacterMovement : MonoBehaviour{
public float speed;
private Rigidbody2D rb2d;
void Start ()
{
rb2d = GetComponent<Rigidbody2D> ();
}
void FixedUpdate()
{
float moveHorizontal = Input.GetAxisRaw ("Horizontal");
float moveVertical = Input.GetAxisRaw ("Vertical");
Vector2 movement = new Vector2 (moveHorizontal, moveVertical);
rb2d.AddForce (movement * speed);
}
}
I have figured out a way to increase the Deceleration. I scrapped my code and changed the mechanics so that the Character follows the mouse and moves forward with the "W" key or the up arrow. This smoothed the directional changes and made gameplay more enjoyable, as for the deceleration, I solved the problem by making the Linear Drag in the rigidbody2D inspector more than one and increasing the speed to make up for velocity loss.
Here is my code for future answer seekers!
using UnityEngine;
using System.Collections;
public class CharacterMovement : MonoBehaviour{
public float speed;
private Rigidbody2D rbtd;
void Start ()
{
rbtd = GetComponent<Rigidbody2D> ();
}
void FixedUpdate()
{
var mousePosition = Camera.main.ScreenToWorldPoint (Input.mousePosition);
Quaternion rot = Quaternion.LookRotation(transform.position - mousePosition,
Vector3.forward);
transform.rotation = rot;
transform.eulerAngles = new Vector3 (0, 0, transform.eulerAngles.z);
rbtd.angularVelocity = 0;
float input = Input.GetAxis ("Vertical");
rbtd.AddForce (gameObject.transform.up * speed * input);
}
}