2D Movement Bug in Unity - c#

I'm trying to make a 2D Space Shooter game in Unity but stumbled upon a bug that needs fixing. I'm using Unity 2021.1.0f1 and the new Input System in Unity and I'm trying to implement movement for my character. When I press the WASD keys, my character for some reason moves 15 units on every press. I don't want that, I want smooth movement for my character. Here's my code:
using UnityEngine;
using UnityEngine.InputSystem;
public class Ship : MonoBehaviour
{
private Keyboard _keyboard = Keyboard.current;
[SerializeField] private float speed = 0.25f;
[SerializeField] private GameObject projectile;
[SerializeField] private Rigidbody2D rigidbody;
private void Start()
{
if (speed == null)
{
Debug.Log("Please assign a a value to \"speed\".");
}
if (rigidbody == null)
{
Debug.Log("Please assign a a value to \"rigidbody\".");
}
if (projectile == null)
{
Debug.Log("Please assign a a value to \"projectile\".");
}
}
public void OnMove(InputAction.CallbackContext context)
{
Vector2 movementVector = context.ReadValue<Vector2>();
Vector3 move = Quaternion.Euler(0.0f, transform.eulerAngles.y, 0.0f) * new Vector3(movementVector.x, movementVector.y, 0.0f);
transform.position += move * speed;
}
public void OnFire(InputAction.CallbackContext context)
{
Vector2 spawnPosition = new Vector2(transform.position.x, 0.5f);
if (context.performed)
{
Instantiate(projectile, spawnPosition, Quaternion.identity);
}
}
}
Anyone?

I have been working on the same project lately and I used the following code for the movement of my spaceship and it moves smoothly :
void C_Movement(){
//Input controller (direction)
float horizontalInput = Input.GetAxis("Horizontal");
float verticalInput = Input.GetAxis("Vertical") ;
Vector3 directionX = new Vector3(horizontalInput,0,0) ;
transform.Translate(directionX* Time.deltaTime * 13) ;
Vector3 directionY = new Vector3(0,verticalInput,0) ;
transform.Translate(directionY* Time.deltaTime * 13) ;
}

Related

Unity player movement on moving planet

I am making a game involving orbital physics. I was successfully able to implement this with a slightly modified version of Brackeys gravity tutorial https://youtu.be/Ouu3D_VHx9o, this is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class gravity : MonoBehaviour
{
public GameObject self;
public Rigidbody rb;
public Vector3 initialVelocity;
const float G = 66.74f;
public static List<gravity> Attractors;
public bool isAttractable;
private void Awake()
{
rb.AddForce(initialVelocity);
}
private void FixedUpdate()
{
//planets
if (isAttractable == false)
{
foreach (gravity attractor in Attractors)
{
if (attractor != this)
Attract(attractor);
}
}
//players, spaceships, astroids, ect
if (isAttractable == true)
{
foreach (gravity attractor in Attractors)
{
if (attractor != this)
Attract(attractor);
}
}
}
void OnEnable()
{
if( isAttractable == false)
{
if (Attractors == null)
Attractors = new List<gravity>();
Attractors.Add(this);
}
}
void OnDisable()
{
if (isAttractable == false)
{
Attractors.Remove(this);
}
}
void Attract(gravity objToAttract)
{
Rigidbody rbToAttract = objToAttract.rb;
Vector3 direction = -1 * (rb.position - rbToAttract.position);
Vector3 Force = direction.normalized * (G * ((rb.mass * rbToAttract.mass) / direction.sqrMagnitude));
rb.AddForce(Force);
}
public GameObject GetClosestPlanet()
{
GameObject close = null;
float minDist = Mathf.Infinity;
foreach (gravity attracor in Attractors)
{
float dist = Vector3.Distance(attracor.transform.position, transform.position);
if (dist < minDist)
{
close = attracor.transform.gameObject;
minDist = dist;
}
}
return close;
}
}
Then for player movement I used (and modified) Sebastian Lagues tutorial https://youtu.be/TicipSVT-T8,
this resulted in this code for the player controller:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerController : MonoBehaviour
{
public float mouseSensitivityX = 250f;
public float mouseSensitivityY = 250f;
Transform cameraT;
float verticalLookRot;
private Rigidbody rb;
Vector3 moveAmount;
Vector3 smootgMoveVelocity;
public float moveSpeed = 15;
public float jumpForce = 220;
public LayerMask groundedMask;
public bool grounded;
public GameObject currentPlanet;
private gravity playerGravity;
private void Awake()
{
rb = GetComponent<Rigidbody>();
playerGravity = GetComponent<gravity>();
Cursor.lockState = CursorLockMode.Locked;
cameraT = Camera.main.transform;
}
void Update()
{
currentPlanet = playerGravity.GetClosestPlanet();
//camera
transform.Rotate(Vector3.up * Input.GetAxis("Mouse X") * Time.deltaTime * mouseSensitivityX);
verticalLookRot += Input.GetAxis("Mouse Y") * Time.deltaTime * mouseSensitivityY;
verticalLookRot = Mathf.Clamp(verticalLookRot, -60, 60);
cameraT.localEulerAngles = Vector3.left * verticalLookRot;
//move input
Vector3 moveDir = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized;
Vector3 targetMoveAmount = moveDir * moveSpeed;
moveAmount = Vector3.SmoothDamp(targetMoveAmount, targetMoveAmount, ref smootgMoveVelocity, .15f);
//level on planet
if(currentPlanet != null)
{
transform.rotation = Quaternion.FromToRotation(transform.up, (transform.position - currentPlanet.transform.position).normalized) * transform.rotation;
}
//jump
if (Input.GetButtonDown("Jump"))
{ if(grounded)
{
rb.AddForce(transform.up * jumpForce);
print("u jumped");
}
}
}
private void FixedUpdate()
{
//move
rb.MovePosition(rb.position + transform.TransformDirection(moveAmount) * Time.fixedDeltaTime);
//check if on ground
Ray ray = new Ray(transform.position, -transform.up);
RaycastHit hit;
grounded = Physics.Raycast(ray, out hit, transform.localScale.y + 1.1f, groundedMask);
}
}
Now for the issue, this systems works fine when the planet the player is walking on is stationary. As in there are no other attracting bodys in the system and the planet has no initial velocity. However if the planet is moving the player will bounce up and down uncontrollably and will not be able to walk a certain distance away from the planets farthest point from its direction of movement. Here is a recording of this: https://youtu.be/noMekosb7CU
Does anyone know what is causing the bouncing and walking restrictions and how I can fix it?
Some notes on suggested solutions that haven't worked:
-set the planet as the players parent object, same results
-increase players mass, same results
-set the players velocity to += the planets velocity, same results or player goes into infinity
For me it seems to be working "correctly".
Looking like your player is attracted correctly and when the planet moves, your player is quickly moving towards the planet.
I think you could temporarily assign the player as a child gameobject to the planet he's walking on and he should probably move correctly along the planet coordinates and not on global coordinates. (If it works, you could just always assign the player as a child gameObject to every new planet that he visits)

