No collision happening on instantiated GameObject but original prefab works fine

I have to admit defeat with this one because it’s very odd the behaviour and I can’t quite pin down what is happening since there are no errors and Debug.Log isn’t showing anything strange either. All of the code works fine with a standard prefab however since I have tried to instantiate it real time despite my boolean setting to true everything suddenly decides to break.

The concept is pretty straight forward, I have a button I click to instantiate a new base which makes my playaer invulnerable when they enter it and there is a timer that counts down to track how long that lasts. However despite the boolean activating I cannot kill the enemies that I have also spawned in despite the boolean being set to true. What’s so strange is that this only specifically happens with instantiated prefab and not the prefab that I have in the scene, by the way, the instantiated prefab is an absolute copy of the one in the scene which is why I’m so confused as to why Unity is behaving this way.

I hope the explanation of what’s going on makes sense, I’ll give you the relevant bits of code, I have no idea why there’s one piece of code activating fine and not the other, I haven’t run into problems until now.

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

public class CreateBase : MonoBehaviour {

    public GameObject lightBase;
    private LightBaseChangeScale lightBaseChangeScaleScript;

    void Start ()

    {
        lightBaseChangeScaleScript = GameObject.FindWithTag ("LightBase").GetComponent<LightBaseChangeScale>();
    }

    public void InstantiateLightBase ()

    {
        if ( lightBaseChangeScaleScript.BasePoints > 0 )

        {
        Instantiate ( lightBase, transform.position, Quaternion.identity );
        lightBaseChangeScaleScript.BasePoints -= 1;
        lightBaseChangeScaleScript.SetBasePointsText ();
        }
    }

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

public class LightBaseChangeColourScale : MonoBehaviour {

    public GameObject LightBaseObject;
    private LightBaseChangeColourScale changeColourScaleScript;
    private LightBaseChangeScale changeScaleScript;

    void Start ()

    {
        changeColourScaleScript = gameObject.GetComponent<LightBaseChangeColourScale>();
        changeScaleScript = gameObject.GetComponent<LightBaseChangeScale>();
        changeScaleScript.SetLightPointsText();
        changeScaleScript.SetBasePointsText();
    }


    void OnTriggerEnter (Collider other)

