So, I'm having a problem with shaky movement in a very simple 2D platformer, with a square player, using a circle collider. The player's movement is shaky, not the ground. I think it's a problem with the colliders, because I've been on another post trying to fix the script, and I think I did it. I've been trying to fix this for quite a while.
public float moveSpeed;
public float jumpHeight;
Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
rb.velocity = new Vector2(rb.velocity.x, jumpHeight);
}
if (Input.GetKey(KeyCode.D))
{
rb.velocity = new Vector2(moveSpeed, rb.velocity.y);
}
if (Input.GetKey(KeyCode.A))
{
rb.velocity = new Vector2(-moveSpeed, rb.velocity.y);
}
}
Related
I am building my first 2D project in unity, I am stuck in the PlayerMovement script, it's not colliding with neither the walls nor the objects the player is supposed to move by one block and it should push the objects (like in sokoban), but it's not detecting any of these
the player is a capsule which has a capsule collider 2d component and a rigidbody 2d component and the each wall bloack has box collider 2d and tilemap and tilemap collider 2d and a rigidbody 2d.
I tried using the OnDrawGismos() method to detect the object before moving but it's not working
here's my code
public Tilemap wall;
private Vector3 moveToPosition;
private Vector3 movement;
private bool walking;
private float moveSpeed = 2;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void Update()
{
if (!walking)
{
movement.x = Input.GetAxis("Horizontal");
movement.y = Input.GetAxis("Vertical");
if (movement != Vector3.zero)
{
moveToPosition = transform.position + new Vector3(movement.x, movement.y, 0);
Vector3Int wallMapTile = wall.WorldToCell(moveToPosition - new Vector3(0, 0.5f, 0));
if (wall.GetTile(wallMapTile) == null)
{
StartCoroutine(Move(moveToPosition));
}
}
}
}
IEnumerator Move(Vector3 newPos)
{
walking = true;
while ((newPos - transform.position).sqrMagnitude > Mathf.Epsilon)
{
transform.position = Vector3.MoveTowards(transform.position, newPos, moveSpeed * Time.deltaTime);
yield return null;
}
transform.position = newPos;
walking = false;
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawSphere(moveToPosition- new Vector3(0,0.5f,0), 0.2f);
}```
use rb.velocity to control the player movement instead of transform.position because the player would be teleporting not walking
the problem I am having is when I run full speed (i.e. pressing a and w and looking 45 degrees to the right it doesn't use .normalized on purpose) into a wall or anything else it allows the player to go through it, so my code is
Vector3 m_Input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
Vector3 moveDirection = m_Input;
moveDirection = transform.TransformDirection(moveDirection);
rb.MovePosition(transform.position + moveDirection * moveSpeed);
and moveSpeed is set to 0.2. I have checked and all of the colliders are not triggers. any help would be greatly appreciated
First off do double check
All your colliders & rigidbody are 3d
Everything is on the same layer (or your layers are set to interact with each other)
Your rigidbody is attached to the same game object as your collider
However, it seems that your issue is that your rigidbody is set to be kinematic (as Rigidbody.MovePosition is intended to be used by kinematic rigidbody's only)
If your rigidbody is set to kinematic then no forces (such as collider normal forces) will be applied to your object, so it will be able to pass through walls.
Solution
The easiest way to avoid this is by making sure your rigidbody is set to non-kinematic, and moving it via Rigidbody.velocity.
Something similar to:
Vector3 m_Input = new Vector3(Input.GetAxis("Horizontal"), 0,
Input.GetAxis("Vertical"));
Vector3 moveDirection = m_Input;
moveDirection = transform.TransformDirection(moveDirection);
rb.velocity = (moveDirection * moveSpeed);
This should move your character according to physics and allow for the correct interactions with colliders.
Also, you should be aware if you ever do want to move a rigidbody like that, you should be sure to do so in FixedUpdate and scale movement by Time.FixedDeltaTime.
now the jump is broken this is the full script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FPSMovement : MonoBehaviour
{
public Rigidbody rb;
public GameObject cam;
Vector2 rotation = Vector2.zero;
public float sensitivity = 10f;
public string xAxis = "Mouse X";
public string yAxis = "Mouse Y";
public float OmoveSpeed;
public float SprintSpeed;
public float moveSpeed;
public float jumpVar;
public bool Grounded = false;
public Vector3 slideScale;
public Vector3 normalScale;
public Vector3 dir;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
moveSpeed = OmoveSpeed;
slideScale = new Vector3(1, 0.5f, 1);
normalScale = new Vector3(1, 1, 1);
}
// Update is called once per frame
void FixedUpdate()
{
dir = rb.velocity;
// Should be cross platform movement
Vector3 m_Input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
Vector3 moveDirection = m_Input;
moveDirection = transform.TransformDirection(moveDirection);
rb.velocity = (moveDirection * moveSpeed);
// Sprinting
if (Input.GetKey(KeyCode.LeftControl))
{
moveSpeed = SprintSpeed;
}
else
{
moveSpeed = OmoveSpeed;
}
// Jumping
if (Input.GetKey(KeyCode.Space))
{
if (Grounded)
{
rb.velocity += new Vector3(0, jumpVar, 0);
Grounded = false;
}
}
// TO-DO: Sliding
// Camera Rotation
rotation.x += Input.GetAxis(xAxis) * sensitivity;
rotation.y += Input.GetAxis(yAxis) * sensitivity;
rotation.y = Mathf.Clamp(rotation.y, -90, 90);
var xQuat = Quaternion.AngleAxis(rotation.x, Vector3.up);
var yQuat = Quaternion.AngleAxis(rotation.y, Vector3.left);
transform.localRotation = xQuat;
cam.transform.localRotation = yQuat;
}
private void OnCollisionEnter(Collision collision)
{
if (collision.transform.tag == "Ground")
{
Grounded = true;
}
}
private void OnCollisionExit(Collision collision)
{
Grounded = false;
}
}
So i made a player with a rigidbody and a child game object "feet", i also added a layer "floor" to every plateforme my player can jump off so i can use Physics.CheckSphere() to see if my player is actually on the ground and can jump. In this last case i add a force to my rigidbody with a ForceMode.Impulse. Everything work except that sometimes the player do a little jump and sometimes a higher jump. Here is my code :
[SerializeField] private float speed;
[SerializeField] private float jumpForce;
[SerializeField] private Transform feet = null;
[SerializeField] private LayerMask floorMask;
private Vector3 direction;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
direction = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical")) * speed;
transform.LookAt(transform.position + new Vector3(direction.x, 0, direction.z));
}
void FixedUpdate()
{
rb.velocity = new Vector3(direction.x, rb.velocity.y, direction.z);
if (Input.GetKeyDown(KeyCode.Space))
{
if (Physics.CheckSphere(feet.position, 0.1f, floorMask))
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
}
}
I replaced the AddForce method with velocity and it seems to work but AddForce isn't the proper way to do jumps ?
rb.velocity = new Vector3(rb.velocity.x, 1 * jumpForce, rb.velocity.z);
Using ForceMode.Impulse is the ideal way to implement a jump with RigidBody. I beleive you need to take your button input out of FixedUpdate() and place it into regular Update(). Then use a bool such as "canJump". This is because your input is being read inside FixedUpdate(); Which is only called every other frame with the physics engine. Also, your rb.velocity.y should be set to 0 when touching ground.
void Update() {
direction = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical")) * speed;
transform.LookAt(transform.position + new Vector3(direction.x, 0, direction.z));
bool canJump = Input.GetKeyDown(keyCode.Space) ? true : false;
}
void FixedUpdate() {
if (Physics.CheckSphere(feet.position, 0.1f, floorMask)) {
if (canJump)
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
else
rb.velocity = new Vector3(direction.x, 0, direction.z);
}
else
rb.velocity = new Vector3(direction.x, rb.velocity.y, direction.z);
}
I'm trying to make my Player Teleport to my mouse position but whenever I right click it seems to teleport far away from my camera and generally where my mouse pointer was.
I am not getting any error messages nor am I getting warnings.
for example, if I click in the middle of the screen with my mouse it will teleport to the center of the text Canvas.
I couldn't seem to find any solutions to my issue on the unity forums.
maybe someone here could help me
my code:
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour
{
public float moveSpeed;
public float jumpHeight;
public GameObject bullet;
public float speed = 5.0f;
public Transform groundCheck;
public float groundCheckRadius;
public LayerMask whatIsGround;
private bool grounded;
public Transform player; //Variable for Teleport funktion
void Awake()
{
player = GameObject.FindGameObjectWithTag("Player").transform; //Finding the player (Teleport)
}
void fixedUpdate()
{
grounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);
}
void Update()
{
if (Input.GetKeyDown("space"))
{
GetComponent<Rigidbody2D>().velocity = new Vector2(GetComponent<Rigidbody2D>().velocity.x, jumpHeight);
}
if (Input.GetKey(KeyCode.D))
{
GetComponent<Rigidbody2D>().velocity = new Vector2(moveSpeed, GetComponent<Rigidbody2D>().velocity.y);
}
if (Input.GetKey(KeyCode.A))
{
GetComponent<Rigidbody2D>().velocity = new Vector2(-moveSpeed, GetComponent<Rigidbody2D>().velocity.y);
}
if (Input.GetMouseButtonDown(1))
{
player.position = (Input.mousePosition); // teleporting
}
if (Input.GetMouseButtonDown(0))
{
Vector2 target = Camera.main.ScreenToWorldPoint(new Vector2(Input.mousePosition.x, Input.mousePosition.y));
Vector2 myPos = new Vector2(transform.position.x, transform.position.y);
Vector2 direction = target - myPos;
direction.Normalize();
Quaternion rotation = Quaternion.Euler(0, 0, Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg);
GameObject projectile = (GameObject)Instantiate(bullet, myPos, rotation);
projectile.GetComponent<Rigidbody2D>().velocity = direction * speed;
}
}
}
You just need to transform the input position from screen to world, like you did in your shooting code:
if (Input.GetMouseButtonDown(1))
{
Vector3 target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
player.position = target; // teleporting
}
I'm working on a 2D game (for smartphone) which is automatically jumping, and I want to give a player movement (accelerometer) (a similar principle as doodle jump). How to make automatically jumping of 2D sprite? I tried to create an animation but it will not move using the accelerometer. So I coded script for automatically jump but it's not working. any help? (automatically jump means when player hits ground, jump again)
public float speed = 6.0F;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
private Vector3 moveDirection = Vector3.zero;
Rigidbody2D coll;
void Start(){
coll = GetComponent<Rigidbody2D>();
}
void Update() {
if (coll.gameObject.tag == "Ground") {
moveDirection = Vector3.zero;
moveDirection.x = 1;
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
}
}
}
So can someone give me script when player hit ground, player will jump? I want to move up and to the right.
Player object should have collider2D and rigidbody2D. Ground object should have collider2D and "Ground" tag. This code must be on player object.
public int power;
void Update()
{
transform.position = new Vector3(transform.position.x + Input.acceleration.x, transform.position.y, transform.position.z);
}
void OnCollisionEnter2D(Collision2D col)
{
if (col.collider.gameObject.tag.Equals("Ground"))
{
rigidbody2D.AddForce(Vector2.up * power);
}
}
I hope it works.