How to make my character look in the direction of the camera in Unity 3d?

My character has a chinemachine camera attached to it and it is moving perfectly fine. But when I move my mouse to change the camera direction it is not looking in that direction. And I can't figure out how to make it look in that direction.
I have a reference to the original camera at the top of the script by the name cam.
The script has different functions for movement, rotation, animation, etc.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//so that unity recognises the callbacks ctx passed to the movementinput
using UnityEngine.InputSystem;
public class AnimationAndMovController : MonoBehaviour
{
public Transform cam;
public float speed;
//here we are creadting three vars for the animation
//vector2 currentMovementInput stores the input axis of the player
//vector3 store the current position of the player
PlayerInput playerInput;
CharacterController characterController;
Animator animator;
Vector2 currentMovementInput;
Vector3 currentMovement;
Vector3 currentRunMovement;
Vector3 moveDir;
bool isMovementPressed;
bool isRunPressed;
float rotationFactor = 15.0f;
// float turnSmoothtime = 0.1f;
// float turnSmoothVelocity ;
float runMultiplier = 4.0f;
int walkHash ;
int runHash ;
//runs before start function
void Awake(){
playerInput = new PlayerInput();
characterController = GetComponent<CharacterController>();
animator = GetComponent<Animator>();
// walkHash = Animator.StringToHash("Walking");
// runHash = Animator.StringToHash("run");
//now instead of writing the logic three times we pass the callback ctx to the movementInput() function
playerInput.CharacterControls.Move.started += movementInput;
playerInput.CharacterControls.Move.canceled += movementInput;
playerInput.CharacterControls.Move.performed += movementInput;
playerInput.CharacterControls.Run.started += handleRun;
playerInput.CharacterControls.Run.canceled += handleRun;
}
void handleRun(InputAction.CallbackContext ctx){
isRunPressed = ctx.ReadValueAsButton();
}
//we are going to handle rotations with quaternions
void handleRotation(){
Vector3 positionToLookAt;
positionToLookAt.x = currentMovement.x;
positionToLookAt.y = 0.0f ;
positionToLookAt.z = currentMovement.z;
Vector3 direction = new Vector3(positionToLookAt.x, 0.0f, positionToLookAt.z).normalized;
Quaternion currentRotation = transform.rotation;
//we take the current rotation and the target rotation and slerp them *FYI : Im still not sure how slerp works
if(isMovementPressed){
Quaternion targetRotation = Quaternion.LookRotation(positionToLookAt);
transform.rotation = Quaternion.Slerp(currentRotation, targetRotation, rotationFactor * Time.deltaTime);
}
}
//we are passing the callback ctx to this function so that we dont have to call the function everytime we start, cancel or perform the movement
void movementInput(InputAction.CallbackContext ctx){
//we are setting the movement input to the axis of the player
currentMovementInput = ctx.ReadValue<Vector2>();
currentMovement.x = currentMovementInput.x;
//we are setting the z axis to the y axis of the player because we move y axis on keyboard or joystick but in game we move in z axis
currentMovement.z = currentMovementInput.y;
//now we are setting the run movement to the current movement
currentRunMovement.x = currentMovementInput.x * runMultiplier;
currentRunMovement.z = currentMovementInput.y * runMultiplier;
isMovementPressed = currentMovementInput.x != 0 || currentMovementInput.y != 0;
}
void handleAnimation(){
bool walk = animator.GetBool("walking");
bool run = animator.GetBool("run");
if(isMovementPressed && !walk){
animator.SetBool("walking", true);
}
else if(!isMovementPressed && walk){
animator.SetBool("walking", false);
}
if((isMovementPressed && isRunPressed) && !run){
animator.SetBool("run", true);
}
else if((!isMovementPressed || !isRunPressed)&& run){
animator.SetBool("run", false);
}
}
void handleGravity(){
//we are setting the gravity to -9.8f because we are moving in y axis
if(characterController.isGrounded){
float groundGravity = -0.05f;
currentMovement.y = groundGravity;
currentRunMovement.y = groundGravity;
}
else{
float gravity = -9.8f;
currentMovement.y += gravity * Time.deltaTime;
currentRunMovement.y += gravity * Time.deltaTime;
}
}
// Update is called once per frame
void Update()
{
handleAnimation();
handleRotation();
handleGravity();
if(isRunPressed){
characterController.Move(currentRunMovement * Time.deltaTime);
}
else{
characterController.Move(currentMovement * Time.deltaTime);
}
}
//we are checking if the player script gets enabled or disabled and accordingly we are enabling or disabling the player input
void OnEnable(){
playerInput.CharacterControls.Enable();
}
void OnDisable(){
playerInput.CharacterControls.Disable();
}
}
That quite a lot of code to dive into.
I'd try:
Quaternion cameraRot = Camera.Main.transform.rotation;
transform.rotation = cameraRot;
Or if you have a target Quaternion.LookRotation:
Vector3 relativePos = target.position - transform.position;
// the second argument, upwards, defaults to Vector3.up
Quaternion rotation = Quaternion.LookRotation(relativePos, Vector3.up);
transform.rotation = rotation;
Hope that helps
Use Transform.LookAt, which points a Game Object's rotation towards a target's position.
In your case, this would be
transform.LookAt(cam);
here is the code that I use..
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveCamera : MonoBehaviour
{
public float sensitivity = 1000f;
public float xRotation = 0f;
public Transform playerBody;
public Quaternion localRotate;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
float MX = Input.GetAxis("Mouse X")*sensitivity*Time.deltaTime;
float MY = Input.GetAxis("Mouse Y")*sensitivity*Time.deltaTime;
xRotation -= MY;
xRotation = Mathf.Clamp(xRotation,-90f,90f);
transform.localRotation = Quaternion.Euler(xRotation,0f,0f);
localRotate = transform.localRotation;
playerBody.Rotate(Vector3.up * MX);
}
}
the player body you see is the player object to you character...
note that the camera is use is not In. cinema chine and is inside of the player...

