Ammo Limitations in Unity2D (Top Down) - c#

I am fairly new to C# and am currently trying to expand upon Ruby's Tutorial by adding in an ammo limitation function that controls the amount of Cogs Ruby has at a time as well as her ability to pick up extra ammo. Right now my script is not limiting the number of rounds Ruby can fire and is stuck displaying "Cogs: 4". She is able to pick up the ammo (pickup set to is trigger) but it is not updating the Cogs. Please help, I would love to understand what I am possibly doing wrong as my code is not displaying any errors.
Ruby's Controller Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.SceneManagement;
public class RubyController : MonoBehaviour
{
public float speed = 3.0f;
public int maxHealth = 5;
public GameObject projectilePrefab;
public int Score;
int Cog;
public static int CogAmount = 4;
public TextMeshProUGUI scoreText;
public TextMeshProUGUI CogText;
public GameObject winTextObject;
public GameObject loseTextObject;
public GameObject BackgroundMusicObject;
public GameObject WinSoundObject;
public GameObject LoseSoundObject;
public AudioClip throwSound;
public AudioClip hitSound;
public AudioClip collectedClip;
public int health { get { return currentHealth; }}
int currentHealth;
public float timeInvincible = 2.0f;
bool isInvincible;
float invincibleTimer;
Rigidbody2D rigidbody2d;
float horizontal;
float vertical;
public ParticleSystem HealthIncrease;
public ParticleSystem HealthDecrease;
Animator animator;
Vector2 lookDirection = new Vector2(1,0);
AudioSource audioSource;
// Start is called before the first frame update
void Start()
{
rigidbody2d = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
currentHealth = maxHealth;
audioSource = GetComponent<AudioSource>();
Score = 0;
Cog = 4;
SetCogText();
winTextObject.SetActive(false);
loseTextObject.SetActive(false);
WinSoundObject.SetActive(false);
LoseSoundObject.SetActive(false);
HealthIncrease.Stop();
HealthDecrease.Stop();
}
public void ChangeScore(int scoreAmount)
{
{
Score++;
scoreText.text = "Fixed Robots: " + Score.ToString();
}
}
// Update is called once per frame
void Update()
{
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
Vector2 move = new Vector2(horizontal, vertical);
if(!Mathf.Approximately(move.x, 0.0f) || !Mathf.Approximately(move.y, 0.0f))
{
lookDirection.Set(move.x, move.y);
lookDirection.Normalize();
}
animator.SetFloat("Look X", lookDirection.x);
animator.SetFloat("Look Y", lookDirection.y);
animator.SetFloat("Speed", move.magnitude);
if (isInvincible)
{
invincibleTimer -= Time.deltaTime;
if (invincibleTimer < 0)
isInvincible = false;
}
if(Input.GetKeyDown(KeyCode.C) && Cog >= 1)
{
Cog = Cog -1;
Launch();
}
else if (Input.GetKeyDown(KeyCode.C) && Cog ==0)
{
return;
}
if (Input.GetKeyDown(KeyCode.X))
{
RaycastHit2D hit = Physics2D.Raycast(rigidbody2d.position + Vector2.up * 0.2f, lookDirection, 1.5f, LayerMask.GetMask("NPC"));
if (hit.collider != null)
{
NonPlayerCharacter character = hit.collider.GetComponent<NonPlayerCharacter>();
if (character != null)
{
character.DisplayDialog();
}
}
}
if (CogAmount > 0)
{
CogText.text = "Cogs: " + CogAmount;
}
else if (CogAmount <= 0)
{
CogText.text = "Out of Cogs!";
}
if (Score >= 4)
{
winTextObject.SetActive(true);
{
if(Input.GetKeyDown(KeyCode.R))
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
speed = 0;
WinSoundObject.SetActive(true);
BackgroundMusicObject.SetActive(false);
}
}
else if (currentHealth == 0)
{
loseTextObject.SetActive(true);
{
if(Input.GetKeyDown(KeyCode.R))
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
speed = 0;
LoseSoundObject.SetActive(true);
BackgroundMusicObject.SetActive(false);
}
}
if (Input.GetKeyDown(KeyCode.Escape))
{
Application.Quit();
}
}
void FixedUpdate()
{
Vector2 position = rigidbody2d.position;
position.x = position.x + speed * horizontal * Time.deltaTime;
position.y = position.y + speed * vertical * Time.deltaTime;
rigidbody2d.MovePosition(position);
}
void SetCogText()
{
CogText.text = "Cogs: " + Cog.ToString();
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("Cog"))
{
Cog = Cog + 3;
other.gameObject.SetActive(false);
}
}
public void ChangeHealth(int amount)
{
if (amount < 0)
{
if (isInvincible)
return;
isInvincible = true;
invincibleTimer = timeInvincible;
GameObject projectileObject = Instantiate(HealthDecrease.gameObject, rigidbody2d.position + Vector2.up * 0.5f, Quaternion.identity);
Projectile projectile = projectileObject.GetComponent<Projectile>();
PlaySound(hitSound);
}
if (amount < 5)
{
GameObject projectileObject = Instantiate(HealthIncrease.gameObject, rigidbody2d.position + Vector2.up * 0.5f, Quaternion.identity);
}
currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth);
UIHealthBar.instance.SetValue(currentHealth / (float)maxHealth);
}
void Launch()
{
GameObject projectileObject = Instantiate(projectilePrefab, rigidbody2d.position + Vector2.up * 0.5f, Quaternion.identity);
Projectile projectile = projectileObject.GetComponent<Projectile>();
projectile.Launch(lookDirection, 300);
animator.SetTrigger("Launch");
PlaySound(throwSound);
}
public void PlaySound(AudioClip clip)
{
audioSource.PlayOneShot(clip);
}
}
Projectile Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectile : MonoBehaviour
{
Rigidbody2D rigidbody2d;
void Awake()
{
rigidbody2d = GetComponent<Rigidbody2D>();
}
public void Launch(Vector2 direction, float force)
{
rigidbody2d.AddForce(direction * force);
}
void Update()
{
if(transform.position.magnitude > 1000.0f)
{
Destroy(gameObject);
}
}
void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag == "Enemy")
{
EnemyController e = other.collider.GetComponent<EnemyController>();
if (e != null)
{
e.Fix();
}
}
else if (other.gameObject.tag == "HardEnemy")
{
HardEnemyController e = other.collider.GetComponent<HardEnemyController>();
if (e != null)
{
e.Fix();
}
}
Destroy(gameObject);
}
}

