C# Unity 2D Topdown Movement Script not working - c#

I have been working on a unity project where the player controls a ship. I was following along with a tutorial and have made an input script and a movement script that are tied together with unity's event system. As far as I can tell my script and the script in the tutorial are the same, but the tutorial script functions and mine doesn't.
Script to get player input
using UnityEngine;
using System.Collections;
using System;
using UnityEngine.Events;
public class PlayerInput : MonoBehaviour
{
public UnityEvent<Vector2> OnBoatMovement = new UnityEvent<Vector2>();
public UnityEvent OnShoot = new UnityEvent();
void Update()
{
BoatMovement();
Shoot();
}
private void Shoot()
{
if(Input.GetKey(KeyCode.F))
{
OnShoot?.Invoke();
}
}
private void BoatMovement()
{
Vector2 movementVector = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
OnBoatMovement?.Invoke(movementVector.normalized);
}
}
Script to move player
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class Movement : MonoBehaviour
{
public Rigidbody2D rb2d;
private Vector2 movementVector;
public float maxspeed = 10;
public float rotatespeed = 50;
private void Awake()
{
rb2d = GetComponent<Rigidbody2D>();
}
public void HandleShooting()
{
Debug.Log("Shooting");
}
public void Handlemovement(Vector2 movementVector)
{
this.movementVector = movementVector;
}
private void FixedUpdate()
{
rb2d.velocity = (Vector2)transform.up * movementVector.y * maxspeed * Time.deltaTime;
rb2d.MoveRotation(transform.rotation * Quaternion.Euler(0, 0, -movementVector.x * rotatespeed * Time.fixedDeltaTime));
}
}
Any help would be appreciated!

You need to attach your Handlers (HandleShooting and Handlemovement) to corresponding events. Easiest way would be to make events static in PlayerInput
public static UnityEvent<Vector2> OnBoatMovement = new UnityEvent<Vector2>();
public static UnityEvent OnShoot = new UnityEvent();
and attach corresponding handlers to them in Movement.Awake
private void Awake(){
rb2d = GetComponent<Rigidbody2D>();
PlayerInput.OnBoatMovement += Handlemovement;
PlayerInput.OnShoot += HandleShooting;
}
Also in PlayerInput.BoatMovement you should probably check
if(movementVector.sqrMagnitude > 0){
OnBoatMovement?.Invoke(movementVector.normalized);
}
Or else random shit may happen when trying to normalize Vector with magnitude 0 (I compare sqr magnitude to aviod calculating root which is never desired)

Related

My Bullet is not getting instantiated where my Player is. It is getting instantiated from center only

I am new to Unity & on Stackoverflow. Need your help as I am stuck in this below mentioned situation.
When I spawn my projectile(Bullet), It should be instantiated at player's current position but It's not getting changed. The bullet is getting generated from Center only(Not from Player's position). Please advise. image is for reference
SpawnobjectController Script
public class SpawnobjectController : MonoBehaviour
{
[SerializeField]
GameObject projectilereference;
[SerializeField]
GameObject enemyreference;
[SerializeField]
GameObject playerreference;
void Start()
{
StartCoroutine(Enemycoroutine());
StartCoroutine(ProjectileCoroutine());
}
void SpawnProjectile()
{
Instantiate(projectilereference, new Vector3(playerreference.transform.position.x,projectilereference.transform.position.y,0.0f), Quaternion.identity);
}
IEnumerator ProjectileCoroutine()
{
while (true)
{
SpawnProjectile();
yield return new WaitForSeconds(2.0f);
}
}
IEnumerator Enemycoroutine()
{
while (true) {
SpawnEnemy();
yield return new WaitForSeconds(1.0f);
}
}
void SpawnEnemy()
{
Instantiate(enemyreference, enemyreference.transform.position, Quaternion.identity);
}
}
PlayerController Scripts
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
float _horizontalAxisPlayer;
float _playerSpeed = 5f;
float _maxXBoundry = 2.31f;
void Start()
{
}
void Update()
{
ControlPlayerBoundries();
PlayerMovement();
}
void PlayerMovement()
{
_horizontalAxisPlayer = Input.GetAxis("Horizontal")*_playerSpeed*Time.deltaTime;
transform.Translate(new Vector3(_horizontalAxisPlayer, 0.0f, 0.0f));
}
void ControlPlayerBoundries()
{
if (transform.position.x>_maxXBoundry)
{
transform.position = new Vector3(_maxXBoundry,transform.position.y,0.0f);
}
else if (transform.position.x<-_maxXBoundry)
{
transform.position = new Vector3(-_maxXBoundry, transform.position.y, 0.0f);
}
}
}
EnemyController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyController : MonoBehaviour
{
[SerializeField]
private float enemeySpeed = 2f;
void Start()
{
}
void Update()
{
transform.Translate(Vector3.down * enemeySpeed * Time.deltaTime);
}
}
ProjectileController Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ProjectileController : MonoBehaviour
{
[SerializeField]
private GameObject Playerref;
[SerializeField]
private float projectile_speed = 2f;
void Start()
{
}
void Update()
{
// print(Playerref.transform.position);
}
private void LateUpdate()
{
transform.Translate(new Vector3(transform.position.x, 0.5f) * projectile_speed * Time.deltaTime);
}
}
Your problem is likely in the script that translates your bullet.
As the code you shared does exactly what you want. Assuming we are in a front view.
I have verified this by using your script and a copy of the enemy script in place of a bullet that moves them in Vector3.Up direction.
Edit:
You are creating a new vector with the transforms x and 0,5f that gets added every frame.
You either set transform.position or use Translate but with a direction only.
Moves the transform in the direction and distance of translation.
transform.Translate(Vector3 translation)
The following line would work instead.
private void LateUpdate()
{
transform.Translate(Vector3.up * projectile_speed* Time.deltaTime);
}

