0
\$\begingroup\$

I have this object called Treant and I instantiated him from another Object called spawn. The spawn only instantiates a new Treant every second or not.

My problem is that the Treant has a Health bar but that same health bar isn't instantiated in the other Treant that I clone. The health bar will only appear in the next Treant the is created after I destroy the one that has the Health bar.

How can I made all Treants have the Health Bar on top of them?

This is my Spawn class:

 // Start is called before the first frame update
public Component Enemies;
public Component Target;
private float lastSpawn = 5;
private float waited = 0f;
private int spawnPerWave = 1;
private int spawned = 0;
private List<int> fibonacci = new List<int>
{
    1, 1
};


// Update is called once per frame
void Update()
{
    CreateNewWave();
    Spawn();    
}

private void Spawn()
{
    waited += Time.deltaTime;

    if (lastSpawn < waited && spawned < spawnPerWave)
    {
        Debug.Log("Spawned");
        waited = 0;
        spawned += 1;
        var enemy = Instantiate(Enemies);
        enemy.GetComponent<EnemyAI>().target = Target;
    }
}

private void CreateNewWave()
{
    if(spawned == spawnPerWave && fibonacci.Count < 4)
    {
        spawned = 0;
        spawnPerWave = fibonacci[fibonacci.Count - 1] + fibonacci[fibonacci.Count - 2];
        fibonacci.Add(spawnPerWave);
    }
}

Objects following around my player object, but one of them does not have a health bar instantiated

The Canvas config:

Canvas configuration

The Slider config:

enter image description here

The code from FollowTransform:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FollowTransform : MonoBehaviour
{
    public Transform m_objectToFollow;
    private RectTransform m_rect;

    void Start()
    {
        m_rect = GetComponent<RectTransform>();
    }

    void Update()
    {
        this.m_rect.anchoredPosition = CanvasManager.Instance.WorldToCanvasPoint(m_objectToFollow.position);
    }
}

Canvas Manager Script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CanvasManager : MonoBehaviour
{
    private Rect m_canvasRect;
    // Start is called before the first frame update
    private static CanvasManager canvasManager;
    public static CanvasManager Instance
    {
        get
        {
            return canvasManager;
        }
    }

    void Start()
    {
        if(canvasManager != null && canvasManager != this)
        {
            Destroy(this.gameObject);
        }
        else
        {
            canvasManager = this;
        }

        m_canvasRect = GetComponentInParent<Canvas>().GetComponent<RectTransform>().rect;
    }

    public Vector2 WorldToCanvasPoint(Vector3 a_position)
    {

        Vector2 viewport = Camera.main.WorldToViewportPoint(a_position);
        return Vector2.right * (viewport.x - 0.5f) * m_canvasRect.width + Vector2.up * (viewport.y - 0.5f) * m_canvasRect.height;
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Can you show us how you've configured the canvas inside the treant, and any positioning scripts you might be using? \$\endgroup\$ – DMGregory Feb 13 at 2:34
  • \$\begingroup\$ @DMGregory just added to the question the configs from Canvas, Slider and the script that I'm using to set the position to the Slider. Thanks \$\endgroup\$ – Rafael Ahrons Feb 14 at 1:51
1
\$\begingroup\$

Check that the Treant prefab has the canvas on it and that the values on it are correct.

If it's not the prefab then maybe Canvas has a singleton script on it that destroys any new instances of itself.

You can then do a sanity check. Get and print all the components on the Treant before instantiating (in Start()) and then after. You can do it like this

foreach(var component in Enemies.GetComponents<Component>())
{
    Debug.Log(component.name)
}

Also maybe instead of

 public Component Enemies;

use

public GameObject Enemies;

That's not the problem, but when given a GameObject Component references the first component it finds on it i.e. Transform. So when you're doing enemy.GetComponent<EnemyAI>() it translates to enemy.gameObject.GetComponent<EnemyAI>() so it's pointless to use Component instead of GameObject

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thank you for the help, but It didn't solved =/. Just updated the question to have more info. The GameObject tip was new for me. Thanks \$\endgroup\$ – Rafael Ahrons Feb 14 at 2:26
1
\$\begingroup\$

The problem was with the Canvas Manager Script. It has a Singleton to the canvas, so the canvas isn't been instantiated every time that a Treant is created.

To solve this, just remove the singleton. I got some help from Sid Makes Game

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CanvasManager : MonoBehaviour
{
    private Rect m_canvasRect;
    public static CanvasManager Instance { get; private set; }

    void Start()
    {
        Instance = this;        
        m_canvasRect = GetComponentInParent<Canvas>().GetComponent<RectTransform>().rect;
    }

    public Vector2 WorldToCanvasPoint(Vector3 a_position)
    {

        Vector2 viewport = Camera.main.WorldToViewportPoint(a_position);
        return Vector2.right * (viewport.x - 0.5f) * m_canvasRect.width + Vector2.up * (viewport.y - 0.5f) * m_canvasRect.height;
    }
}
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.