Ok after a bit of trial and error I believe I have finally fixed the issue. I will post my updated script for anyone wanting to compare and/or learn from my mistakes lol. Basically I utilized a SetCogText(); variable in the start function and throughout my code to update my TextMeshPro; and removed the public static int CogAmount = 0; I initially used in my code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.SceneManagement;
public class RubyController : MonoBehaviour
{
public float speed = 3.0f;
public int maxHealth = 5;
public GameObject projectilePrefab;
public int Score;
int Cog;
public TextMeshProUGUI scoreText;
public TextMeshProUGUI CogText;
public GameObject winTextObject;
public GameObject loseTextObject;
public GameObject LevelOneTextObject;
public GameObject BackgroundMusicObject;
public GameObject WinSoundObject;
public GameObject LoseSoundObject;
private static int Level;
public AudioClip throwSound;
public AudioClip hitSound;
public AudioClip collectedClip;
public int health { get { return currentHealth; }}
int currentHealth;
public float timeInvincible = 2.0f;
bool isInvincible;
float invincibleTimer;
Rigidbody2D rigidbody2d;
float horizontal;
float vertical;
public ParticleSystem HealthIncrease;
public ParticleSystem HealthDecrease;
Animator animator;
Vector2 lookDirection = new Vector2(1,0);
AudioSource audioSource;
// Start is called before the first frame update
void Start()
{
rigidbody2d = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
currentHealth = maxHealth;
audioSource = GetComponent<AudioSource>();
Score = 0;
Cog = 4;
SetCogText();
winTextObject.SetActive(false);
loseTextObject.SetActive(false);
LevelOneTextObject.SetActive(false);
WinSoundObject.SetActive(false);
LoseSoundObject.SetActive(false);
HealthIncrease.Stop();
HealthDecrease.Stop();
}
public void ChangeScore(int scoreAmount)
{
{
Score++;
scoreText.text = "Fixed Robots: " + Score.ToString();
}
if (Level == 1)
{
if (Score == 4)
{
LevelOneTextObject.SetActive(true);
}
}
if (Level == 2)
{
if(Score == 4)
{
winTextObject.SetActive(true);
{
if(Input.GetKeyDown(KeyCode.R))
SceneManager.LoadScene(1);
speed = 0;
WinSoundObject.SetActive(true);
BackgroundMusicObject.SetActive(false);
}
}
}
}
// Update is called once per frame
void Update()
{
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
Vector2 move = new Vector2(horizontal, vertical);
if(!Mathf.Approximately(move.x, 0.0f) || !Mathf.Approximately(move.y, 0.0f))
{
lookDirection.Set(move.x, move.y);
lookDirection.Normalize();
}
animator.SetFloat("Look X", lookDirection.x);
animator.SetFloat("Look Y", lookDirection.y);
animator.SetFloat("Speed", move.magnitude);
if (isInvincible)
{
invincibleTimer -= Time.deltaTime;
if (invincibleTimer < 0)
isInvincible = false;
}
if(Input.GetKeyDown(KeyCode.C) && Cog >= 1)
{
Cog = Cog -1;
SetCogText();
Launch();
}
else if (Input.GetKeyDown(KeyCode.C) && Cog ==0)
{
return;
}
if (Input.GetKeyDown(KeyCode.X))
{
RaycastHit2D hit = Physics2D.Raycast(rigidbody2d.position + Vector2.up * 0.2f, lookDirection, 1.5f, LayerMask.GetMask("NPC"));
if (hit.collider != null)
{
if (Score >= 4)
{
Level = 2;
SceneManager.LoadScene(2);
Score = 4;
}
else if (Score < 4)
{
NonPlayerCharacter character = hit.collider.GetComponent<NonPlayerCharacter>();
if (character != null)
{
character.DisplayDialog();
}
}
}
}
if (currentHealth == 0)
{
loseTextObject.SetActive(true);
{
if(Input.GetKeyDown(KeyCode.R))
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
speed = 0;
LoseSoundObject.SetActive(true);
BackgroundMusicObject.SetActive(false);
}
}
if (Input.GetKeyDown(KeyCode.Escape))
{
Application.Quit();
}
}
void SetCogText()
{
if (Cog > 0)
{
CogText.text = "Cogs: " + Cog.ToString();
}
else if (Cog <= 0)
{
CogText.text = "Out of Cogs!";
SetCogText();
}
}
void FixedUpdate()
{
Vector2 position = rigidbody2d.position;
position.x = position.x + speed * horizontal * Time.deltaTime;
position.y = position.y + speed * vertical * Time.deltaTime;
rigidbody2d.MovePosition(position);
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("Cog"))
{
Cog = Cog + 3;
other.gameObject.SetActive(false);
SetCogText();
}
}
public void ChangeHealth(int amount)
{
if (amount < 0)
{
if (isInvincible)
return;
isInvincible = true;
invincibleTimer = timeInvincible;
GameObject projectileObject = Instantiate(HealthDecrease.gameObject, rigidbody2d.position + Vector2.up * 0.5f, Quaternion.identity);
Projectile projectile = projectileObject.GetComponent<Projectile>();
PlaySound(hitSound);
}
if (amount < 5)
{
GameObject projectileObject = Instantiate(HealthIncrease.gameObject, rigidbody2d.position + Vector2.up * 0.5f, Quaternion.identity);
}
currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth);
UIHealthBar.instance.SetValue(currentHealth / (float)maxHealth);
}
void Launch()
{
GameObject projectileObject = Instantiate(projectilePrefab, rigidbody2d.position + Vector2.up * 0.5f, Quaternion.identity);
Projectile projectile = projectileObject.GetComponent<Projectile>();
projectile.Launch(lookDirection, 300);
animator.SetTrigger("Launch");
PlaySound(throwSound);
}
public void PlaySound(AudioClip clip)
{
audioSource.PlayOneShot(clip);
}
}

