I have been working on enemies in my game, but feel the code is clunky as is and also does not seem to work. I put code into my player script and enemy script. the player script is as follows:
EDIT: sorry for not being clear enough, here are the lines of code that do not work and what I want them to do:
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag == "Enemy")
{
Destroy (this.gameObject);
}
}
What i want in this code is for when the player encounters an enemy or object with the "Enemy" tag, touching that object will destroy or kill the player object.
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag == "Killable")
{
Debug.Log ("entering killzone!");
Destroy (other.gameObject);
Instantiate (DeadStar, transform.position, Quaternion.identity);
this.gameObject.SetActive (false);
}
}
}
This code was loosely copied from a previous game, this has bits of it's killzone and was made to destroy the player object when it touches any object that contains this script. (the player is tagged "Killable")
hope this edit helps, im a little tired and forgot to specify things, sorry about that.
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
public float JumpSpeed;
public float Scale;
public string JumpKey;
public string LeftKey;
public string RightKey;
public float speed;
public GameObject Player;
public Rigidbody2D rb;
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag == "Enemy")
{
Destroy (this.gameObject);
}
}
void Start()
{
GetComponent<Rigidbody2D>().freezeRotation = true; /*GetComponent<Rigidbody>().angularVelocity = Vector3.zero;*/
rb = GetComponent (typeof(Rigidbody2D)) as Rigidbody2D;
}
void FixedUpdate ()
{
Vector3 hold = rb.velocity;
hold.x = 0;
if (Input.GetKey (LeftKey))
{
hold.x -= speed;
}
if (Input.GetKey (RightKey))
{
hold.x += speed;
}
if (Input.GetKeyDown (KeyCode.Space))
{
hold.y = JumpSpeed;
}
rb.velocity = hold;
}
}
The enemy script is as follows:
using UnityEngine;
using System.Collections;
public class EnemyKillzone : MonoBehaviour {
public GameObject DeadStar;
public GameObject Player;
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag == "Killable")
{
Debug.Log ("entering killzone!");
Destroy (other.gameObject);
Instantiate (DeadStar, transform.position, Quaternion.identity);
this.gameObject.SetActive (false);
}
}
}
Related
I am making a game similar to flappy bird I am currently following this guy's tutorial and I'm stuck near the end I have been searching for 4hours and can't find a solution here's the code
Game Manager:
using UnityEngine;
public class GameManager : MonoBehaviour
{
private int score;
public void GameOver()
{
Debug.Log("Game Over!");
}
public void IncreaseScore()
{
score++;
}
}
player:
using UnityEngine;
public class playermove : MonoBehaviour
{
private Vector3 direction;
public float gravity = -9.8f;
public float strength = 5f;
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0))
{
direction = Vector3.up * strength;
}
direction.y += gravity * Time.deltaTime;
transform.position += direction * Time.deltaTime;
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "Obstacle")
{
FindObjectOfType<GameManager>().GameOver();
} else if (other.gameObject.tag == "Score")
{
FindObjectOfType<GameManager>().IncreaseScore();
}
}
}
I'm trying to detect when the player hits a sprite with a tag and 2d collider (set as a trigger)
edit: Inspector ss of trigger object
I'm new to programming and C#. I'm trying to build a melee system for my platform game following tutorials on yt.
This is my PlayerAttack script:
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class PlayerAttack : MonoBehaviour {
//[SerializeField] private float attackCooldown;
[SerializeField] private float range;
[SerializeField] private int damage;
[SerializeField] private LayerMask enemyLayer;
public Transform AttackPoint;
//private float cooldownTimer = Mathf.Infinity;
private Animator anim;
private Enemy enemyHealth;
private void Awake()
{
anim = GetComponent<Animator>();
enemyHealth = GetComponent<Enemy>();
}
private void Update()
{
if (Input.GetButtonDown("Fire1"))
{
anim.SetTrigger("Attack");
Attack();
Debug.Log("attacking");
}
}
private void OnDrawGizmos()
{
if (AttackPoint == null)
return;
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(AttackPoint.position, range);
}
void Attack()
{
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(AttackPoint.position, range, enemyLayer);
foreach (Collider2D Enemy in hitEnemies)
{
Enemy.transform.GetComponent<Enemy>().TakeDamage(damage);
}
}
}
and this one is the EnemyHealth script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
[SerializeField] private int startingHealth;
public int currentHealth;
public Animator anim;
void Start()
{
currentHealth = startingHealth;
}
public void TakeDamage(int _damage)
{
currentHealth = Mathf.Clamp(currentHealth - _damage, 0, startingHealth);
if (currentHealth > 0)
{
//hurt animation
//invulnerability
}
else
{
//die animation
GetComponentInParent<EnemyPatrol>().enabled = false;
GetComponent<EnemyMelee>().enabled = false;
}
}
void Die()
{
if (currentHealth <= 0)
{
Debug.Log("Enemy Dead!");
Destroy(gameObject);
//die animation
}
}
}
I'm getting an error from the Unity editor "object reference not set to an instance of an object" on line 61 of the PlayerAttack:
enter code here
Enemy.transform.GetComponent().TakeDamage(damage);
I checked the scripts names and they are fine, and I checked also if I missed something in the editor , I don't know what's wrong.
When I hit the enemy the game crashes and i get this error.
Thanks
You are trying to call Enemy.transform.GetComponent<Enemy>().TakeDamage(damage); on everything that has collider but some of those objects don't have the Enemy component so you can't call TakeDamage on them. That is where the error comes from. To fix it you have to find only the enemy game objects. To do this you can assign tags to your enemy and check the ones with Enemy tag through the script like this:
foreach (Collider2D Enemy in hitEnemies)
{
if (Enemy.tag == "Enemy")
Enemy.transform.GetComponent<Enemy>().TakeDamage(damage);
}
There is another way to do it without tags which I don't recommend:
foreach (Collider2D Enemy in hitEnemies)
{
if (Enemy.transform.GetComponent<Enemy>() != null)
Enemy.transform.GetComponent<Enemy>().TakeDamage(damage);
}
Check if the player has hit the enemy or not:
foreach (Collider2D hitEnemy in hitEnemies) {
if(hitEnemy.TryGetComponent(out Enemy enemy)) {
enemy.TakeDamage(damage);
}
}
Other than the answer:
In your PlayerAttack.cs script, you have a field enemyHealth which you are trying to get a reference to it using enemyHealth = GetComponent<Enemy>(); in your Awake() method. This doesn't get a reference to it because of Enemy.cs and PlayerAttack.cs scripts are attached to different gameobjects.
I'm still new to coding and this issue has me stuck.
I was following a tutorial video on how to make a power up script but for some reason, it doesn't function.
I've been looking around for a solution but none of them seem to work. Any help would be appreciated!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PowerUpPickupEffect : MonoBehaviour
{
public GameObject pickupEffect;
public float multiplier = 2.0f;
void OnTriggerEnter2D (Collider2D other)
{
if (other.CompareTag ("Player"))
{
Pickup ();
}
}
void Pickup (Collider player)
{
Instantiate (pickupEffect, transform.position, transform.rotation);
player.transform.localScale *= multiplier;
Destroy (gameObject);
}
}
Your method PickUp expects a Collider as parameter.
However: Note that Collider != Collider2D They are from completely two separated and independent physics engines Physics and Physics2D!
For 2D it should rather be
void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
// pass in the expected argument
Pickup(other);
}
}
void Pickup(Collider2D player)
{
Instantiate(pickupEffect, transform.position, transform.rotation);
player.transform.localScale *= multiplier;
Destroy(gameObject);
}
or for 3D
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
// pass in the expected argument
Pickup(other);
}
}
void Pickup(Collider player)
{
Instantiate(pickupEffect, transform.position, transform.rotation);
player.transform.localScale *= multiplier;
Destroy(gameObject);
}
I have 2 monsters and 1 player. when players shoot, i get this mistake and they stop shooting. I have the same code for players, but players can keep shooting. I think the problem is with "destroy" but I can not find a solution enter image description here
public class SpawnBulletController : MonoBehaviour
{
public GameObject bullet;
public float interval = 1F;
// Use this for initialization
void Start () {
InvokeRepeating("ShootBullet", interval, interval);
}
void ShootBullet()
{
GameObject g = Instantiate(bullet, transform.position, Quaternion.identity);
}
}
public class BorderCollision : MonoBehaviour
{
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag != "Player")
Destroy(other.gameObject);
}
}
When your collider hits any GameObject that has no "Player" tag the GameObject will be destroyed this is wrong.
you should try
private void OnCollisionEnter2D(Collision2D collider)
{
if (collider.gameObject.tag == "Monster")
Destroy(collider.gameObject);
}
And if you want to destroy more with the same code but not with the same tag you should try.
private void OnCollisionEnter2D(Collision2D collider)
{
if (collider.gameObject.tag == "Monster" || collider.gameObject.tag == "Monster2")
Destroy(collider.gameObject);
}
So far my script is below. I am attempting to create another Collider part to the script, I am attempting to make it so when you collide with Lava, which has a Tag named lava, the player will die. However, I can't get it to call for the die function and I also can't use OnTriggerEnter(collider,other) as it gives me an error.
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
// Player Movement Start
{
public float speed;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
rb.AddForce(movement * speed);
}
//End of Player Movement Script
//Pickups Script
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Pick Up"))
{
other.gameObject.SetActive(false);
}
}
//End of Pickups Script
//Health and Death Script
public float health;
public GameObject Ragdoll;
public void TakeDamage(float dmg){
health -= dmg;
if (health <= 0) {
Die();
}
}
public void Die() {
Application.LoadLevel(Application.loadedLevel);
}
}
//End of Health and Death script
According to the answer here,
The access level for class members and struct members, including
nested classes and structs, is private by default.
With this logic, and knowing that OnTriggerEnter(...) must be called from outside of your MonoBehaviour, you should probably explicitly make it public
Also, you say you are trying to run your Die(...) method from the OnTriggerEnter(...) function, but i dont see that in your code, it should look as follows:
public void OnTriggerEnter(Collider other)
{
switch (other.tag)
{
case "Pick Up": other.gameObject.SetActive(false);
break;
case "Lava": Die();
break;
}
}