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

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

public GameObject arrowPrefab;
public Transform crossbowAsParent;

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!

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:

[SerializeField]
private GameObject arrow; // Assign a prefab to this in the inspector

[SerializeField]
private Transform arrowPosition; // grab objects's position

void Start()
{
    InstantiateObject();
}

private void InstantiateObject()
{
     GameObject arrowPrefab = Instantiate(arrow) as GameObject; // creating a local game object to store the    instantiated object and then casting it to a Gamebject

  arrowPrefab.name = "Arrow"; // Setting prefab name in hierarchy
  arrowPrefab.transform.position = new Vector3(arrowPosition.position.x, arrowPosition.position.y, arrowPosition.position.z); // Setting the position of the prefab to "arrowPosition"
}

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

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!

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:

private void InstantiateObject()
{
     GameObject arrowPrefab = Instantiate(arrow) as GameObject; // creating a local game object to store the    instantiated object and then casting it to a Gamebject
  arrowPrefab.name = "Arrow"; // Setting prefab name in hierarchy
arrowPrefab.transform.parent = arrowPosition;
  arrowPrefab.transform.position = new Vector3(arrowPosition.position.x, arrowPosition.position.y, arrowPosition.position.z); // Setting the position of the prefab to "arrowPosition"
}

Hope that helps.

Regards

-Joshmond

Thank you Joshmond!

Yeah I found it.
GameObject arrowprefab=Instantiate(arrow) as GameObject;
arrowprefab. SetParent(arrowPosition, false) ;
Check SetParent() for more