Related

Unity c# make player move as a projectile after colliding with other gameObjects

When shooting a bullet or making a bomb explode, the player doesn't move as a projectile. Instead, they just move an unusually little distance. The players move as expected - a projectile, after reassigning groundCheck to "none", but the players themselves can't be moved any more. When colliding with a bullet or is in the range of a bomb, how can I change the code so that the player can move as a projectile without assigning groundCheck to "none" ?
Code of player:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveWASDPlayer1 : MonoBehaviour
{
public float speed = 5;
public float jumpForce = 10;
private float moveInput;
private Rigidbody2D rb;
private bool facingRight = true;
private bool isGrounded;
public Transform groundCheck;
public float checkRadius = 0.5f;
public LayerMask whatIsGround;
private int extraJumps;
public int extraJumpsValue = 1;
public Sprite Player1Shoot;
public Sprite Player1idle;
public GameObject Player2;
public GameObject PistolBulletToRight, PistolBulletToLeft;
Vector2 PistolBulletPos;
public float fireRate;
public int remainingBullet = 10;
private void Start()
{
extraJumps = extraJumpsValue;
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
Physics2D.IgnoreLayerCollision(6, 7);
Shoot();
CheckJumps();
Flip();
StartCoroutine(Fire());
moveInput = Input.GetAxis("Horizontal1");
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
if (Input.GetKeyDown(KeyCode.S))
{
Physics2D.IgnoreLayerCollision(3, 6, true);
Invoke("StopCollidingIntoGround", 0.25f);
}
}
void CheckJumps()
{
isGrounded = Physics2D.OverlapCircle(groundCheck.position, checkRadius, whatIsGround);
if (isGrounded == true)
{
extraJumps = extraJumpsValue; ;
}
if (Input.GetKeyDown(KeyCode.W) && extraJumps > 0)
{
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
extraJumps--;
Physics2D.IgnoreLayerCollision(3, 6, true);
Invoke("StopCollidingIntoGround", 0.48f);
}
else if (Input.GetKeyDown(KeyCode.W) && extraJumps == 0 && isGrounded == true)
{
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
}
void Flip()
{
if (facingRight == false && moveInput > 0)
{
facingRight = !facingRight;
Vector3 Scaler = transform.localScale;
Scaler.x *= -1;
transform.localScale = Scaler;
}
else if (facingRight == true && moveInput < 0)
{
facingRight = !facingRight;
Vector3 Scaler = transform.localScale;
Scaler.x *= -1;
transform.localScale = Scaler;
}
}
void StopCollidingIntoGround()
{
Physics2D.IgnoreLayerCollision(3, 6, false);
}
void Shoot()
{
if (Input.GetKeyDown(KeyCode.Z))
{
this.gameObject.GetComponent<SpriteRenderer>().sprite = Player1Shoot;
}
if (Input.GetKeyUp(KeyCode.Z))
{
this.gameObject.GetComponent<SpriteRenderer>().sprite = Player1idle;
}
}
IEnumerator Fire()
{
PistolBulletPos = transform.position;
if (remainingBullet < 1)
{
yield return new WaitForSeconds(2);
remainingBullet = 10;
}
if (Input.GetKeyDown(KeyCode.Z) && remainingBullet > 0)
{
if (facingRight)
{
PistolBulletPos += new Vector2(+1f, -0.1f);
Instantiate(PistolBulletToRight, PistolBulletPos, Quaternion.identity);
remainingBullet--;
yield return new WaitForSeconds(fireRate);
}
else
{
PistolBulletPos += new Vector2(-1f, -0.1f);
Instantiate(PistolBulletToLeft, PistolBulletPos, Quaternion.identity);
remainingBullet--;
yield return new WaitForSeconds(fireRate);
}
}
}
}
Code of bomb:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bomb : MonoBehaviour
{
Collider2D[] inExplosionRadius = null;
[SerializeField] private float ExplosionForceMulti = 5;
[SerializeField] private float ExplosionRadius = 5;
private void Update()
{
if(Input.GetKeyDown(KeyCode.X))
{
Explode();
}
}
void Explode()
{
inExplosionRadius = Physics2D.OverlapCircleAll(transform.position, ExplosionRadius);
foreach(Collider2D o in inExplosionRadius)
{
Rigidbody2D o_rigidbody = o.GetComponent<Rigidbody2D>();
if (o_rigidbody != null)
{
Vector2 distanceVector = o.transform.position - transform.position;
if(distanceVector.magnitude > 0)
{
float explosionForce = ExplosionForceMulti / distanceVector.magnitude;
o_rigidbody.AddForce(distanceVector.normalized * explosionForce);
}
}
}
}
private void OnDrawGizmos()
{
Gizmos.DrawWireSphere(transform.position, ExplosionRadius);
}
}
Code of bullet:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PistolBullet : MonoBehaviour
{
public float velX = 5f;
float velY = 0f;
Rigidbody2D rb;
Collider2D[] inShootRadius = null;
[SerializeField] public float ShootForceMulti = 5;
[SerializeField] public float ShootRadius = 5;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void Update()
{
rb.velocity = new Vector2(velX, velY);
Destroy(gameObject, 3f);
Shoot();
}
public void Shoot()
{
inShootRadius = Physics2D.OverlapCircleAll(transform.position, ShootRadius);
foreach (Collider2D o in inShootRadius)
{
Rigidbody2D o_rigidbody = o.GetComponent<Rigidbody2D>();
if (o_rigidbody != null)
{
Vector2 distanceVector = o.transform.position - transform.position;
if (distanceVector.magnitude > 0)
{
float explosionForce = ShootForceMulti / distanceVector.magnitude;
o_rigidbody.AddForce(distanceVector.normalized * explosionForce);
}
}
}
}
private void OnCollisionEnter(Collision collision)
{
Destroy(gameObject);
}
}
If I understand correctly: When getting hit by a bullet or explosion the player is not flung as expected?
I would argue this is the culprit: rb.velocity = new Vector2(moveInput * speed, rb.velocity.y); as you are overriding the player velocity every frame without taking in account the current velocity, unless moveInput has that calculated into.
As to why it works when GroundCheck is unassigned, because the script stops executing due to the missing reference beforehand and the Rigidbody will only be modified from the other scripts.

Unity2D-How to restore hearts after destroying them when Player gets hit

I am using Destroy(Corazones[0].gameObject); to destroy 5 hearts in an array, but I need to restore them when the player gets another heart. I already have the collider that increases lives +1 and it works, but I do not know how to respawn the heart that represents that life.
The hearts get destroyed when the player gets Hit(); but I also need for the hearts to get restored with Vida(); which increases the live +1
Thanks for your help!
This is the way the hearts look
My code uses spanish words.
PD: I know my code is a mess, but works for the other stuff.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityStandardAssets.CrossPlatformInput;
using UnityEngine.UI;
public class DixonMovement : MonoBehaviour
{
public GameObject PildoraPrefab;
public float Speed;
public float JumpForce;
public AudioClip Golpe;
public AudioClip Salto;
public AudioClip Muerte;
public AudioClip Caida;
public GameObject[] Corazones;
private Rigidbody2D Rigidbody2D;
private Animator Animator;
private float Horizontal;
private bool Grounded;
private float LastShoot;
private int Health = 5;
public bool YaSono = false;
[Header("IFrame Stuff")]
public Color flashColor;
public Color regularColor;
public float flashDuration;
public int numberOfFlashes;
public Collider2D triggerCollider;
public SpriteRenderer mySprite;
float timer;
bool invencible = false;
private void Start()
{
Rigidbody2D = GetComponent<Rigidbody2D>();
Animator = GetComponent<Animator>();
}
// Update is called once per frame
private void Update()
{
timer -= Time.deltaTime;
if (timer <= 0)
{
invencible = false;
}
Horizontal = CrossPlatformInputManager.GetAxis("Horizontal");
if (Horizontal < 0.0f) transform.localScale = new Vector3(-1.0f, 1.0f, 1.0f);
else if (Horizontal > 0.0f) transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
Animator.SetBool("Caminar", Horizontal != 0.0f);
Debug.DrawRay(transform.position, Vector3.down * 0.5f, Color.red);
if (Physics2D.Raycast(transform.position, Vector3.down, 0.5f))
{
Grounded = true;
}
else Grounded = false;
if (CrossPlatformInputManager.GetButtonDown("Jump") && Grounded)
{
Jump();
}
if (Input.GetKeyDown(KeyCode.W) && Grounded)
{
Jump();
}
if (Input.GetKey(KeyCode.Space) && Time.time > LastShoot + 0.25f)
{
Shoot();
LastShoot = Time.time;
}
if (CrossPlatformInputManager.GetButtonDown("Shoot") && Time.time > LastShoot + 0.50f)
{
Shoot();
LastShoot = Time.time;
}
/* if (CrossPlatformInputManager.GetButtonDown("Vertical") && Time.time > LastShoot + 0.50f)
{
Shoot();
LastShoot = Time.time;
}*/
if (transform.position.y <= -2)
{
Fall();
}
}
private void FixedUpdate()
{
Rigidbody2D.velocity = new Vector2(Horizontal * Speed, Rigidbody2D.velocity.y);
}
private void Jump()
{
Rigidbody2D.AddForce(Vector2.up * JumpForce);
Camera.main.GetComponent<AudioSource>().PlayOneShot(Salto);
}
private void Shoot()
{
Vector3 direction;
if (transform.localScale.x == 1.0f) direction = Vector3.right;
else direction = Vector3.left;
GameObject pastilla = Instantiate(PildoraPrefab, transform.position + direction * 0.40f, Quaternion.identity);
pastilla.GetComponent<Pastilla>().SetDirection(direction);
}
**public void Hit()
{
Health -= 1;
if (Health > 0)
{
StartCoroutine(FlashCo());
}
if (Health < 1)
{
Destroy(Corazones[0].gameObject);
}
else if (Health < 2)
{
Destroy(Corazones[1].gameObject);
}
else if (Health < 3)
{
Destroy(Corazones[2].gameObject);
}
else if (Health < 4)
{
Destroy(Corazones[3].gameObject);
}
else if (Health < 5)
{
Destroy(Corazones[4].gameObject);
}
if (Health > 0)
{
Camera.main.GetComponent<AudioSource>().PlayOneShot(Golpe);
}**
if (Health == 0)
{
Camera.main.GetComponent<AudioSource>().PlayOneShot(Muerte);
Animator.SetTrigger("Muerte");
if (Grounded == false)
{
Rigidbody2D.bodyType = RigidbodyType2D.Dynamic;
Rigidbody2D.gravityScale = 2;
}
else
{
Rigidbody2D.bodyType = RigidbodyType2D.Static;
}
}
}
public void Fall()
{
if (transform.position.y <= -1)
{
Rigidbody2D.AddForce(Vector2.up * 60);
if (!YaSono)
{
Camera.main.GetComponent<AudioSource>().PlayOneShot(Caida);
YaSono = true;
}
Animator.SetTrigger("Muerte");
Health = 0;
Destroy(Rigidbody2D, 2);
Destroy(Corazones[0].gameObject);
Destroy(Corazones[1].gameObject);
Destroy(Corazones[2].gameObject);
Destroy(Corazones[3].gameObject);
Destroy(Corazones[4].gameObject);
Invoke("RestartLevel", 2);
}
}
public void Vida()
{
if (Health >=5) { } else { Health += 1; }
}
public void Bounce()
{
Rigidbody2D.AddForce(Vector2.up * 300);
}
void Invencible()
{
timer = 1;
if (timer > 0)
{
invencible = true;
}
}
private IEnumerator FlashCo()
{
int temp = 0;
triggerCollider.enabled = false;
while (temp < numberOfFlashes)
{
mySprite.color = flashColor;
yield return new WaitForSeconds(flashDuration);
mySprite.color = regularColor;
yield return new WaitForSeconds(flashDuration);
temp++;
}
triggerCollider.enabled = true;
}
private void RestartLevel()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
Instead of using Destroy(Corazones[0].gameObject) you could use Corazones[0].gameObject.setActive(false) or simply Corazones[0].setActive(false) since the array already contains GameObjects.
This would preserve the GameObject while all of its components and children would be inactivated including its Renderer which would make it disappear.
Then later when you need it you could reactivate it using Corazones[0].setActive(true).

Why is this Coroutine for my Weapon Reloading not working?

I have this code for a Weapon with reloading, and if I start to reload, switch to a different weapon, and the switch back to the weapon that should be reloading, The weapon doesn't reload, can't shoot, and will Display the AmmoDisplay of the previous weapons... any idea why? I tried setting the IEnumerator to public, but that didn't work either.
using UnityEngine;
using System.Collections;
using TMPro;
public class GunScript_SB : MonoBehaviour
{
public float damage = 10f;
public float range = 100f;
public float impactForce = 30f;
public float fireRate = 15f;
public float maxAmmo = 10;
private float currentAmmo;
public float reloadTime = 3f;
private bool isReloading = false;
public Camera fpsCam;
public ParticleSystem muzzleFlash;
public GameObject impactEffect;
public TextMeshProUGUI ammunitionDisplay;
private float nextTimeToFire = 0;
void Start()
{
currentAmmo = maxAmmo;
}
void onEnable()
{
isReloading = false;
AmmoDisplay();
}
// Update is called once per frame
void Update()
{
if (isReloading)
return;
if (currentAmmo <= 0)
{
StartCoroutine(Reload());
return;
}
if (Input.GetButtonDown("Fire1") && Time.time >= nextTimeToFire)
{
nextTimeToFire = Time.time + 1f / fireRate;
Shoot();
}
if (ammunitionDisplay != null)
{
AmmoDisplay();
}
if (Input.GetKeyDown(KeyCode.R) && currentAmmo < maxAmmo)
{
StartCoroutine(Reload());
}
}
public IEnumerator Reload()
{
isReloading = true;
Debug.Log("Reloading...");
yield return new WaitForSeconds(reloadTime);
currentAmmo = maxAmmo;
isReloading = false;
}
void Shoot()
{
muzzleFlash.Play();
currentAmmo--;
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
{
Debug.Log(hit.transform.name);
Target target = hit.transform.GetComponent<Target>();
if (target != null)
{
target.TakeDamage(damage);
}
if (hit.rigidbody != null)
{
hit.rigidbody.AddForce(-hit.normal * impactForce);
}
GameObject impactGO = Instantiate(impactEffect, hit.point, Quaternion.LookRotation(hit.normal));
Destroy(impactGO, 1f);
}
}
void AmmoDisplay()
{
ammunitionDisplay.SetText(currentAmmo + " / " + maxAmmo);
}
}
Your coroutine could possibly still running after switching weapon. Add a referencing field and stop the coroutine before starting it again:
private Coroutine reloadCoroutine;
if (reloadCoroutine != null){
StopCoroutine(reloadCoroutine);
}
reloadCoroutine = StartCoroutine(Reload());

Jump/Throw Coding or Animation Issues

The Setup
I have a basketball player with an animator and 5 assigned animations to that animator as followed:
PlayerIdle
PlayerWalk
PlayerJump
PlayerBend
PlayerShoot
Setup_FruitHoops
Player Animation Window with Parameters
The Problem
In PlayMode, the player is able to move and jump successfully. The issue comes when the player attempts to grab the apple that is on the ground. The desired game design that I wanted was for the player to bend over and grab the apple by pressing the G key and then press G again to throw the apple towards the hoop to score a point. However, when I run it and after I first press G, the player can no longer jump, grab, or throw. The below section is the code for PlayerMovement and GrabberScript. Any advice is greatly appreciated.
PlayerMovement.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float speed = 5f;
private Rigidbody2D rb;
private Animator anim;
private bool isGrounded, jumped;
private float jumpshotPower = 6f;
public Transform groundCheck;
public LayerMask groundLayer;
private void Awake()
{
rb = GameObject.Find("Player Parent").GetComponent<Rigidbody2D>();
anim = GameObject.Find("Player Parent").GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
CheckIfGrounded();
PlayerJump();
}
private void FixedUpdate()
{
PlayerWalk();
}
void PlayerWalk()
{
float h = Input.GetAxisRaw("Horizontal");
if (h > 0)
{
//going right
anim.SetBool("isWalking", true);
rb.velocity = new Vector2(speed, rb.velocity.y);
ChangeDirection(-1);
}
else if (h < 0)
{
//going left
anim.SetBool("isWalking", true);
rb.velocity = new Vector2(-speed, rb.velocity.y);
ChangeDirection(1);
}
else
{
//standing still
anim.SetBool("isWalking", false);
rb.velocity = new Vector2(0f, rb.velocity.y);
}
}
void ChangeDirection(int d)
{
Vector3 temp = transform.localScale;
temp.x = d;
transform.localScale = temp;
}
void CheckIfGrounded()
{
isGrounded = Physics2D.Raycast(groundCheck.position, Vector2.down, 0.1f, groundLayer);
if (isGrounded)
{
if (jumped)
{
jumped = false;
anim.SetBool("isJumping", false);
}
}
}
void PlayerJump()
{
if (isGrounded)
{
if (Input.GetKey(KeyCode.UpArrow))
{
jumped = true;
rb.velocity = new Vector2(rb.velocity.x, jumpshotPower);
anim.SetBool("isJumping", true);
}
}
}
}
GrabberScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GrabberScript : MonoBehaviour
{
private bool grabbed, throwObject;
private RaycastHit2D hit;
public float distance;
public Transform holdpoint;
public float throwForce;
public LayerMask notFruitLayer;
private Animator anim;
private void Awake()
{
anim = GameObject.Find("Player Parent").GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.G))
{
if (!grabbed)
{
//grab fruit
anim.Play("PlayerBend");
Physics2D.queriesStartInColliders = false;
hit = Physics2D.Raycast(transform.position, Vector3.down * transform.localScale.x, distance);
if(hit.collider != null && hit.collider.tag == "Apple")
{
grabbed = true;
}
}
else if(!Physics2D.OverlapPoint(holdpoint.position, notFruitLayer))
{
//throw fruit
grabbed = false;
if(hit.collider.gameObject.GetComponent<Rigidbody2D>() != null)
{
PlayerShooting();
}
}
if (grabbed)
{
hit.collider.gameObject.transform.position = holdpoint.position;
}
}
}
private void OnDrawGizmos()
{
Gizmos.color = Color.green;
Gizmos.DrawLine(transform.position, transform.position + Vector3.down * transform.localScale.x * distance);
}
void PlayerShooting()
{
if (grabbed == true)
{
if (Input.GetKey(KeyCode.G))
{
throwObject = true;
hit.collider.gameObject.GetComponent<Rigidbody2D>().velocity = new Vector2(transform.localScale.x, 1) * throwForce;
anim.Play("PlayerShoot");
}
}
}
}

