Unity 3D - Collider bug in 2D - unity3d

I have a problem with Unity 2D collider, shown in this video: https://youtu.be/AMof6lJNtNk
Red wall is "killing" me, but just after game start/respawn. I'm colliding with 2 walls (brick has smaller collider than red wall) and I'm dying, but if I first collide to brick, then to red wall I don't die. Why?
I don't want to die in either case.
using UnityEngine;
using System.Collections;
public class MovementScript : MonoBehaviour {
public float speed = 1.0f;
Vector3 spawn;
// Use this for initialization
void Start () {
GetComponent ().freezeRotation = true;
spawn = GetComponent ().transform.position;
}
// Update is called once per frame
void Update () {
//Debug.Log ("Vertical: " + Input.GetAxis ("Vertical"));
if (Input.GetAxis ("Vertical") > 0) {
GetComponent ().velocity = new Vector2 (0, 1)*speed;
} else if (Input.GetAxis ("Vertical") ().velocity = new Vector2 (0, -1)*speed;
}
if (Input.GetAxis ("Horizontal") > 0) {
GetComponent ().velocity = new Vector2 (1, 0)*speed;
} else if (Input.GetAxis ("Horizontal") ().velocity = new Vector2 (-1, 0)*speed;
}
}
void OnTriggerEnter2D (Collider2D col){
Debug.Log ("Koliduje!");
if (col.transform.tag == "Respawn") {
Debug.Log ("Skułeś się!");
GetComponent ().transform.position = spawn;
}
}
}

Related

Shoot raycast on reflect direction

I'm creating a pool game. And I want to shoot Raycast on the reflect direction so I can draw LineRenderer on it.
Main Cue Ball Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DrawCueBallTrajectory : MonoBehaviour
{
private RaycastHit hit;
private LineRenderer lineRender;
private float cueBallRadius;
private void Awake()
{
lineRender = GetComponent<LineRenderer>();
cueBallRadius = GetComponent<SphereCollider>().radius;
}
void Update()
{
Vector3 reduceTransPos = new Vector3(transform.position.x, transform.position.y - 2f, transform.position.z);
Ray ray = new Ray(transform.position, -transform.forward);
if (Physics.SphereCast(ray, cueBallRadius, out hit))
{
if (hit.collider != null)
{
lineRender.enabled = true;
lineRender.SetPosition(0, transform.position);
lineRender.SetPosition(1, -transform.forward + new Vector3(hit.point.x, hit.point.y + 1f, hit.point.z));
if (hit.collider.gameObject.CompareTag("OtherCueBall"))
{
Vector3 newDirection = Vector3.Reflect(hit.transform.position, hit.normal);
hit.collider.gameObject.GetComponent<OtherCueBallTrajectory>().DrawPredictionLine(newDirection);
}
}
}
}
}
Other Ball Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OtherCueBallTrajectory : MonoBehaviour
{
private RaycastHit hit;
private LineRenderer lineRender;
private float cueBallRadius;
private void Awake()
{
lineRender = GetComponent<LineRenderer>();
cueBallRadius = GetComponent<SphereCollider>().radius;
}
public void DrawPredictionLine(Vector3 targetDestination)
{
Ray ray = new Ray(transform.position); // what to put here
}
}
You must emit another sphere cast along the point of impact. Also adjust the lineRender points count according to the number of fractures. I made these changes to the script main cue ball and do not see the need to refer the second sphere cast to the other ball.
if (Physics.SphereCast(ray, cueBallRadius, out hit))
{
if (hit.collider != null)
{
lineRender.enabled = true;
lineRender.positionCount = 2; // here I set lineRender position count
lineRender.SetPosition(0, transform.position);
lineRender.SetPosition(1, -transform.forward + new Vector3(hit.point.x, hit.point.y + 1f, hit.point.z));
if (hit.collider.gameObject.CompareTag("OtherCueBall"))
{
Vector3 newDirection = Vector3.Reflect(hit.transform.position, hit.normal);
lineRender.positionCount = 3; // we need 1 more break point
// second sphere cast begin from hit.point along reflectDirection
if (Physics.SphereCast(hit.point, cueBallRadius, newDirection, out var secondHit))
{
lineRender.SetPosition(2, secondHit.point); // stop when hit wall or anything
}
else
{
lineRender.SetPosition(2, hit.point + newDirection * 10f); // point along direction for maximum of 10f length for e.g..
}
}
}
}

