Collision system not working. There are no errors, it just wont register that the projectile hit the player - unity3d

Here is the code in which I was talking about. I can't figure out why my collider isn't working:
using System.Collections.Generic;
using UnityEngine;
public class SphereCollider : MonoBehaviour
{
GameObject obj;
void Awake ()
{
obj = GameObject.FindGameObjectWithTag("Player");
}
// Update is called once per frame
void Update()
{
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.name == "Player")
{
obj.GetComponent<Health>().health -= 25;
}
}
}
}

Rather than using the code you have, make sure to change some code. This is what you should change: get rid of the obj variable and the awake function. Then instead of finding the object with that name, use tag. Also get rid of Update(){} and take the OnCollisionEnter(){} out of it.
A few more changes are shown in code:
void OnCollisionEnter(Collision collision){
var obj = collision.GameObject;
if (obj.Tag == “Player”){
obj.GetComponent<Health>().health -= 25;
}
}
This will work as long as: the script is called Health, the variable inside Health is called health, and it is set to a float, and the player’s tag is set to Player.

Not sure if the code pasted in the question is just copied over wrong, but OnCollisionEnter() is its own unique method and should not be nested in Update().
If the player will be colliding with this Sphere object often, it is good to cache a component rather than using GetComponent frequently. However I assume in your case this Sphere will be one of many obstacles, so calling the GetComponent in the collision is fine. The issue with your current code is the gameObject you are colliding with might not have the name exactly spelled as Player, which would make your collision check fail. Caching the object that has the tag of Player is a bit redundant when you can just check it inside of the collision check.
I will use your entire snippet of code so there is no confusion
using System.Collections.Generic;
using UnityEngine;
public class SphereCollider : MonoBehaviour
{
void OnCollisionEnter(Collision col)
{
// compare if the collider's gameObjects tag is equal to our target tag (Player)
if (col.gameObject.tag == "Player")
{
// get the component of Health on our gameObject that we collided with that has the tag of Player
obj.GetComponent<Health>().health -= 25;
}
}
}

Related

Unity 2020 - 2D Game, Getting an error that my object couldn't be set to an instance of an object while working with Raycasts

I'm currently working on a 2D game on Unity with grid-based movement.
I've run into a problem with the raycasting system (which I plan to use to detect what's in the tile the player is moving to).
My entire player code is split up between groups which are all connected to the parent script known as "playerScript".
I'm getting the errors from the two scripts "PlayerCollisionScript" & "PlayerMovementScript"
PlayerCollisionScript looks like this
using UnityEngine;
public class PlayerCollisionScript : MonoBehaviour
{
[SerializeField]
internal PlayerScript playerScript;
internal void IfPlayerWalkWall()
{
RaycastHit2D hit = Physics2D.Raycast(transform.position, transform.TransformDirection(playerScript.direction), 1f);
if (hit.collider.name == "Walls")
{
Debug.Log("Walk wall");
}
}
}
and PlayerMovementScript
using System.Collections;
using UnityEngine;
public class PlayerMovementScript : MonoBehaviour
{
[SerializeField]
internal PlayerScript playerScript;
private void Update()
{
// What happens when the player moves
if ((playerScript.moveUp == true) && !playerScript.isPlayerMoving)
{
playerScript.direction = Vector2.up;
playerScript.collisionScript.IfPlayerWalkWall();
if (playerScript.hitWall == false)
{
StartCoroutine(MovePlayer(playerScript.direction));
}
playerScript.hitWall = false;
}
}
I keep getting off it the error Error Picture
I've so far have attempted moving the entire Raycast code into the MovementScript but I still got the same error, this error occurs as long as I type in the CollisionScript something to hit for example hit.collider.name will get this error, hit itself will work just fine.
Thanks for anyone willing to help ^^
Please refer to the API:
"This function returns a RaycastHit2D object with a reference to the collider that is hit by the ray (the collider property of the result will be NULL if nothing was hit)."
Especially since you limit the maximum distance of the raycast to 1 unit it is not unlikely that it does hit nothing.
Your script should be checking that before trying to access hit.collider.name
RaycastHit2D hit = Physics2D.Raycast(transform.position, transform.TransformDirection(playerScript.direction), 1f);
if (hit.collider && hit.collider.name.Equals("Walls"))
{
Debug.Log("Walk wall");
}

Pooled GameObject in Unity destroys itself after SetActive if Force is applied

When I retrieve an object from a list of created objects and reactivate it, it destroys itself, but only if I have force applied to start it moving. If I never apply force, everything works as intended and I can keep activating the object over and over.
I've tried putting a debug.log in the OnCollision and it isn't colliding with anything.
As said above, if I never initiate speed, the rest works fine.
When speed is applied, the first projectile works, the second destroys itself.
I've tried manually activating them instead of by code. Same result.
Exception: If I manually activate/deactivate objects myself through the inspector, they work if I only have 1 shot in the pool.
The one shot rule doesn't work if I do it through code. It breaks even if I only have one shot.
All the code worked when I wasn't using pooling.
Spawn code:
void CreateBullet(int GunID)
{
GameObject ShotFired = Guns[GunID].GetComponent<Weapon>().FireWeapon();
if (ShotFired == null)
{
ShotFired = Instantiate(Guns[GunID].GetComponent<Weapon>().Projectile,Guns[GunID].gameObject.transform);
Physics.IgnoreCollision(ShotFired.GetComponent<SphereCollider>(), Guns[GunID].GetComponentInParent<CapsuleCollider>());
Guns[GunID].GetComponent<Weapon>().AmmoPool.Add(ShotFired);
}
ShotFired.transform.position = Guns[GunID].transform.position;
ShotFired.transform.rotation = Guns[GunID].transform.rotation;
ShotFired.SetActive(true);
}
Projectile Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
public class Projectile : NetworkBehaviour
{
public float Speed;
public float LifeTime;
public float DamagePower;
public GameObject ExplosionFX;
// Start is called before the first frame update
void Start()
{
GetComponent<Rigidbody>().AddRelativeForce(Vector3.up * Speed, ForceMode.VelocityChange);
StartCoroutine(DeactivateSelf(5.0f));
}
private void OnDestroy()
{
Debug.Log("WHY!");
}
IEnumerator DeactivateSelf(float Sec)
{
yield return new WaitForSeconds(Sec);
Explode();
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.GetComponentInChildren<Vehicle>())
{
collision.gameObject.GetComponentInChildren<Vehicle>().CmdTakeDamage(DamagePower);
}
Explode();
}
void Explode()
{
GameObject ExplosionEvent = Instantiate(ExplosionFX, this.transform.position, Quaternion.identity);
NetworkServer.Spawn(ExplosionEvent);
GetComponent<Rigidbody>().AddRelativeForce(Vector3.zero);
gameObject.SetActive(false);
}
}
Any thoughts welcome. Thanks in advance!
In case anyone else stumbles across this, here's what happened and why assigning a movement speed to the object was what caused the issue.
My projectiles had a 'trailrenderer' on them.
By default 'Autodestruct' is true.
Autodestruct does not destruct the trail, but the game object when the trail disappears. So if you disable anything that had a trail, and activated it through movement, when the object stops moving (say to reposition in an object pool) it will destroy the parent object.
If the object never moves, it never generates a trail, and never needs to be destroyed.
To fix, just uncheck autodestruct.
https://docs.unity3d.com/ScriptReference/TrailRenderer-autodestruct.html

