N
N
NickName73312018-02-09 21:34:03
C++ / C#
NickName7331, 2018-02-09 21:34:03

Unity3D(C#) - Why is character's health not recovering?

I was making a "system" of character's health, and came across a problem: when a character tries to restore the last "heart" - it is not restored (although the first 4 are restored). Here is the character code:

spoiler
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
using UnityEngine.SceneManagement;
using System;

public class Character : Unit
{
  [SerializeField]
  private float speed = 3.0F;
  [SerializeField]
  private int lives = 5;
  [SerializeField]
  private int fallController = -10;

  private int coins = 0;

  public int Lives
  {
    get { return lives; }
    set 
    {
      if (value < 5) lives = value;
      livesBar.Refresh ();
    }
  }

  public int Coins
  {
    get { return coins; }
  }

  private LivesBar livesBar;


  [SerializeField]
  private float jumpForce = 15.0F;

  private bool isGrounded = false;

  private Bullet bullet;

  private CharState State
  {
    get { return (CharState)animator.GetInteger ("State"); }
    set { animator.SetInteger("State", (int)  value); }
  }


  new private Rigidbody2D rigidbody;
  private Animator animator;
  private SpriteRenderer sprite;

  private void Awake()
  {
    livesBar = FindObjectOfType<LivesBar> ();
    rigidbody = GetComponent<Rigidbody2D> ();
    animator = GetComponent<Animator> ();
    sprite = GetComponentInChildren<SpriteRenderer> ();

    bullet = Resources.Load<Bullet> ("Bullet");
  }

  private void FixedUpdate()
  {
    CheckGround ();
  }

  private void Update()
  {
    if (isGrounded) State = CharState.Idle;

    if (Input.GetButtonDown ("Fire1")) Shoot ();
    if (Input.GetButton ("Horizontal")) Run ();
    if (isGrounded && Input.GetButtonDown ("Jump")) Jump ();
    if (gameObject.transform.position.y < fallController)
    {
      Debug.Log("Player Dead");
      SceneManager.LoadScene (SceneManager.GetActiveScene ().name);
    }
  }

  private void Run()
  {
    Vector3 direction = transform.right * Input.GetAxis ("Horizontal");

    transform.position = Vector3.MoveTowards (transform.position, transform.position + direction, speed * Time.deltaTime);

    sprite.flipX = direction.x < 0.0F;

    if (isGrounded) State = CharState.Run;
  }

  private void Jump()
  {
    
    rigidbody.AddForce (transform.up * jumpForce, ForceMode2D.Impulse);


  }

  private void Shoot()
  {
    Vector3 position = transform.position;   position.y += 0.8F;
    Bullet newBullet = Instantiate (bullet, position, bullet.transform.rotation) as Bullet;

    newBullet.Parent = gameObject;
    newBullet.Direction = newBullet.transform.right * (sprite.flipX ? -1.0F : 1.0F);
  }

  public override void ReceiveDamage()
  {
    
    Lives--;
    if (lives == 0)
    {
      ReloadScene();
    }
    rigidbody.velocity = Vector3.zero;
    rigidbody.AddForce(transform.up * 12.0F, ForceMode2D.Impulse);
  }

    private void CheckGround()
  {
    Collider2D[] colliders = Physics2D.OverlapCircleAll (transform.position, 0.3F);

      isGrounded = colliders.Length > 1;

    if (!isGrounded) State = CharState.Jump;
  }

  private void OnTriggerEnter2D(Collider2D collider)
  {
    Bullet bullet = collider.gameObject.GetComponent<Bullet> ();
    if (bullet && bullet.Parent != gameObject) 
    {
      ReceiveDamage ();
    }
  }
  private void ReloadScene()
  {
    Thread.Sleep (500);
    SceneManager.LoadScene (SceneManager.GetActiveScene ().name);
  }
}

public enum CharState
{
  Idle,
  Run,
  Jump
}


Here is the recharge code for "hearts":
spoiler
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Heart : MonoBehaviour 
{
  private void OnTriggerEnter2D(Collider2D collider)
  {
    Character character = collider.GetComponent<Character> ();

    if (character) 
    {
      character.Lives++;
      Destroy (gameObject);
    }
  }
}


Here is the code for "display character hearts":
spoiler
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LivesBar : MonoBehaviour 
{
  private Transform[] hearts = new Transform[5];

  private Character character;

  private void Awake()
  {
    character = FindObjectOfType<Character> ();

    for (int i = 0; i < hearts.Length; i++)
    {
      hearts[i] = transform.GetChild(i);
    }
  }

  public void Refresh()
  {
    for (int i = 0; i < hearts.Length; i++)
    {
      if (i < character.Lives)
        hearts [i].gameObject.SetActive (true);
      else
        hearts [i].gameObject.SetActive (false);
    }
  }
}


Happy in advance for help.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
D
Denis Gaydak, 2018-02-09
@NickName7331

judging by the code, you should have five lives and five hearts (and by the way, I would advise you to enter one variable under the NUMBER OF LIVES and use it everywhere. otherwise
I can only suggest you turn on debugging and see what happens at the time the hearts are replenished,
but if you don’t want to do it yourself look for something like this spoiler-tip
if (i < character.Lives) - and from what to what value does your life change? I see from 0 to 4.
that is, you have full 5 lives when Lives == 4
and when checking, it will be included only for i equal to 0,1,2,3 - that is,
you or life count from 1 to 5. and change the condition in the Lives property. or pass through the array with a different condition))

N
NonameProgrammer, 2018-02-09
@NonameProgrammer

It seems to me (not special in unity) that this is due to the fact that you always create a new object
>Here is the code for replenishing "hearts":
spoiler
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Heart : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D collider)
{
Character character = collider.GetComponent ();
if (character)
{
character.Lives++;
Destroy(gameObject);
}
}
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question