Sorry for the bad formatting I don't know how to do this. I'm using 2020.3.21f1 and following a tutorial and when the enemy circle hits the player he doesn't take damage. when they collide they don't overlap at all, but the Debug.log isn't registering either so I think that the circle collider 2D is the problem. the enemy sprite still moves towards the player when it is in range. another problem (that will turn into a feature if I cant figure out how to change it) is that when the enemy collides with the player and the player pushes it goes the direction it was pushed until it runs into something Here's the tutorial I'm following
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy: MonoBehaviour
{
public float speed = 3f;
private Transform target;
[SerializeField] private float attackDamage = -10f;
private void Update(){
if (target != null){
float step = speed*Time.deltaTime;
transform.position = Vector2.MoveTowards(transform.position, target.position, step);
}
}
private void OnCollision(Collision2D other){
if (other.gameObject.tag == "player"){
Debug.Log("hit");
other.gameObject.GetComponent<PlayerHealth>().UpdateHealth(attackDamage);
}
}
private void OnTriggerEnter2D(Collider2D other) {
if(other.gameObject.tag == "Player"){
target = other.transform;
Debug.Log(target);
}
}
private void OnTriggerExit2D(Collider2D other) {
if(other.gameObject.tag == "Player"){
target = null;
Debug.Log(target);
}
}
}
The sprite by itself wont detect collision, you need to add a box collider for that. If you add that component to the player then modify your code to include those collision detections then it should function ad intended.:)
-TheHackintoshProgrammer;
Related
I have been working on a 2d top down rpg game and I have added walking animations etc, I want to stop the player from doing a walking animation when they hit a wall and currently I have a box collider with a ray cast, the ray cast originally hit the player box collider when walking down but after using a layermask this has stopped, however while walking left and right work perfectly two issues occur that I cannot seem to fix. First, when walking up or down into a tilemap that is on the collision layer (this tilemap has tilemap collider which will stop the player from walking through them) the animation still plays, and second the player will only collide once instead of repeatedly when hitting the tilemap when two tiles are placed back to back, here is my code for collision, the tiles that are for collision are on layer 6.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerScript : MonoBehaviour
{
public float moveSpeed;
private Animator ani;
private bool isMoving;
private Vector2 lastMove;
private Rigidbody2D body;
private Vector2 movement;
private LayerMask wallLayer = 1 << 6;
// Start is called before the first frame update
void Start()
{
body = GetComponent<Rigidbody2D>();
ani = GetComponent<Animator>();
movement = Vector2.zero;
isMoving = false;
}
// Update is called once per frame
void Update() {
isMoving = false;
movement = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
RaycastHit2D ray = Physics2D.Raycast(body.position, movement, 0.6f, wallLayer);
if((movement.x != 0f || movement.y != 0f) && !(ray && ray.collider.tag == "wall")) {
isMoving = true;
lastMove = movement;
}
ani.SetFloat("MoveX", movement.x);
ani.SetFloat("MoveY", movement.y);
ani.SetFloat("LastX", lastMove.x);
ani.SetFloat("LastY", lastMove.y);
ani.SetBool("IsMoving", isMoving);
}
void FixedUpdate() {
body.MovePosition(body.position + movement * moveSpeed * Time.deltaTime);
}
}
The code looks fine. Most likely, the issue is with your configuration of the AnimatorController.
Do you have transitions in place for (for example) coming from the walk animation back to idle?
I am a beginner in Unity and I am currently making a simple game. I have a problem where upon initial collision, the event that I wanted to happen does not trigger or in other words the OnCollisionEnter is not working upon initial collision.
The process of my script is when colliding which is the OnCollisionEnter the button will appear or it will be set active to true. But in the first collision it does not trigger or it is not working, I need to walk away a bit and go back in that way it only works. Sometimes I need to do it 2 or more times for the collider to trigger. I don't know if the script has problem or the collider itself but I made sure it is colliding properly when I look at the editor.
I set the object to static so it will not be pushed when walking and colliding towards it. I wonder if that has to do with this problem because even disabled it is the same. But can anyone give suggestions on how not to make the objects move or be pushed away upon collision?
Here is the script for my collision:
using UnityEngine;
using UnityEngine.UI;
public class InteractNPC : MonoBehaviour
{
//public Button UI;
[SerializeField] GameObject uiUse, nameBtn;
private Transform head;
private Vector3 offset = new Vector3(0, 1.0f, 0);
// Start is called before the first frame update
void Start()
{
//uiUse = Instantiate(UI, FindObjectOfType<Canvas>().transform).GetComponent<Button>();
uiUse.gameObject.SetActive(true);
head = transform.GetChild(0);
uiUse.transform.position = Camera.main.WorldToScreenPoint(head.position + offset);
}
// Update is called once per frame
void Update()
{
uiUse.transform.position = Camera.main.WorldToScreenPoint(head.position + offset);
nameBtn.transform.position = Camera.main.WorldToScreenPoint(head.position + offset);
}
private void OnCollisionEnter(Collision collisionInfo)
{
//Debug.Log("wews2");
if(collisionInfo.collider.name == "Player")
{
nameBtn.gameObject.SetActive(true);
}
}
private void OnCollisionExit(Collision collisionInfo)
{
if(collisionInfo.collider.name == "Player")
{
nameBtn.gameObject.SetActive(false);
}
}
}
Here is another script with collision and has the same problem:
using UnityEngine;
using UnityEngine.UI;
public class InteractButtonPosition : MonoBehaviour
{
//public Button UI;
[SerializeField] GameObject uiUse;
private Vector3 offset = new Vector3(0, 0.5f, 0);
// Start is called before the first frame update
void Start()
{
//uiUse = Instantiate(UI, FindObjectOfType<Canvas>().transform).GetComponent<Button>();
//uiUse = GameObject.FindGameObjectWithTag("ViewButton");
}
// Update is called once per frame
void Update()
{
uiUse.transform.position = Camera.main.WorldToScreenPoint(this.transform.position + offset);
}
private void OnCollisionEnter(Collision collisionInfo)
{
if(collisionInfo.collider.name == "Player")
{
Debug.Log("wews");
uiUse.gameObject.SetActive(true);
}
}
private void OnCollisionExit(Collision collisionInfo)
{
if(collisionInfo.collider.name == "Player")
{
//Destroy(uiUse.gameObject);
uiUse.gameObject.SetActive(false);
}
}
}
Try changing Colision detection from Descrete to Continuous
collission detection
I solved this issue by using OntriggerEnter instead of OnCollisionEnter. In the editor, for the NPC I put a Collider on each part of the body and check the IsTrigger in the parent Object so it will still collide with my character even if the IsTrigger is enabled that will make the character go through the object. I just enlarged the scale of the collider with IsTrigger enabled so the collision will be detected immediately.
I use Cinemachine camera collider for my project. This basically means that my entire game is inside a polygon collider.
With the following script my line renderer collides instantly with this camera collider:
[SerializeField] private float defDistanceRay = 10f;
public Transform laserFirePoint;
public LineRenderer m_linerenderer;
Transform m_transform;
private void Awake()
{
m_transform = GetComponent<Transform>();
}
private void Update()
{
ShootLaser();
}
void ShootLaser()
{
if(Physics2D.Raycast(m_transform.position, transform.right))
{
RaycastHit2D _hit = Physics2D.Raycast(m_transform.position, transform.right);
Draw2DRay(laserFirePoint.position, _hit.point);
Debug.Log(_hit.collider.name);
}
else
{
Draw2DRay(laserFirePoint.position, laserFirePoint.transform.right * defDistanceRay);
}
}
void Draw2DRay(Vector2 startPos, Vector2 endPos)
{
m_linerenderer.SetPosition(0, startPos);
m_linerenderer.SetPosition(1, endPos);
}
Can I somehow bypass this collider by setting a "tag" on it and in my code ignore colliders with that specific tag?
Anyone have a good work around for this issue?
EDIT: Forgot to mention Im looking at: https://docs.unity3d.com/ScriptReference/Physics2D.IgnoreCollision.html
But that takes in 2 colliders I just want to ignore 1.
EDIT2: I tried to set the Cinemachine camera polygon collider as a Layermask and ignore it with the following code:
public LayerMask layerMask;
void ShootLaser()
{
if (Physics2D.Raycast(m_transform.position, transform.right))
{
RaycastHit2D _hit = Physics2D.Raycast(m_transform.position, transform.right, layerMask);
Draw2DRay(laserFirePoint.position, _hit.point);
Debug.Log(_hit.collider.name);
}
else
{
Draw2DRay(laserFirePoint.position, laserFirePoint.transform.right * defDistanceRay);
}
}
EDIT 3:
RaycastHit2D _hit = Physics2D.Raycast(m_transform.position, transform.right, defDistanceRay, layerMask);
I added defDistanceRay into the Raycast and now it dosent seem to collide with the camera collider atleast! Super buggy but atleast i bypass the Cinemachine camera collider!
I need to make a platform that moves up when the player enters it.
MovingPlatform.cs
public class MovingPlatform : MonoBehaviour
{
[SerializeField]
private Vector3 newPosition;
void Start()
{
newPosition = new Vector3(transform.position.x, transform.position.y + 5, transform.position.z);
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
transform.position = Vector3.MoveTowards(transform.position, newPosition, 4 * Time.deltaTime);
}
}
}
My problem is that the platform moves up only a little and without the player.
Why the platform moves only once
The reason, the platform moves only once is due to OnTriggerEnter getting called upon entering the trigger not staying inside it. If you want it to get called constantly, while inside it, use OnTriggerStay instead or assign a boolean value inside OnTriggerEnter and OnTriggerExit methods and change your position inside an Update/FixedUpdate.
Why the platform moves without the player
Regarding the platform moving without the player, I'm assuming that the player is a physics object and you expect them to be pushed by it. Potential reasons for that happening:
You are moving the platform too fast
You are moving the platform outside the physics loop
The platform and/or player doesn't have a collider (Trigger colliders do not collide)
Potential solution
It uses OnCollisionEnter instead of the OnTriggerEnter since it seemed to be more appropriate in this case (Make sure to have a non-trigger collider, if you gonna use it).
using UnityEngine;
public class MovingPlatform : MonoBehaviour
{
[SerializeField]
private Vector3 targetPosition = default;
private bool touchingPlayer = false;
private void Start()
{
targetPosition = new Vector3(
transform.position.x,
transform.position.y + 5f,
transform.position.z);
}
private void FixedUpdate()
{
if (touchingPlayer)
{
transform.position = Vector3.MoveTowards(
transform.position,
targetPosition,
4f * Time.fixedDeltaTime);
}
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Player"))
touchingPlayer = true;
}
private void OnCollisionExit(Collision collision)
{
if (collision.gameObject.CompareTag("Player"))
touchingPlayer = false;
}
}
https://streamable.com/mbevlw
Instead Of Moving the platform using Vector3s, Create an animation that plays when the player enters a trigger zone.
Or making them bounce when colliding. but now it's not detecting any collision.
The first cube have a Rigidbody Use Gravity and Is Kinematic both checked enabled true.
If I will disable the Is Kinematic the cube will fall down.
Both cubes have attached the same script.
Both cubes have a box collider and the Is Trigger on both is unchecked disabled.
This script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Door : MonoBehaviour
{
public Transform target;
public float speed;
private void Start()
{
}
private void Update()
{
float step = speed * Time.deltaTime; // calculate distance to move
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
}
}
Each cube have the script and target is the other cube. So both cubes are moving to each other but never collide.
Both cubes settings screenshot :
It would be better practice set rigidbody.velocity once instead of changing transform.position every frame, but this solution should work regardless:
private bool collided = false;
private void Move() {
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
}
private void Update() {
if (!collided) {
Move();
}
}
private void OnCollisionEnter(Collider other) {
if (other.gameObject.GetComponent<Door>() != null) {
collided = true;
}
}
This may not be the best way to do it depending on how you plan on moving forward, but this is a way that works.
If you want to make them bounce, I'd suggest using rigidbody.AddForce() or set rigidbody.velocity. Then you can either use a bouncy physic material or changing the OnCollisionEnter code to use rigidbody.AddForce() or rigidbody.velocity when they collide with each other.