Unity collision not detected

I'm making a Unity game, in which player should push all "Enemy" object from the plane. So to be able to count the number of fallen objects I want to generally be able to tell when a collision occurred between the red cube and every other cube. The script seems to not detect a collision, how to fix it?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Collide : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Enemy")
Destroy(gameObject);
Debug.Log("Hit Occured");
}
}
you need OnCollisionEnter
void OnCollisionEnter(Collision collision){
}
because your colliders aren't triggers.
You need to implement OnCollisionEnter(Collision collision) not OnTriggerEnter(Collider other) or check BoxCollider IsTrigger checkbox
There are 3 things to be checked
1. The OnCollisionEnter should be used in place of OnTriggerEnter
2. isTrigger checkbox should be enabled so that the event is triggered when the both bodies collide with other .
3. The most important thing which no one has mentioned is the tags given to the gameobject or the enemies because we need to define the gameobject that event should be triggered when hit to the specific body because the gameobject contains the collider and can collide to any wall or something so you need to define the tags properly

Unity: NullReferenceException: Object reference not set to an instance of an object

I am following an Unity tutorial. I face a problem when trying to detect collision in the game. This is the error:
NullReferenceException: Object reference not set to an instance of an object
This is the script:
using UnityEngine;
public class Collide : MonoBehaviour
{
public Movement movement; // A reference to our PlayerMovement script
// This function runs when we hit another object.
// We get information about the collision and call it "collisionInfo".
void OnCollisionEnter(Collision collisionInfo)
{
// We check if the object we collided with has a tag called "Obstacle".
if (collisionInfo.collider.tag == "Obstacle")
{
movement.enabled = false; // Disable the players movement.
Debug.Log("Coollision occured");
}
}
}
As i saw in the second image you have not added the movement reference to the movement field. At the same in the script also you are not assigning the reference. Try to assign at editor or you can create object.
The reason is you have not set the movement field in your Collide component.
You can add it from the Unity Editor or add the following line in your Start function of Collide :
void Start()
{
movement = GetComponent<Movement>();
}

2D player damage on trigger collider

So I'm making a little top down space shooter and everything works great so far. My issue is that when I change weapons I would like the secondary to do more damage than the primary (changeable with the number keys). It's been a real head scratcher and any help would be greatly appreciated. this is what I tried;
adding the weapons to individual layers. in the OnTriggerEnter2D function I make an if statement stating if the gameObject (bullet) is firing from layer 13, take away x amount of HP. Doesn't do anything though. below is my current code for the enemy.
using UnityEngine;
using System.Collections;
public class enemyDamage : MonoBehaviour {
public int health = 2;
void OnTriggerEnter2D(){
health--;
}
void Start () {
}
void Update () {
if (health <= 0){
Die();
}
}
void Die(){
Destroy (gameObject);
}
}
You can change your OnTriggerEnter2D function by adding Collider2D parameter to it. That way you can get access to the gameObject that triggered the function.
You didn't post the code that is instantiating the bullet. But if you set bullets name to different values you can decrease the health based on that.
void OnTriggerEnter2D(Collider2D other) {
if(other.gameObject.name == "missile"){
health -= 10;
}else if(other.gameObject.name == "bullet"){
health -= 1;
}
}
Or even better idea might be adding a script to the bullet, which knows the amount of damage the bullet is going to make.
void OnTriggerEnter2D(Collider2D other) {
health -= other.gameObject.GetComponent<BulletScript>().damage;
}