PLAYER = Ninja Boy
ENEMY = Ninja girl
I have two game objects, one is enemy and the other is player both having colliders2D and rigidbody2D.
I made a script for enemy chase my when i;m in his sight(i made a boxcollider2d for this) and when he's close enought he start's attacking. To detect collision between he's sword and me i made an edge collider that he enables it when starts attacking and disable when the attack animation is done
The problem is that when i don't move, the player OnEnterTrigger2D function doesn't detect the collision
if i'm in this position (the player is clearly inside the collider)
This is the Player class
public override IEnumerator TakeDamage()
{
if (!immortal && !IsDead)
{
health -= 10;
Animator.SetLayerWeight(1, 0);
if (!IsDead)
{
Animator.SetTrigger("damage");
Rigidbody.velocity = Vector2.zero;
immortal = true;
yield return new WaitForSeconds(immortalTimer);
immortal = false;
}
}
if(IsDead)
{
Animator.SetTrigger("dead");
}
}
protected override void OnTriggerEnter2D(Collider2D collider)
{
Debug.Log(collider.name);
base.OnTriggerEnter2D(collider);
}
and the player inherits from Character
public abstract IEnumerator TakeDamage();
protected virtual void OnTriggerEnter2D(Collider2D collider)
{
if (damagingObjects.Contains(collider.tag))
{
StartCoroutine(TakeDamage());
}
}
and i noticed that if a manualy activate the enemy's trigger while playing, the player will take damege even if he's not moving
Related
So I am trying to make it so that when the user shoots the recoil animation plays, but I have an issue where the bool (which goes true the moment the Fire() is called), instantly goes back to false. I have tried to remove the line of code which is supposed to only make the bool false once the user stopped firing the gun, but the result of that was just the recoil animation playing in a loop.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WeaponFire : MonoBehaviour
{
public GameObject playerCam; // The player camera
public float range = 150f;
public float damage = 25f;
public float rounds = 30f;
public float mags = 3f;
public GameObject FPS_char; // The gameobject that has the animator
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (FPS_char.GetComponent<Animator>().GetBool("WeaponFire")) // Check to see if the player has fired
{
FPS_char.GetComponent<Animator>().SetBool("WeaponFire", false); // Set to false if true
}
}
public void Fire()
{
// Shoot a ray
RaycastHit hit;
// Set the WeaponFire bool to true when Fire() is called, which is called when the player presses the left mouse button
FPS_char.GetComponent<Animator>().SetBool("WeaponFire", true);
// Create a ray
if (Physics.Raycast(playerCam.transform.position, playerCam.transform.forward, out hit, range))
{
if (rounds <= 0)
{
// Player needs to reload
return;
}
if(rounds >= 0)
{
rounds -= 1f;
gameObject.GetComponent<AudioSource>().Play(); // Play a weapon fire sound
EnemyManager enemyManager = hit.transform.GetComponent<EnemyManager>(); // A script that gives the enemies health and attack damage etc
if (enemyManager != null) // check to see if what the player hit contains that script (if it does then it is an enemy)
{
enemyManager.Hit(damage); // Call the Hit() function of the script on the enemy which removes health from the enemy depending on how much damage the weapon does
}
}
}
}
public void Reload()
{
mags -= 1f;
rounds = 30f;
// Add a reload animation
}
}
For things that need to play once use animator.SetTrigger which plays the animation when it is called once automatically. You need to change the Animator parameter from Bool to Trigger in the Animator window.
public void Fire()
{
FPS_char.GetComponent<Animator>().SetTrigger("Fire");
}
so I'm making a 2d platform. My level is made up of a multiple platforms that are all part of a prefab. I want to make it so when my player presses a key (in this case 'E') inside of a collider2d the platform above the player is destroyed and the box resting on the platform falls down.
I've got the detection working for when 'E' is pressed inside of the trigger but can't figure out how to destroy just the single platform in the prefab.
Any help would be appreciated!
public class SwitchController : MonoBehaviour
{
public Collider2D switchCollider;
public Rigidbody2D player;
void Start()
{
switchCollider = GetComponent<Collider2D>();
}
private void OnTriggerStay2D(Collider2D col)
{
// var player = col.GetComponent<PlayerController>();
var actionBtn = PlayerController.action;
if (player)
{
Debug.Log("Collided");
if (Input.GetKeyDown(KeyCode.E))
{
actionBtn = true;
Debug.Log("Action Pressed");
}
}
}
}
If possible, the simplest solution would be to store the platform via the inspector (of the prefab).
Then you would destroy the game-object when needed, like so:
public class SwitchController : MonoBehaviour {
// ...
public GameObject targetPlatform;
private void OnTriggerStay2D(Collider2D col) {
// ...
Destroy(targetPlatform); // Destroy the platform.
}
}
Or, you can raycast upwards from the player
public class SwitchController : MonoBehaviour {
public Collider2D switchCollider;
public Rigidbody2D player;
[SerializeField, Tooltip("The layer mask of the platforms.")]
public LayerMask platformLayerMask;
void Start() {
switchCollider = GetComponent<Collider2D>();
}
private void OnTriggerStay2D(Collider2D col) {
var actionBtn = PlayerController.action;
if (player) {
if (Input.GetKeyDown(KeyCode.E)) {
actionBtn = true;
// Raycast upwards from the player's location.
// (Raycast will ignore everything but those with the same layermask as 'platformPlayerMask')
RaycastHit2D hit = Physics2D.Raycast(player.transform.position, Vector2.up, Mathf.Infinity, platformLayerMask);
if (hit.collider != null) {
// Destroy what it hits.
Destroy(hit.transform.gameObject);
}
}
}
}
}
Compared to the first solution, this solution is more dynamic.
You just have to set the Layers of the platforms in the inspector.
I have a game with a player and an enemy.
I also have a particle system for when the player dies, like an explosion.
I have made this particle system a prefab so I can use it multiple times per level as someone might die a lot.
So in my enemy.cs script, attached to my enemy, I have:
public GameObject deathParticle;
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.name == "Player" && !player.dead){
player.dead = true;
Instantiate(deathParticle, player.transform.position, player.transform.rotation);
player.animator.SetTrigger("Death");
}
}
So this plays my particle system when the player gets killed by an enemy. Now on my player script, I have this. This specific function gets played after the death animation:
public void RespawnPlayer()
{
Rigidbody2D playerBody = GetComponent<Rigidbody2D>();
playerBody.transform.position = spawnLocation.transform.position;
dead = false;
animator.Play("Idle");
Enemy enemy = FindObjectOfType<Enemy>();
Destroy(enemy.deathParticle);
}
This respawns the player like normal but in my project each time I die I have a death (clone) object which I don't want. The last 2 lines are meant to delete this but it doesn't.
I have also tried this which didn't work:
Enemy enemy = FindObjectOfType<Enemy>();
ParticleSystem deathParticles = enemy.GetComponent<ParticleSystem>();
Destroy(deathParticles);
There is no need to Instantiate and Destroy the death particle, that will create a lot of overhead, you can simply replay it when you want it to start and stop it, when you dont need it
ParticleSystem deathParticleSystem;
private void OnTriggerEnter2D(Collider2D collision)
{
#rest of the code
deathParticleSystem.time = 0;
deathParticleSystem.Play();
}
public void RespawnPlayer()
{
//rest of the code
deathParticleSystem.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
}
or you can enable and disable the gameObject associated with your particle prefab
public GameObject deathParticlePrefab;
private void OnTriggerEnter2D(Collider2D collision)
{
#rest of the code
deathParticlePrefab.SetActive(true);
}
public void RespawnPlayer()
{
//rest of the code
deathParticlePrefab.SetActive(false);
}
You could always create a new script and assign it to the prefab that destroys it after a certain amount of time:
using UnityEngine;
using System.Collections;
public class destroyOverTime : MonoBehaviour {
public float lifeTime;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
lifeTime -= Time.deltaTime;
if(lifeTime <= 0f)
{
Destroy(gameObject);
}
}
}
So in this case you would assign this to your deathParticle. This script is useful in a multitude of scenarios if you're instantiating objects so that you don't have a load of unnecessary objects.
I a have this enemy prefab that gets instantiated from a spawn point in my game, on the enemy prefab I have a particle system componet that if the player shoots the enemy more than 2 times the particle system will play. However I'm having problems with firing the particle system on only one of the enemy prefab that the player shot. Is there a way when the enemy prefab gets shot at to fire the particle system on that enemy prefab rather than the particle system playing when the enemy prefab gets shoot at and any other enemies prefabs that didn't get shot at without using ontriggerenter2d as I had some problems.
This is the script attached to the player:
public GameObject enemy;
public static bool firePar = false;
public static int combo = 0;
void Start (){
firePar = false;
combo = 0;
}
void OnTriggerEnter2D(Collider2D col) {
if(col.tag == "Enemy") {
Destroy(col.gameObject,0.2f);
}
}
void Update() {
if(combo >= 10) {
firePar = true;
} else if (combo < 10) {
firePar = false;
}
}
This is the code on the enemy (for firing the particles):
private ParticleSystem par;
void Start (){
par = GetComponent<ParticleSystem>();
}
void Update () {
if(Playerbullet.firePar == true) {
par.Play();
} else {
par.Stop ();
}
}
I am completely new to Unity. I am having difficulty in building a FPS shooter. Here is my code in Ammo prefab:
public class Ammo : MonoBehaviour {
public GameObject obj ;
// Use this for initialization
void Start () {
obj= GameObject.FindGameObjectWithTag ("Player");
}
// Update is called once per frame
void Update () {
transform.Translate (obj.transform.forward* Time.deltaTime);
}
void OnCollision(Collider coll)
{
if (coll.tag != "Player")
Destroy (gameObject);
}
}
And in FPS:
public class FPS : MonoBehaviour {
public GameObject Ammo;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetButtonDown("Fire1"))
{
Instantiate(Ammo, transform.position,transform.rotation);
}
}
}
But when I shoot the sphere goes in random direction. (It goes up when I look forward). Is there anyone help me. I am absolutely new to Unity.
Bullet doesn't go in random direction. It depends on your player position. First of all you should take forward vector from players camera NOT FROM PLAYER. Because you want to shoot the direction you look at (thus the camera).