Unity2D Enemy RigidBody Sticking To Player

Video example: https://imgur.com/a/d7MRjVG
Hello, my enemy object is getting stuck to my player object and dragged along. Normally, the enemy has a much lower movement speed than my player does. But when stuck to the player, the enemy essentially inherits my player's movement. I should note that this ONLY happens when the enemy is higher than my player ie has a greater Y position
Player is a rigidbody with Kinematic type
Enemy is a rigidbody with Dynamic type (I wanted this so I can push enemies aside)
Enemy is scripted not to attempt movement if too close to the player as well
The enemy has a pretty basic movement script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AI_Common : MonoBehaviour
{
public float moveSpeed; // Movement speed
public float contactDamageDistance; // offset for contact damage and when to stop walking
public ContactFilter2D movementFilter; // Filter of object types to collide with
Vector2 proposedMovement; // movement to check for collisions before executing
List<RaycastHit2D> castCollisions = new List<RaycastHit2D>(); // Collision list
float myX; // Used for incrementing movement
float myY; // Used for incrementing movement
GameObject player;
Rigidbody2D rBody;
Animator animator;
SpriteRenderer spriteRenderer;
// Start is called before the first frame update
void Start()
{
player = GameObject.FindWithTag("Player");
rBody = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
spriteRenderer = GetComponent<SpriteRenderer>();
}
// Update is called once per frame
void Update()
{
}
// Once per physics frame
private void FixedUpdate()
{
animator.SetBool("IsWalking", false);
// Attempt to move toward player if far enough away
if (Vector2.Distance(player.transform.position, rBody.transform.position) < contactDamageDistance)
return;
bool moveSuccess = false;
myX = 0;
myY = 0;
if (player.transform.position.x > rBody.position.x)
{
myX = moveSpeed * Time.fixedDeltaTime;
} else if (player.transform.position.x < rBody.position.x)
{
myX = -moveSpeed * Time.fixedDeltaTime;
}
// Flip X if needed
if(player.transform.position.x - rBody.position.x < -contactDamageDistance)
{
spriteRenderer.flipX = true;
}
else if (player.transform.position.x - rBody.position.x < contactDamageDistance)
{
spriteRenderer.flipX = false;
}
if (player.transform.position.y > rBody.position.y)
{
myY = moveSpeed * Time.fixedDeltaTime;
}
else if (player.transform.position.y < rBody.position.y)
{
myY = -moveSpeed * Time.fixedDeltaTime;
}
print($"MyX:{rBody.transform.position.x}, MyY:{rBody.transform.position.y}, PlayerX{player.transform.position.x}, playerY{player.transform.position.y}");
print($"Distance:{Vector2.Distance(player.transform.position, rBody.transform.position)}");
moveSuccess = TryMove(new Vector2(myX, myY));
// If move failed, try X only
if (!moveSuccess && myX != 0)
{
moveSuccess = TryMove(new Vector2(myX, 0));
}
// If move failed, try Y only
if (!moveSuccess && myY != 0)
{
moveSuccess = TryMove(new Vector2(0, myY));
}
animator.SetBool("IsWalking", moveSuccess);
}
private bool TryMove(Vector2 moveDirection)
{
// Check for collisions
int count = rBody.Cast(
moveDirection, // X and Y values -1 to 1
movementFilter, // Specifies which objects are considered for collision
castCollisions, // List of collisions detected by cast
moveSpeed * Time.fixedDeltaTime + contactDamageDistance); // Length of cast equal to movement plus offset
// If no collisions found, move
if (count == 0)
{
rBody.MovePosition(rBody.position + moveDirection);
return true;
}
return false;
}
}

Inverse Kinematics (IK) Foot Placement

