Unity Prefab not instantiated at the expected position

3.6k views Asked by At

Hello stackoverflow community.
I have a script that is instantiating NPCs at positions, that are saved in a special list. The NPC Prefabs do have a NavMeshAgent on them and are placed on a normal NavMesh. After Instantiating the Prefab I set the parent and also position and rotation of the new object to an empty object called "DynamicObjects" (just for grouping in the scene view). The parents Transform is at 0/0/0 with zero rotation, so it should be no problem to set a normal position. The problem is, that the object is not created at the given coordinates. For example the given position is 193/6.2/87 but the NPC will be at 170/6.4/87 instead of 193/6.2/87.
Here is my script (detailed explanation below):

GameObject npcPrefab = Resources.Load<GameObject>("Prefabs/NPC/NPC_default");
foreach (NPC_Wrapper wrapper in npc_wrappers) {
    if (wrapper.position.map != mapID)
        continue;

    GameObject npcObject = Instantiate(npcPrefab);
    npcObject.transform.SetParent(dynamicObjects);

    NPCBase npcBase = npcObject.GetComponent<NPCBase>();
    npcBase.SetPosition(new Vector3(wrapper.position.x, wrapper.position.y, wrapper.position.z));
    npcBase.SetRotation(new Vector3(wrapper.position.rotX, wrapper.position.rotY, wrapper.position.rotZ));
    npcBase.SetEntityID(wrapper.npcID);
    npcBase.SetWorldPosition(wrapper.position);

    Debug.Log("Spawn NPC " + wrapper.npcID + " at " + wrapper.position.x + "/" + wrapper.position.y + "/" + wrapper.position.z);
}

Explanation:
First step is loading the prefab. I have a list with NPC_Wrapper objects in it. Those wrappers contain the position of a NPC. I check for every NPC, if it is in this map (mapID). If it is in this map, i Instantiate the prefab and set the parent to dynamicObjects (Transform of my empty object). Now i grab my NPCBase class from the Instantiated object and set transform.position and transform.rotation by using the SetPosition and SetRotation method (it just does that, but in the NPCBase class). SetEntityID and SetWorldPosition have no effect, so we can skip them. When im done i log the position where it should be to the console. And although i set the right coordinates, the GameObject wont be at the position in wrapper.position.xyz.

What i have tried:

  • replacing transform.position with transform.localPosition
  • using NavMeshAgent.nextPosition instead of transform.position
  • setting to 0/0/0 (seems to work just fine)
  • Instantiating without setting the parent (no difference)
  • setting the position inside this method directly: npcObject.transform.position = ... (no difference)
  • searching the internet and this forum (but couldnt find a good answer or one that fixed my problem)

I tried figuring it out by myself for a while now but im really frustrated so i thought i'd ask if someone has an idea what may be the problem.
Thank you in advance and i will be happy to answer any questions!

1

There are 1 answers

3
dnjj On

Alright after 2 days of debugging I figured it out!

So, the instantiated GameObject has a NavMeshAgent on it. I instantiated it and set the position to my desired position. The problem is, that the NavMeshAgent will change the position of the GameObject in the first frame after spawning. Thats because although the object is on a valid NavMesh, the Agent will adjust it's initial position somehow.

How i fixed it:
Honestly, most problems like this have fairly simple solutions. In this case, don't set the position of the object by using transform.position = newVector but rather by using navmeshagent.Warp(newVector). This works fine in all tested cases.
Hope other people having this problem can profit of this as well :)