transform does not exits in current context

I am finding it hard to figure out why my transform is wrong. Can anyone help me on this problem. I am trying to make a FSM for my enemy so it either goes for the player or go for food. But when I try to test it I get a compiler error.
using UnityEngine;
using System.Collections;
public class Enemy : MovingObject
{
public int playerDamage;
private Animator animator;
private Transform target;
private bool skipMove;
private Transform Player;
public AudioClip enemyAttack1;
public AudioClip enemyAttack2;
protected override void Start ()
{
GameManager.instance.AddEnemeyToList(this);
animator = GetComponent<Animator> ();
target = GameObject.FindGameObjectWithTag ("Food").transform;
base.Start ();
AIEnemy();
Player = GameObject.FindWithTag("Player").transform;
}
protected override void AttemptMove<T> (int xDir, int yDir)
{
if (skipMove)
{
skipMove = false;
return;
}
base.AttemptMove <T> (xDir, yDir);
skipMove = true;
}
public void MoveEnemy()
{
int xDir = 0;
int yDir = 0;
if (Mathf.Abs (target.position.x - transform.position.x) < float.Epsilon)
yDir = target.position.y > transform.position.y ? 1 : -1;
else
xDir = target.position.x > transform.position.x ? 1 : -1;
AttemptMove<Player> (xDir, yDir);
}
protected override void OnCantMove <T> (T component)
{
Player hitPlayer = component as Player;
hitPlayer.LoseFood (playerDamage);
animator.SetTrigger("enemyAttack");
SoundManager.instance.RandomizeSfx (enemyAttack1, enemyAttack2);
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Food")
{
other.gameObject.SetActive(false);
}
else if (other.tag == "Soda")
{
other.gameObject.SetActive(false);
}
}
void AIEnemy()
{
int State = 0;
if (State == 0)
{
transform.LookAt(Player);
State++;
}
if (State == 1)
transform.LookAt(target);
Debug.Log("State 1");
State++;
if (State == 2)
{
Debug.Log("State 2");
}
}
}
public Transform FindClosetFood()
{
float minDistance = float.PositiveInfinity;
Transform closetFood = null;
GameObject[] foods = GameObject.FindGameObjectsWithTag("Food");
for(int i = 0; i<foods.Length; i++)
{
float distance = Vector2.Distance(transform.position, foods[i].transform.position);
if (distance < minDistance)
{
minDistance = distance;
closetFood = foods[i].transform;
}
}
return closetFood;
}
}
I added a private Transform Player. So my enemy knows what to look at but I still dont get anything in console. And I tried calling it in start. But now I ended up with this compiler error.
The error comes in this line
float distance = Vector2.Distance("transform".position, foods[i].transform.position);
MovingObject script:
using UnityEngine;
using System.Collections;
public abstract class MovingObject : MonoBehaviour
{
public float moveTime = 0.1f;
public LayerMask blockingLayer;
private BoxCollider2D boxCollider;
private Rigidbody2D rb2D;
private float inverseMoveTime;
// Use this for initialization
protected virtual void Start ()
{
boxCollider = GetComponent<BoxCollider2D> ();
rb2D = GetComponent<Rigidbody2D> ();
inverseMoveTime = 1f / moveTime;
}
protected bool Move (int xDir, int yDir, out RaycastHit2D hit)
{
Vector2 start = transform.position;
Vector2 end = start + new Vector2 (xDir, yDir);
boxCollider.enabled = false;
hit = Physics2D.Linecast (start, end, blockingLayer);
boxCollider.enabled = true;
if (hit.transform == null)
{
StartCoroutine(SmoothMovement (end));
return true;
}
return false;
}
protected IEnumerator SmoothMovement (Vector3 end)
{
float sqrRemainingDistance = (transform.position - end).sqrMagnitude;
while (sqrRemainingDistance > float.Epsilon)
{
Vector3 newPosition = Vector3.MoveTowards (rb2D.position, end, inverseMoveTime * Time.deltaTime);
rb2D.MovePosition(newPosition);
sqrRemainingDistance = (transform.position - end).sqrMagnitude;
yield return null;
}
}
protected virtual void AttemptMove <T> (int xDir, int yDir) where T : Component
{
RaycastHit2D hit;
bool canMove = Move (xDir, yDir, out hit);
if (hit.transform == null)
return;
T hitComponent = hit.transform.GetComponent<T> ();
if(!canMove && hitComponent != null)
OnCantMove (hitComponent);
}
protected abstract void OnCantMove <T> (T component) where T : Component;
}
It can't find transform.position because transform is a variable undeclared under Component. MonoBehaviour drives from Behaviour and Behaviour derives from Component. To get access to the transform variable, your script must derive from one of these. Although MonoBehaviour is what the script should derive from.
In code, your Enemy script already derive from MovingObject script which derives from MonoBehaviour so that should give you access to the transform variable but there is a problem. There is an extra } at the end of the AIEnemy() function in your Enemy script. That extra } at the end of the AIEnemy() function closes or marks the end of the Enemy script therefore making the transform variable unavailable to you. Remove the extra } at the end of the AIEnemy() function and your problem should be fixed.
If you can't find it, use the new Enemy script below:
public class Enemy : MovingObject
{
public int playerDamage;
private Animator animator;
private Transform target;
private bool skipMove;
private Transform Player;
public AudioClip enemyAttack1;
public AudioClip enemyAttack2;
protected override void Start()
{
GameManager.instance.AddEnemeyToList(this);
animator = GetComponent<Animator>();
target = GameObject.FindGameObjectWithTag("Food").transform;
base.Start();
AIEnemy();
Player = GameObject.FindWithTag("Player").transform;
}
protected override void AttemptMove<T>(int xDir, int yDir)
{
if (skipMove)
{
skipMove = false;
return;
}
base.AttemptMove<T>(xDir, yDir);
skipMove = true;
}
public void MoveEnemy()
{
int xDir = 0;
int yDir = 0;
if (Mathf.Abs(target.position.x - transform.position.x) < float.Epsilon)
yDir = target.position.y > transform.position.y ? 1 : -1;
else
xDir = target.position.x > transform.position.x ? 1 : -1;
AttemptMove<Player>(xDir, yDir);
}
protected override void OnCantMove<T>(T component)
{
Player hitPlayer = component as Player;
hitPlayer.LoseFood(playerDamage);
animator.SetTrigger("enemyAttack");
SoundManager.instance.RandomizeSfx(enemyAttack1, enemyAttack2);
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Food")
{
other.gameObject.SetActive(false);
}
else if (other.tag == "Soda")
{
other.gameObject.SetActive(false);
}
}
void AIEnemy()
{
int State = 0;
if (State == 0)
{
transform.LookAt(Player);
State++;
}
if (State == 1)
transform.LookAt(target);
Debug.Log("State 1");
State++;
if (State == 2)
{
Debug.Log("State 2");
}
}
public Transform FindClosetFood()
{
float minDistance = float.PositiveInfinity;
Transform closetFood = null;
GameObject[] foods = GameObject.FindGameObjectsWithTag("Food");
for (int i = 0; i < foods.Length; i++)
{
float distance = Vector2.Distance(transform.position, foods[i].transform.position);
if (distance < minDistance)
{
minDistance = distance;
closetFood = foods[i].transform;
}
}
return closetFood;
}
}

Categories

Resources