- Home /
Script uses transform.position of Prefab instead of Instance
The script is attached to a prefab ("build space").
I instantiate a number of them at different positions (from a different Script). That works as intended, I get all the instances where I want.
Clicking on one of the Instances opens a UI Menu:
private void OnMouseDown() {
if (!EventSystem.current.IsPointerOverGameObject()) {
Instantiate(buildMenuCanvas, transform.position, transform.rotation);
Debug.Log("BuildSpace at Position " + transform.position);
}
}
This works as intended, and the transform.position
is also what I expect (i.e. of the instance that was clicked).
Clicking a button on the UI calls the Build
function, which should do 3 things:
- close the UI (works)
- Destroy the "build space" Instance that was clicked on
- Instantiate a "building" at the position of the "build space"
public void Build() {
Instantiate(building, transform.position, transform.rotation);
Debug.Log("Instantiated Building at " + transform.position);
Destroy(GameObject.FindGameObjectWithTag("UIPopup"));
Destroy(this.gameObject);
}
The "buildings" get instantiated, but not at the position of the "build space" that was clicked, but at the position of the "build space" Prefab. Also, the "build space" Instance is not destroyed.
It seems the Build
function runs on the prefab instead of the instance. (I also get a 'destroying assets is not permitted' error). As I said above, in OnMouseDown
, the position is correct. Could it be that it is because the referenced Object for the Buttons OnClick
is the Prefab?
How can I make sure that the Build
function is called on the Instance that was clicked on?
Answer by gewl · Nov 21, 2018 at 04:23 PM
You got it! This is because the referenced Object for the Button's OnClick is the prefab.
In order for the Button to dynamically call the Build method on the correct "build space" prefab, you need to dynamically assign the OnClick listener at runtime. The precise way to do this is going to differ a bit depending on how you've implemented things. Also, unrelatedly, I really recommend having one "buildMenuCanvas" that you turn on/off and move around the screen instead of creating/deleting a new one every time you open the menu—creation/deletion is expensive!
So the gist is going to be:
- Give your UI menu controller a public
ActivateBuildMenu
method, that takes in the BuildSpace script. In thisActivateBuildMenu
method:turn the build menu's gameObject on,
change its position based on the screenspace of the build space instance, and
assign an onClick listener to the Button that calls the Build method on the passed BuildSpace script (this will tell you how to assign listeners at runtime). Also, have this listener turn the UI menu controller off, so that your BuildSpace doesn't need to be responsible for the state of UI elements!
In your UI menu controller's OnDisable, have it clear the button of all listeners.
Change your BuildSpace script to have a serialized reference to your UI menu controller, and have it call
ActivateBuildMenu(this)
instead of Instantiating the menu object.
Again, the precise implementation can be moved around a bit, but that's the gist of it.
Thank you. That should be enough to get me what I want.
I assumed as much. I'm rather new to Unity, so I'm often just brute-forcing things as I learn, but thanks for the additional advice.I really recommend having one "build$$anonymous$$enuCanvas" that you turn on/off and move around the screen ins$$anonymous$$d of creating/deleting a new one every time you open the menu—creation/deletion is expensive!
Your answer
Follow this Question
Related Questions
How do I get the global position 2 Answers
My onclick action listeners I attach to my buttons as I instantiate them only work once 1 Answer
Enemy only chasing pre-fab's original location, not instance's 2 Answers
Passing through a GameObject/Function to a button's OnClick 1 Answer
Weird behaviour when trying to dynamically create buttons 0 Answers