change direction into random direction on collision Unity2D

I'm new to unity and I'm trying to create a game where there's a ball that can move
in the direction by dragging and releasing on the screen and that change direction randomly when hitting a prefab, I already created that kind of movement but couldn't figure out how to make the ball change direction randomly when hitting the prefab.
Sorry if this isn't the right place to ask.
Here's my script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
[SerializeField] private float power = 2;
[SerializeField] private Vector2 minPow, maxPow;
public Vector3 force;
private Vector3 startPoint, endPoint;
private Rigidbody2D rb;
private Camera cam;
private Aim aim;
void Start()
{
cam = Camera.main;
rb = GetComponent<Rigidbody2D>();
aim = GetComponent<Aim>();
}
void Update()
{
if(Input.GetMouseButtonDown(0))
{
startPoint = cam.ScreenToWorldPoint(Input.mousePosition);
startPoint.z = 15;
}
if(Input.GetMouseButton(0))
{
Vector3 currentPos = cam.ScreenToWorldPoint(Input.mousePosition);
startPoint.z = 15;
aim.RenderLine(startPoint, currentPos);
}
if(Input.GetMouseButtonUp(0))
{
endPoint = cam.ScreenToWorldPoint(Input.mousePosition);
endPoint.z = 15;
force = new Vector3(Mathf.Clamp(startPoint.x - endPoint.x, minPow.x, maxPow.x), Mathf.Clamp(startPoint.y - endPoint.y, minPow.y, maxPow.y));
rb.AddForce(force * power, ForceMode2D.Impulse);
aim.EndLine();
}
}
public void BoostUp(float pow)
{
rb.velocity *= pow;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Boost : MonoBehaviour
{
[SerializeField] float pow;
private void OnTriggerEnter2D(Collider2D other)
{
if(other.tag == "Player")
{
Player player = other.GetComponent<Player>();
if(player != null)
{
player.BoostUp(pow);
Destroy(this.gameObject);
}
}
}
}
You can get a random angle in radians using Random.Range(0f, 2f * Mathf.PI) and then pass it to Mathf.Cos and Mathf.Sin functions to get a direction with that angle:
float angle = Random.Range( 0f, 2f * Mathf.PI );
Vector2 direction = new Vector2( Mathf.Cos( angle ), Mathf.Sin( angle ) );

Player gravity turns off while i move in Unity

I am quite new to unity and I have two scripts, one for gravity and one for player movement as the names suggest. The reason I am using a gravity script is that the third person movement doesn't support using a rigidbody with position and rotation enabled, so I have frozen the position and the rotation inside the rigidbody (which turns off gravity in the rigidbody). I made the Gravity script myself but I followed a tutorial on the player movement script because I have no idea how to make third person movement so I don't really know what is going on in the movement script.
Movement script:
public class ThirdPersonMovement : MonoBehaviour
{
public CharacterController controller;
public Transform cam;
public float speed = 6f;
public float turnSmoothTime = 0.1f;
float turnSmoothVelocity;
void Update()
{
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
UnityEngine.Vector3 direction = new UnityEngine.Vector3(horizontal, 0f, vertical).normalized;
if (direction.magnitude >= 0.1f)
{
float targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg + cam.eulerAngles.y;
float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
transform.rotation = UnityEngine.Quaternion.Euler(0f, angle, 0f);
UnityEngine.Vector3 moveDir = UnityEngine.Quaternion.Euler(0f, targetAngle, 0f) * UnityEngine.Vector3.forward;
controller.Move(moveDir.normalized * speed * Time.deltaTime);
}
}
}
Gravity script:
public class gravityScript : MonoBehaviour
{
public float GravitySpeed = -0.03f;
public bool GravityCheck = false;
void OnCollisionEnter(Collision col)
{
if (col.gameObject.name == "Terrain0_0")
{
GravityCheck = true;
}
}
void OnCollisionExit(Collision col)
{
GravityCheck = false;
}
void Update()
{
if (GravityCheck == false)
{
transform.Translate(0, GravitySpeed, 0);
}
}
}
Thank you in advance :)
I don't know what happened but when I opened it today (the day after posting) it was working fine. It was likely just a bug that got fixed after a restart.

