- Home /
Send message to instantiated clone has funny results
There is a prefab with a script attached to it, prefab A. Then prefab A instantiates a clone of itself, prefab B, and sends a message to call a method. The message is sent and received, but the results are not as expected.
Code and results
using UnityEngine;
using System.Collections;
public class TestOfPrefabNonsense : MonoBehaviour {
public int basePairs;
public GameObject prefab;
void Start () {
basePairs = 0;
}
void OnMouseDown(){
MakePrefabB(); // I am using a button for this
}
public void MakePrefabB(){
Debug.Log(basePairs); //10 basePairs gets added to by editor to test this
int half = basePairs/2;
Debug.Log(half); // 5
GameObject prefabB = Instantiate (prefab);
prefabB.SendMessage("TakeHalf", half);
basePairs -= half;
}
void TakeHalf(int half){
Debug.Log(half); // 5
basePairs += half;
Debug.Log(basePairs); // 15
}
}
Actual Values (From the Inspector) after creating prefabB
prefabA basePairs = 5
prefabB basePairs = 0
Can anyone explain why this is?
A GameObject. In one of the examples I used to reproduce this error I used a cube with the script attached to it. In the game it is a sprite. It just has to be able to replicate itself.
I was referring to where you have "prefabA" in in your "Actual Values" list.
@Bioinformatizer:
You use the term prefab in the wrong way. A prefab is a pre made object that is not part of the scene but is an object in the project itself. When you instantiate a prefab it becomes an ordinary GameObject in the scene. You could say a prefab-instance but at runtime something like that doesn't even exist.
You actually only have one prefab and two instances A and B. Those aren't prefabs.
Answer by Bunny83 · Jun 10, 2015 at 02:08 PM
Like @Gnemlock said in his answer you run TakeHalf before Start runs. You might want to use Awake instead. Awake is called before the Instantiate call returns. So Awake is the best place for setting up initial values as it acts like a constructor. Start is only ensured to run before the first Update call on that object. That's why Start is usually scheduled at the beginning of the frame.
Besides that you have a setup that might cause other problems as well. A prefab can not contain a reference to it's own prefab. Self-references are replaced with the instance reference when the object is instantiated. That means the "prefab" field of the objectA instance will point to itself and not to the prefab it was made of. See those question for reference:
http://answers.unity3d.com/questions/577888/how-to-instantiate-from-prefab-not-from-instance.html
http://answers.unity3d.com/questions/45079/instantiated-objects-scripts-not-enabled-not-sure.html
In case it doesn't matter if you simply clone the current object or the prefab this might not be a problem for your. Just be sure you understand what object actually got cloned.
It works with the Awake function just fine. Not knowing that Start would get called the frame after was the issue.
On another note there is definetly ways to reference the same class, as I am doing it in a script for a game In working on and they work fine. In my case the references are static, but I imagine if that's what makes it work you would be able to apply the same thing to yours.
Answer by Gnemlock · Jun 10, 2015 at 07:21 AM
From the inspector, you are setting the value. However, as soon as you hit run, your scripts run their Start function, where you tell it to set basePair to 0. 0/2 is also 0, so when you add it to basePair.. yep.. 0.
This is not true as the inspector value is set after the game is running and paused.
I don't see how that's relevant, the Send$$anonymous$$essage call is made as soon as the "prefabB" instance is created.
@Bioinformatizer: Gnemlock is right. Start is called the next frame after the object got created. Since you call TakeHalf (via Send$$anonymous$$essage) immediately when you instantiate your object, TakeHalf is invoked before Start is run. However you might have more problems besides that ^^
Answer by DiebeImDunkeln · Jun 10, 2015 at 01:24 PM
make TakeHalf public and try:
prefabB.GetComponent<TestOfPrefabNonsense>().TakeHalf(half);
instead of:
prefabB.SendMessage("TakeHalf", half);
I think that will work.
Your answer
Follow this Question
Related Questions
Cast a variable over intentiated gameObjects 0 Answers
New instances of object are colliding when collider is turned off. 2 Answers
Problems with cloning, aka double trouble. 0 Answers
Checking if object intersects? 1 Answer
Functions work in the Editor, don't work when Built. (Javascript) 0 Answers