Unity accessing rigidBody component with input system

I have just started a new Unity tut using its input system to move a ball. However, the script doesn't seem to be working when I try to move the ball
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem; //Namespace for accessing InputSystem to control ball
public class PlayerController : MonoBehaviour
{
private Rigidbody rb;
private float movementX;
private float movementY;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Onmove(InputValue movementValue)
{
Vector2 movementVector = movementValue.Get<Vector2>();
movementX = movementVector.x;
movementY = movementVector.y;
}
void FixedUpdate()
{
Vector3 movement = new Vector3(movementX, 0.0f, movementY);
rb.AddForce(movement);
}
}
If you did everything else right and the problem is only in your script then changing from Onmove to OnMove should fix problem
Create in Unity a new InputControl with the name PlayerInputActions and into
Inspector select Generate C# class, Unity autogenerate for you Action Maps , Actions and Binding Property, double click on it to watch, than in a new c# script named NewInputSystem
using UnityEngine;
using UnityEngine.InputSystem;
public class NewInputSystem : MonoBehaviour
{
public Rigidbody rb;
public float moveSpeed = 7.0f;
Vector2 moveDirections = Vector2.zero;
public PlayerInputActions playerControls;
private InputAction move;
private void Awake()
{
playerControls = new PlayerInputActions();
}
private void OnEnable()
{
move = playerControls.Player.Move;
move.Enable();
}
private void OnDisable()
{
move.Disable();
}
void Start()
{
rb =gameObject.GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
moveDirections = move.ReadValue<Vector2>();
}
private void FixedUpdate()
{
//change how you want
rb.velocity = new Vector3(moveDirections.y * moveSpeed, 0, moveDirections.x * -moveSpeed);
}
}

Having problems with "OnCollisionEnter2D" in Unity2D

