Search Unity

Instantiate(Object original, Transform parent) does not clone object with correct local position

Discussion in 'Scripting' started by davidhfw, Mar 30, 2017.

  1. davidhfw

    davidhfw

    Joined:
    Aug 17, 2016
    Posts:
    77
    Objective is to instantiate a arrow on top of a crossbow held by a enemy character. What I did was to child the arrow object to the crossbow object and then position/rotate the arrow to the position/rotation I want. Then I create arrow prefab by dragging the scene arrow into my project prefab folder. In script, I called the Instantiate method
    Code (CSharp):
    1. public GameObject arrowPrefab;
    2. public Transform crossbowAsParent;
    3.  
    4. Instantiate(arrowPrefab, crossbowAsParent);
    I drag the arrow prefab into the public arrowPrefab field and the crossbow scene object into the public Transform crossbowAsParent field in the inspector.

    When the Instantiate method is called, the cloned arrow appeared a child object (in the object hierarchy) of the crossbow object correctly, but it does not have the original/prefab's position and rotation values, which it should according to the Unity manual, unless I have interpreted wrongly.

    "If a parent is specified and no position and rotation is specified, the position and rotation of the original will be used for the cloned object's local position and rotation, or its world position and rotation if the instantiateInWorldSpace parameter is true."

    Appreciate any help on this. Thanks!
     
  2. joshmond

    joshmond

    Joined:
    May 28, 2012
    Posts:
    34
    Hello Davidhfw,

    The problem you have here is you are instantiating the object but it's not holding any reference to anything so you cannot manipulate the position. What you want to do is something like this:

    Code (CSharp):
    1.  
    2.  
    3. [SerializeField]
    4. private GameObject arrow; // Assign a prefab to this in the inspector
    5.  
    6. [SerializeField]
    7. private Transform arrowPosition; // grab objects's position
    8.  
    9. void Start()
    10. {
    11.     InstantiateObject();
    12. }
    13.  
    14. private void InstantiateObject()
    15. {
    16.      GameObject arrowPrefab = Instantiate(arrow) as GameObject; // creating a local game object to store the    instantiated object and then casting it to a Gamebject
    17.  
    18.   arrowPrefab.name = "Arrow"; // Setting prefab name in hierarchy
    19.   arrowPrefab.transform.position = new Vector3(arrowPosition.position.x, arrowPosition.position.y, arrowPosition.position.z); // Setting the position of the prefab to "arrowPosition"
    20. }
    21.  
    Using this method you have more control over the placement of the prefab, you can also set a parent. If you wanted to you could set the position of the prefab directly by doing: "arrowPrefab.transform.position = arrowPosition.position", the benefit of using the Vector3 is you can apply offsets to the position.

    Hope this has helped.

    Regards

    -Joshmond
     
    Last edited: Mar 30, 2017
  3. davidhfw

    davidhfw

    Joined:
    Aug 17, 2016
    Posts:
    77
    Hi Joshmond,

    What you suggested worked perfectly, thank you. However, I would like to know more on using the Transform parent parameter in Instantiate(Object original, Transform parent) method.

    Original gameobject is at (0, 0, 30) //as shown in inspector, world coordinates
    Parent gameobject is at (0, 0, 10) //as shown in inspector, world coordinates

    After I child the original gameobject to the parent, the original gameobject has the coordinate (0, 0, 20) // as shown in inspector, local coordinates

    Next I drag the original child gameobject into the prefab folder and made it a prefab. The prefab's coordinates as shown in the inspector is (0, 0, 20) //these values local coordinates relative to the parent object

    In script, I create the clone Instantiate(original, parent) and the clone has the coordinate (0, 0, 10) //as shown in inspector, local coordinates.

    From this simple test, it seems that the clone was spawned at world coordinates (0, 0, 20) before changing the values to (0, 0, 10) as local coordinates in the inspector as it is childed to the parent.

    The manual mentioned that if a parent is specified and no position and rotation is specified (as in our case here), the position and rotation of the original will be used for the cloned object's local position and rotation. The simple test seems to demonstrate that the position of the original has been used as the cloned object's world position instead.

    Long story short, is there a way to spawn the clone object as a child of the parent and use the position values in the prefab as local coordinates instead of world coordinates?

    Thanks!

     
  4. joshmond

    joshmond

    Joined:
    May 28, 2012
    Posts:
    34
    That is a very simple fix, all you need to do is set the transform.parent before setting the position, so it code you will add this line:

    Code (CSharp):
    1.  
    2. private void InstantiateObject()
    3. {
    4.      GameObject arrowPrefab = Instantiate(arrow) as GameObject; // creating a local game object to store the    instantiated object and then casting it to a Gamebject
    5.   arrowPrefab.name = "Arrow"; // Setting prefab name in hierarchy
    6. arrowPrefab.transform.parent = arrowPosition;
    7.   arrowPrefab.transform.position = new Vector3(arrowPosition.position.x, arrowPosition.position.y, arrowPosition.position.z); // Setting the position of the prefab to "arrowPosition"
    8. }
    9.  
    Hope that helps.

    Regards

    -Joshmond
     
  5. davidhfw

    davidhfw

    Joined:
    Aug 17, 2016
    Posts:
    77
    Thank you Joshmond!

     
  6. gauravbc46

    gauravbc46

    Joined:
    Sep 17, 2019
    Posts:
    3
    Yeah I found it.
    GameObject arrowprefab=Instantiate(arrow) as GameObject;
    arrowprefab. SetParent(arrowPosition, false) ;
    Check SetParent() for more