I have a problem with my humanoid character's Foot IK.
I'm building an Isometric Top-Down game with NavMesh to move the Player on click, and I wanted to add some life to the characters so I decided to add IK Foot Placement by following this tutorial.
It worked well, but I wanted to go further by making it more sensitive to colliders so the player's foot gets placed on the ground's surface perfectly.
This script below works well when the ground is rotated.
I tried to fix it a lot but it still doesn't work.
[ Preview Images ]
Here's my script:
using UnityEngine;
using UnityEngine.AI;
public class IKFootPlacement : MonoBehaviour
{
public bool ikActive = false;
public Animator anim;
public NavMeshSurface navmesh;
public LayerMask layerMask;
public Transform LeftFoot_Transform;
public Transform RightFoot_Transform;
public float LeftFoot_DistanceToGround;
public float RightFoot_DistanceToGround;
public float footGap = 0.0f;
private Vector3 L_TargetPosition;
private Vector3 R_TargetPosition;
private Ray L_Ray;
private Ray R_Ray;
void Start()
{
anim = GetComponent<Animator>();
}
void OnAnimatorIK(int layerIndex)
{
if (anim)
{
// Vector3 LeftFoot_position = anim.GetIKPosition(AvatarIKGoal.LeftFoot);
// Vector3 RightFoot_Position = anim.GetIKPosition(AvatarIKGoal.RightFoot);
float IKLeftWeight = anim.GetFloat("IKLeftFootWeight");
anim.SetIKPositionWeight(AvatarIKGoal.LeftFoot, IKLeftWeight);
anim.SetIKRotationWeight(AvatarIKGoal.LeftFoot, IKLeftWeight);
float IKRightWeight = anim.GetFloat("IKRightFootWeight");
anim.SetIKPositionWeight(AvatarIKGoal.RightFoot, IKRightWeight);
anim.SetIKRotationWeight(AvatarIKGoal.RightFoot, IKRightWeight);
//~ Left Foot
if (LeftFoot_Transform)
{
RaycastHit L_Hit;
L_Ray = new Ray(LeftFoot_Transform.position + Vector3.up, Vector3.down);
if (Physics.Raycast(L_Ray, out L_Hit, 2f, layerMask))
{
L_TargetPosition = L_Hit.point;
LeftFoot_DistanceToGround = Vector3.Distance(LeftFoot_Transform.position, L_TargetPosition);
if (LeftFoot_DistanceToGround > 0.15)
L_TargetPosition.y -= LeftFoot_DistanceToGround;
else
L_TargetPosition.y += LeftFoot_DistanceToGround;
L_TargetPosition.y += footGap;
anim.SetIKPosition(AvatarIKGoal.LeftFoot, L_TargetPosition);
anim.SetIKRotation(AvatarIKGoal.LeftFoot, Quaternion.LookRotation(transform.forward, L_Hit.normal));
}
}
//~ Right Foot
if (RightFoot_Transform)
{
RaycastHit R_Hit;
R_Ray = new Ray(RightFoot_Transform.position + Vector3.up, Vector3.down);
if (Physics.Raycast(R_Ray, out R_Hit, 2f, layerMask))
{
R_TargetPosition = R_Hit.point;
RightFoot_DistanceToGround = Vector3.Distance(RightFoot_Transform.position, R_TargetPosition);
if (RightFoot_DistanceToGround > 0.15)
R_TargetPosition.y -= RightFoot_DistanceToGround;
else
R_TargetPosition.y += RightFoot_DistanceToGround;
R_TargetPosition.y += footGap;
anim.SetIKPosition(AvatarIKGoal.RightFoot, R_TargetPosition);
anim.SetIKRotation(AvatarIKGoal.RightFoot, Quaternion.LookRotation(transform.forward, R_Hit.normal));
}
}
}
}
void OnDrawGizmos()
{
Gizmos.color = Color.magenta;
Gizmos.DrawWireSphere(L_TargetPosition, 0.05f);
Gizmos.DrawWireSphere(R_TargetPosition, 0.05f);
Gizmos.color = Color.red;
Gizmos.DrawRay(L_Ray);
Gizmos.DrawRay(R_Ray);
}
}

Why is my raycast not detecting the object?