Is There A Way To Use The Axes Input From A Joystick To Rotate A GameObject Around A Point?

I have a gun and a player (cube) on a 2d Unity Project. I have made a script that rotates the gun around the player depending on the position of the mouse on the screen. I was wondering if I could adapt this script to make the gun rotate depending on the Horizontal and Vertical values of a joystick?
this is what I have so far (don't worry about my terrible spelling):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WeaponAming : MonoBehaviour
{
public GameObject bullet;
public GameObject spawn;
public ParticleSystem mf1;
public ParticleSystem mf2;
public float speed = .5f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
turning();
if (Input.GetButtonDown("XButton"))
{
shoot();
}
}
void turning()
{
Vector3 mousePos = Input.mousePosition;
mousePos.z = 10;
mousePos = Camera.main.ScreenToWorldPoint(mousePos);
Vector2 direc = new Vector2(mousePos.x - transform.position.x, mousePos.y - transform.position.y);
transform.right = direc;
}
void shoot()
{
mf1.Play();
mf2.Play();
GameObject projectile = (GameObject)Instantiate(bullet, spawn.transform.position, Quaternion.identity);
projectile.transform.right = transform.right;
}
}
You can make a direction from Input.GetAxisRaw("Horizontal") and Input.GetAxisRaw("Horizontal") if at least one is nonzero, and then set the transform's right to that direction:
void turning()
{
float horiz = Input.GetAxisRaw("Horizontal");
float vert = Input.GetAxisRaw("Vertical");
if (horiz != 0 || vert != 0)
{
Vector2 direc = new Vector2(horiz, vert);
transform.right = direc;
}
}
If you would like to invert the controls vertically, negate vert:
void turning()
{
float horiz = Input.GetAxisRaw("Horizontal");
float vert = Input.GetAxisRaw("Vertical");
if (horiz != 0 || vert != 0)
{
Vector2 direc = new Vector2(horiz, -vert);
transform.right = direc;
}
}

Categories