Unity 2d detect collision - c#

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

Related

My unity 3d fps movement is going through walls and they all have colliders

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;
}
}

My Game Character should teleport to the mouse pointer but it teleports far away from my mouse pointer

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
}

Unity 2D rotate the AI enemy to look at player

I'm making a 2D game with two sides, left and right, so the player can only move to the left or right or jump. I made an AI as the enemy. The AI is working fine. He can go to the player to kill him.
The problem is the enemy can't rotate or face the player when he goes to kill him. I want the AI to look at the player. When the player is to the left of the enemy, the enemy should rotate to the left to look at the player. I searched many websites and I didn't get any correct solution. This is my enemy script:
public class enemy : MonoBehaviour
{
public float speed;
private Animator animvar;
private Transform target;
public GameObject effect;
public float distance;
private bool movingRight = true;
public Transform groundedDetection;
public float moveInput;
public bool facingRight = true;
void Start()
{
animvar = GetComponent<Animator>();
target = GameObject.FindGameObjectWithTag("Player").transform;
}
// Update is called once per frame
void Update()
{
if (Vector3.Distance(target.position, transform.position) < 20)
{
transform.position = Vector2.MoveTowards(transform.position, target.position, speed * Time.deltaTime);
}
else
{
transform.Translate(Vector2.right * speed * Time.deltaTime);
}
RaycastHit2D groundInfo = Physics2D.Raycast(groundedDetection.position, Vector2.down, distance);
}
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.tag.Equals("danger"))
{
Instantiate(effect, transform.position, Quaternion.identity);
Destroy(gameObject);
}
if (col.gameObject.tag.Equals("Player"))
{
Instantiate(effect, transform.position, Quaternion.identity);
Destroy(gameObject);
}
}
}
The game is 2D, left, right, with jump using Unity3D.
You need a function that would flip your sprite, you can do that by changing the scale of the transform, and keep a boolean to check where it's facing
bool facingRight;, so something like this
void Flip(){
Vector3 scale = transform.localScale;
scale.x *= -1;
transform.localScale = scale;
facingRight = !facingRight;
}
and in your Update check if it needs to be flipped or not
if (Vector3.Distance(target.position,transform.position)<20)
{
transform.position=Vector2.MoveTowards(transform.position, target.position,speed*Time.deltaTime);
if(target.position.x > transform.position.x && !facingRight) //if the target is to the right of enemy and the enemy is not facing right
Flip();
if(target.position.x < transform.position.x && facingRight)
Flip();
}
Its simple enough, just get the Player x position and compare to Enemy's x position, then flip the enemy sprite accordingly
This is my Update() method in my Enemy script. This handles enemy movement and changing direction the sprite is facing:
if (moveRight )
{
transform.Translate(2 * Time.deltaTime * moveSpeed, 0, 0);
transform.localScale = new Vector2(6, 6); //6,6 is just a size that suits my sprite
}
else if (!moveRight)
{
transform.Translate(-2 * Time.deltaTime * moveSpeed, 0, 0);
transform.localScale = new Vector2(-6, 6);
}
This is my enemy Attack() method , I compare the Player X position to Enemy X position. If Player X is less( to the left of the Enemy), I flip the Enemy sprite to negative
if (transform.position.x > Player.position.x)
{
transform.localScale = new Vector2(-6, 6);
}
else if (transform.position.x < Player.position.x)
{
transform.localScale = new Vector2(6, 6);
}

Unity 2D Circle Collider Shaky Movement

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);
}
}

Automatically jump script

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.

Categories

Resources