Im currently on a project where i need to detect if an object is in front of an other, so if it's the case the object can't move, because one is in front of it, and if not the object can move.
So im using here a raycast, and if the ray hit something I turn a bool to true. And in my scene, the ray hits but never turning it to true.
I precise that both of my objects as 2D colliders and my raycast is a 2DRaycast, I previously add to tick "Queries Start in colliders" in physics 2D so my ray won't detect the object where I cast it.
Please save me.
Here is my code :
float rayLength = 1f;
private bool freeze = false;
private bool moving = false;
private bool behindSomeone = false;
Rigidbody2D rb2D;
public GameObject cara_sheet;
public GameObject Monster_view;
public GameObject monster;
void Start()
{
rb2D = GetComponent<Rigidbody2D>();
}
void Update()
{
Movement();
DetectQueuePos();
}
private void Movement()
{
if(freeze || behindSomeone)
{
return;
}
if(Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("Move");
moving = true;
//transform.Translate(Vector3.up * Time.deltaTime, Space.World);
}
if(moving)
{
transform.Translate(Vector3.up * Time.deltaTime, Space.World);
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (!collision.CompareTag("Bar"))
{
return;
}
StartCoroutine(StartFreeze());
}
public void DetectQueuePos()
{
RaycastHit2D hit = Physics2D.Raycast(this.transform.position, this.transform.position + this.transform.up * rayLength, 2f);
Debug.DrawLine(this.transform.position, this.transform.position + this.transform.up * rayLength, Color.red, 2f);
if (hit.collider != null)
{
print(hit.collider.name);
}
if(hit.collider != null)
{
Debug.Log("Behind true");
//Destroy(hit.transform.gameObject);
behindSomeone = true;
}
}
IEnumerator StartFreeze()
{
yield return new WaitForSeconds(1f);
rb2D.constraints = RigidbodyConstraints2D.FreezeAll;
freeze = true;
moving = false;
cara_sheet.SetActive(true);
Monster_view.SetActive(true);
}
While Debug.DrawLine expects a start position and an end position a Physics2D.Raycast expects a start position and a direction.
You are passing in what you copied from the DrawLine
this.transform.position + this.transform.up * rayLength
which is a position, not a direction (or at least it will a completely useless one)! Your debug line and your raycast might go in completely different directions!
In addition to that you let the line have the length rayLength but in your raycasts you pass in 2f.
It should rather be
Physics2D.Raycast(transform.position, transform.up, rayLength)

Unity 2D: My laser script is getting stuck on an if statement and I don't know why

I've been making a laser in my 2D platformer for the past day. I've made the arm follow to cursor perfectly however on the script for the weapon it self doesn't work. Here is my code
using UnityEngine;
using System.Collections;
public class Weapon : MonoBehaviour {
public float fireRate = 0;
public float Damage = 10;
public LayerMask whatToHit;
float timeToFire = 0;
Transform firePoint;
// Use this for initialization
void Awake () {
firePoint = transform.FindChild ("FirePoint");
if (firePoint == null) {
Debug.LogError ("No firePoint");
}
}
// Update is called once per frame
void Update () {
if (fireRate == 0) {
if (Input.GetButtonDown ("Fire1")) {
Shoot();
}
}
else {
if (Input.GetButton ("Fire1") && Time.time > timeToFire) {
timeToFire = Time.time + 1/fireRate;
Shoot();
}
}
}
void Shoot () {
Debug.Log ("Works");
Vector2 mousePosition = new Vector2 (Camera.main.ScreenToWorldPoint (Input.mousePosition).x, Camera.main.ScreenToWorldPoint(Input.mousePosition).y);
Vector2 firePointPosition = new Vector2 (firePoint.position.x, firePoint.position.y);
RaycastHit2D hit = Physics2D.Raycast (firePointPosition, mousePosition-firePointPosition, 100, whatToHit);
Debug.DrawLine (firePointPosition, (mousePosition-firePointPosition)*100, Color.cyan);
Debug.Log ("Works 2");
if (hit.collider != null) {
Debug.Log ("Work 3");
Debug.DrawLine (firePointPosition, hit.point, Color.red);
Debug.Log ("We hit " + hit.collider.name + " and did " + Damage + " damage.");
}
}
}
The if statement in void Shoot isn't working. The first two debug messages in void Shoot show up in the log however the two in the if statement don't and I have no idea why. Can anyone help?