I'm using this code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class CollisionPlayer : MonoBehaviour
{
public bool alreadyDied = false;
public GameObject player;
public float timeDeath;
public ParticleSystem particles;
public GameObject explosionGO;
private SpriteRenderer sr;
private BoxCollider2D bc;
private PlayerController walkScript;
void Start()
{
sr = GetComponent<SpriteRenderer>();
bc = GetComponent<BoxCollider2D>();
walkScript = GetComponent<PlayerController>();
}
void OnCollisionEnter2D (Collision2D collide)
{
if (collide.gameObject.CompareTag("Dead"))
{
Instantiate(particles, player.transform.position, Quaternion.identity);
Instantiate(explosionGO, player.transform.position, Quaternion.identity);
CinemachineShake.Instance.ShakeCamera(30f, .1f);
alreadyDied = true;
}
}
void Update()
{
if(alreadyDied == true)
{
timeDeath -= Time.deltaTime;
sr.enabled = false;
bc.enabled = false;
walkScript.enabled = false;
}
if(timeDeath <= 0)
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
}
This is the bullet's code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LeftBulletScript : MonoBehaviour
{
// Start is called before the first frame update
public float speed;
public float destructionLeftTime;
public ParticleSystem particles;
private GameObject thisGameObject;
void Start()
{
thisGameObject = this.gameObject;
Destroy(gameObject, destructionLeftTime);
}
void Update()
{
transform.Translate(Vector2.left * speed * Time.deltaTime);
if(destructionLeftTime > 0.05f)
{
destructionLeftTime -= Time.deltaTime;
}
else
{
Instantiate(particles, thisGameObject.transform.position, Quaternion.identity);
}
}
}
This code should spawn some particles and a sound effect when the player gets hit by something with tag "Dead". But that does not happen. I have a box collider 2D on both the bullet (that should kill me) and the player. My Rigidbody2D is dynamic on the player with z freezed. The bullet does not have a rigidbody. I made sure that the bullet actually has the tag "Dead", spelled the exact same way as the way I wrote on the script. The weirdest thing is that I used this code on another game and nothing changed (just the name of a script). Both the player and the bullet are on the same layer. Anyone could tell me what could have happened?

Unity - character starts to fly up when there should be gravity

I am developing a 2D platform game, where the character is a ball and should be able to move right and left, and to jump. It now does all that, but for some reason which i do not understand (as i am complitely new to Unity) sometimes it flies up like if the gravity was negative.
Here is the code of my first script Move2D:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move2D : MonoBehaviour
{
public float moveSpeed = 5f;
public bool isGrounded = false;
[SerializeField] private Rigidbody2D rigidbody;
private Vector2 currentMoveDirection;
private void Awake()
{
rigidbody = GetComponent<Rigidbody2D>();
currentMoveDirection = Vector2.zero;
}
public void Jump()
{
if (isGrounded)
{
rigidbody.AddForce(new Vector3(0f, 5f), ForceMode2D.Impulse);
}
}
private void FixedUpdate()
{
rigidbody.velocity = (currentMoveDirection + new Vector2(0f, rigidbody.velocity.y)).normalized * moveSpeed;
}
public void TriggerMoveLeft()
{
currentMoveDirection += Vector2.left;
}
public void StopMoveLeft()
{
currentMoveDirection -= Vector2.left;
}
public void TriggerMoveRight()
{
currentMoveDirection += Vector2.right;
}
public void StopMoveRight()
{
currentMoveDirection -= Vector2.right;
}
}
And this is the code of the second script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ContinuesButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
[SerializeField] private Button targetButton;
[SerializeField] private Move2D playerMovement;
[SerializeField] private bool movesLeft;
private readonly bool isHover;
private void Awake()
{
if (!targetButton) targetButton = GetComponent<Button>();
}
public void OnPointerDown(PointerEventData eventData)
{
if (movesLeft)
{
playerMovement.TriggerMoveLeft();
} else
{
playerMovement.TriggerMoveRight();
}
}
public void OnPointerUp(PointerEventData eventData)
{
if (movesLeft)
{
playerMovement.StopMoveLeft();
} else
{
playerMovement.StopMoveRight();
}
}
}
I noticed that the ball starts to fly up as soon as the movement controller or some collider makes it go up a bit. For example when i make it jump, it just keeps going up, or when in the game i try to make it "walk" up a hill, it immediately starts flying up.
Any help or information is really appreciated, I really do not see the problem.
The issue I lies in normalized. This might unexpectedly increase the Y velocity. Especially in cases when you set the X velocity to 0 the Y component is taken into account to much.
I guess you should rather use something like
currentDirection * moveSpeed + Vector2.up * rigidbody.velocity.y;
In order to simply keep the current Y velocity.
Also be careful with these currentDirection += ...! I would suggest rather use single methods and use fixed values like e.g.
public void DoMove(bool right)
{
currentDirection = (right ? 1 : -1) * Vector2.right;
}
public void StopMove()
{
currentDirection = Vector2.zero;
}
And then rather call them like
public void OnPointerDown(PointerEventData eventData)
{
playerMovement.DoMove(!movesLeft);
}
public void OnPointerUp(PointerEventData eventData)
{
playerMovement.StopMove();
}

Unity prefab movement

Hello i want to create a group of the same prefab following the player in my game. I already got the prefab intantiation to follow the player but when there is more than one they just follow the exact same path on top of each other. is there a way where they can follow the player but act like a bunch of bees moving?
Thanks!
This is the script on my prefab:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class KillerMovement : MonoBehaviour {
public GameObject player;
void FixedUpdate()
{
Vector2 toTarget = player.transform.position - transform.position;
float speed = 0.5f;
transform.Translate(toTarget * speed * Time.deltaTime);
}
}
The best solution depends on you game logic, but you may consider having a delay before starting following (you can tweak the delay depending on the position you want to the particular object to assume in the trail.
using System.Collections;
using UnityEngine;
public class Follower : MonoBehaviour
{
public GameObject player;
public float delay = 0f;
public float speed = .5f;
bool isReady = false;
void Start()
{
StartFollowing();
}
public void StartFollowing()
{
StartCoroutine(WaitThenFollow(delay));
}
IEnumerator WaitThenFollow(float delay)
{
yield return new WaitForSeconds(delay);
isReady = true;
Debug.Log(gameObject.name);
Debug.Log(Time.time);
}
void FixedUpdate()
{
if (isReady && player != null)
{
Vector2 toTarget = player.transform.position - transform.position;
transform.Translate(toTarget * speed * Time.deltaTime);
}
}
}
I've called StartFollowing in the Start method for you to test the code. You should call this method whenever approrpiate in your game logic.

Categories