    {
        if ( !changeColourScaleScript.enabled ) return;

            if ( other.gameObject.tag == "Player" )

            {

                if ( changeScaleScript.LightPoints > 0 )
              
                {

                ParticleSystem playerParticles = GameObject.Find("PlayerParticle").GetComponent<ParticleSystem>();
                Light baseLight = gameObject.GetComponentInChildren<Light>();
                Light playerLight = GameObject.Find("PlayerEmpty").GetComponentInChildren<Light>();
                changeScaleScript.LightPoints -= 1;
                changeScaleScript.SetLightPointsText ();
                Color randomColor = new Color ( Random.value, Random.value, Random.value, 0.5f );
                LightBaseObject.transform.localScale += new Vector3 ( 0.5f, 0.5f, 0 );
                var main = playerParticles.main;
                main.startColor = randomColor;
                baseLight.color = randomColor;
                playerLight.color = randomColor;
                changeColourScaleScript.enabled = false;
                changeScaleScript.enabled = true;
                Debug.Log ("Base activated");

               }

            }
    }

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class LightBaseChangeScale : MonoBehaviour {

    public int LightPoints;
    public int BasePoints;

    void Start ()

    {

        LightPoints = 1;
        SetLightPointsText ();

    }
      
    void OnTriggerEnter (Collider other)

    {

        if ( other.gameObject.tag == "Player" )

        {

            if ( LightPoints > 0 )

            {
                Light baseLight = gameObject.GetComponentInChildren<Light>();
                gameObject.transform.localScale += new Vector3 ( 0.5f, 0.5f, 0 );
                baseLight.intensity += 1;
                LightPoints -= 1;
                SetLightPointsText ();
                SetBasePointsText();
                Debug.Log("Base Expanded");
            }
      
        }

    }

    public void SetLightPointsText ()

    {
        Text lightPointsText = GameObject.Find("LightPointsText").GetComponent<Text>();
        lightPointsText.text = LightPoints.ToString ();
    }

    public void SetBasePointsText ()

    {
        Text basePointsText = GameObject.Find("BasePointsText").GetComponent<Text>();
        basePointsText.text = BasePoints.ToString ();
    }




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

public class CanEnemyBeHarmedByPlayer : MonoBehaviour {

    InvulnerabilityScript invulnerabilityScript;
    LightBaseChangeScale lightBaseChangeScale;

    void Start ()

    {
        GameObject LightBaseGameobjectBoolCheck = GameObject.FindGameObjectWithTag ("LightBase");
        invulnerabilityScript = LightBaseGameobjectBoolCheck.GetComponent<InvulnerabilityScript>();
        lightBaseChangeScale = LightBaseGameobjectBoolCheck.GetComponent<LightBaseChangeScale>();
    }

    void OnTriggerEnter ( Collider other )

    {
        if ( other.gameObject.tag == "Player" )

        {

        if ( invulnerabilityScript.PlayerEnteredBase == true )

        {
            lightBaseChangeScale.LightPoints += 1;
            lightBaseChangeScale.BasePoints += 1;
            lightBaseChangeScale.SetLightPointsText();
            lightBaseChangeScale.SetBasePointsText();
            Destroy ( gameObject );
            Debug.Log ( "Monster killed" );
        }

        }
    }




}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class InvulnerabilityScript : MonoBehaviour
{

    public bool PlayerEnteredBase = false;
    public float invulnerabilityCountDown = 10f;

    private float currentTimeLeft;
    private Coroutine activeTimerCoroutine;

    private void Update()

    {
        if (currentTimeLeft > 0)

        {
            PlayerEnteredBase = true;
        }

        else

        {
            PlayerEnteredBase = false;
        }
    }

    private void UpdateText()

    {
        float time = Mathf.Max(currentTimeLeft, 0);
        Text invulnerabilityCountDownText = GameObject.Find("InvincibilityCountDownText").GetComponent<Text>();
        invulnerabilityCountDownText.text = " " + time.ToString("F0");
    }

    private void OnTriggerStay(Collider other)

    {
        if (other.gameObject.tag == ("Player"))

        {
            StopTimer();
            ResetTimer();
        }
    }

    private void OnTriggerExit(Collider other)

    {
        if (other.gameObject.tag == ("Player"))

        {
            StartTimer();
        }
    }


    private void ResetTimer()

    {
        currentTimeLeft = invulnerabilityCountDown;
        UpdateText();
    }

    private void StartTimer()

    {
        StopTimer();
        activeTimerCoroutine = StartCoroutine(CountDownTimerCoroutine());
    }

    private void StopTimer()

    {
        if (activeTimerCoroutine != null)

        {
            StopCoroutine(activeTimerCoroutine);
        }
    }

    private IEnumerator CountDownTimerCoroutine()

    {
        while (currentTimeLeft > 0.0f)

        {
            currentTimeLeft -= Time.deltaTime;
            UpdateText();
            yield return null;
        }
    }




}

As you can probably tell I’ve been really racking my brain over this, I double checked the usual stuff like whether or not the collider was positioning oddly because of the way I made the prefab and everything is in the right place so I know it’s nothing to do with that. I also double checked things like the rigidbodies to make sure I hadn’t been daft and forgotten anything obvious.

Again, just to stress, I have only ever had problems with the Instantiated copy of the prefab, not the prefab itself that is in the scene. The boolean sets to true as you’d expect but I can’t kill off any of the enemies that spawn in unless I trigger the original prefab I have in the scene already.

This is a ton of code to read through to try to find the error(s), but is it possibly related to the first script’s Instantiate? You don’t assign the value from Instantiate to anything and your lightBaseChangeScaleScript refers to the object on the original, not the copy?

Of course it’s that bloody simple! So in order to fix this I would have to make sure like with all the other code I’ve done that I am getting the lightBaseChangeScale script on the child/gameobject that has been instantiated rather than the original prefab?

Thanks @GroZZleR , I’ll give this a shot and see what happens, I think you’re right about it, I had been going through my code fixing things so that all the values and scripts didn’t rely on public variables so perhaps I just went and missed one particular script.

1 Like

Yes, grab updated component references after instantiation.

Right, I’m getting everything fixed now which is great, what I’m doing is moving stuff like the boolean over to separate empties so that nothing duplicates or causes any weirdness within Unity and that has completely fixed the problems. I just wanted to clear up the detail of why this is, when you have a gameObject with a script instantiate during runtime if there is a duplicate script does Unity simple default to the first script in existence?

If this is the case then that would explain more why I’ve been having problems and why my existing prefab works and my instantiated prefab doesn’t despite them being two exact copies of each other.

It’s a little hard to follow your code, since there’s a lot of it and I don’t know what script is on what GameObject and whatnot, but basically:

lightBaseChangeScaleScript = GameObject.FindWithTag ("LightBase").GetComponent<LightBaseChangeScale>();

You’re grabbing a reference to a component from the first GameObject that FindWithTag returns, and you’re doing that inside Start(), rather than grabbing the component from the prefab clone you create inside your InstantiateLightBase() function like this:

public void InstantiateLightBase()
{
   if ( lightBaseChangeScaleScript.BasePoints > 0 )
        {
           LightBase clone = Instantiate ( lightBase, transform.position, Quaternion.identity );
           lightBaseChangeScaleScript = clone.GetComponent<LightBase>(); // get it from the clone
           lightBaseChangeScaleScript.BasePoints -= 1;
           lightBaseChangeScaleScript.SetBasePointsText ();
   }
}

I imagine it would work? But again, it’s hard to tell exactly how your entire project is structured and what is attached to what.

One important quirk of Unity to remember though, is that linking a prefab object in the inspector loads that object as is and you can do things like:

public GameObject prefab; // linked in the inspector

void Start()
{
    prefab.transform.position = Random.onUnitSphere; // this is perfectly valid despite making little to no sense
}

It’s always important to remember what is a prefab and what is an instance.

1 Like

That’s exactly what I’ve been doing to fix everything lol so it looks like I’m on the right track if we’re both thinking the same thing. The main issues were being caused by me not seperating scripts, particularly the boolean and the global variables from the instantiated clones and that was causing a lot of problems because everything was just duplicating itself without a purpose.

1 Like

So I’m poking around and researching how to get and use the clones of instantiated GameObjects and I’m getting some errors, would someone mind telling me where I’m going wrong here?

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

public class CreateBase : MonoBehaviour {

    private LightBaseChangeScale lightBaseChangeScaleScript;
    PointsManagerScript pointsManagerScript;
    public GameObject lightBase;

    void Start ()

    {
    //    lightBaseChangeScaleScript = GameObject.FindWithTag ("LightBase").GetComponent<LightBaseChangeScale>();
        pointsManagerScript = GameObject.Find("PointsManager").GetComponent<PointsManagerScript>();


    }

    public void InstantiateLightBase ()

    {
        if ( pointsManagerScript.BasePoints > 0 )

        {
        LightBase clone = Instantiate(lightBase, transform.position, Quaternion.identity);
        lightBaseChangeScaleScript = clone.GetComponent<LightBase>();
        pointsManagerScript.BasePoints -= 1;
        lightBaseChangeScaleScript.SetBasePointsText ();
        }
    }

}

I’m bumping this topic because it’s all about the same code, here are the errors in the log.

From what I know of the errors usually the assembly reference means I just need to declare something do I need a using somethingorother; at the top for clone to work? I haven’t seen documentation or anything yet saying so.

Do you have a script called LightBase? There’s none in any of your examples. Are you sure you don’t want:

GameObject clone = Instantiate(lightBase, transform.position, Quaternion.identity);

instead? Your lightBase object is declared as a GameObject, so when you call Instantiate(), that’s what you’ll get back.

I would like to inform you about this as it may help someone. Your object might not collide because you might use a .fbx instead of a prefab. In my case, this was the issue.