Problem with Instantiate

I’ve googled looking for someone with a similar problem…there are many but they all seem to be slightly different so their solution doesn’t work for me…

Basically I’m trying to instantiate a gun in the hand of my character. I’m using the scripts from a tutorial - was having issues so directly copied everything to make sure I didn’t make typos.

I have a game object that’s referenced in the player script as the position the gun is meant to instantiate to. I’ve dragged the game object to the weapon hold reference on the player script in the inspector. As far as I can tell I’ve done the same as the tutorial.

The issue i’m having though is that the gun spawns at it’s default prefab location - the same as if I just dragged the prefab into the hierarchy. It doesn’t seem to take note of the weapon hold position at all.

Also having a similar issue with bullet spawns - they’re spawning at the right spot from the gun but wrong rotation compared to the guns game object for muzzle position.

Are there any common mistakes that newbies make that I could have fallen into? I’ve gone over everything multiple times, completely deleted and restarted and keep getting the same result.

For reference the tutorial is:

Can you post the code you wrote? It’s impossible to know what you did wrong without knowing what you did.

It isn’t my code, it’s from the tutorial and worked fine in that. Here it is:

using UnityEngine;
using System.Collections;

public class GunController : MonoBehaviour {

    public Transform weaponHold;
    public Gun startingGun;
    Gun equippedGun;

    void Start() {
        if (startingGun != null) {
            EquipGun(startingGun);
        }
    }

    public void EquipGun(Gun gunToEquip) {
        if (equippedGun != null) {
            Destroy(equippedGun.gameObject);
        }
        equippedGun = Instantiate (gunToEquip, weaponHold.position,weaponHold.rotation) as Gun;
        equippedGun.transform.parent = weaponHold;
    }

    public void Shoot() {
        if (equippedGun != null) {
            equippedGun.Shoot();
        }
    }
}
using UnityEngine;
using System.Collections;

public class Gun : MonoBehaviour {

    public Transform muzzle;
    public Projectile projectile;
    public float msBetweenShots = 100;
    public float muzzleVelocity = 35;

    float nextShotTime;

    public void Shoot() {

        if (Time.time > nextShotTime) {
            nextShotTime = Time.time + msBetweenShots / 1000;
            Projectile newProjectile = Instantiate (projectile, muzzle.position, muzzle.rotation) as Projectile;
            newProjectile.SetSpeed (muzzleVelocity);
        }
    }
}
using UnityEngine;
using System.Collections;

[RequireComponent (typeof (PlayerController))]
[RequireComponent (typeof (GunController))]
public class Player : MonoBehaviour {

    public float moveSpeed = 5;

    Camera viewCamera;
    PlayerController controller;
    GunController gunController;
 
    void Start () {
        controller = GetComponent<PlayerController> ();
        gunController = GetComponent<GunController> ();
        viewCamera = Camera.main;
    }

    void Update () {
        // Movement input
        Vector3 moveInput = new Vector3 (Input.GetAxisRaw ("Horizontal"), 0, Input.GetAxisRaw ("Vertical"));
        Vector3 moveVelocity = moveInput.normalized * moveSpeed;
        controller.Move (moveVelocity);

        // Look input
        Ray ray = viewCamera.ScreenPointToRay (Input.mousePosition);
        Plane groundPlane = new Plane (Vector3.up, Vector3.zero);
        float rayDistance;

        if (groundPlane.Raycast(ray,out rayDistance)) {
            Vector3 point = ray.GetPoint(rayDistance);
            //Debug.DrawLine(ray.origin,point,Color.red);
            controller.LookAt(point);
        }

        // Weapon input
        if (Input.GetMouseButton(0)) {
            gunController.Shoot();
        }
    }
}
using UnityEngine;
using System.Collections;

[RequireComponent (typeof (Rigidbody))]
public class PlayerController : MonoBehaviour {

    Vector3 velocity;
    Rigidbody myRigidbody;

    void Start () {
        myRigidbody = GetComponent<Rigidbody> ();
    }

    public void Move(Vector3 _velocity) {
        velocity = _velocity;
    }

    public void LookAt(Vector3 lookPoint) {
        Vector3 heightCorrectedPoint = new Vector3 (lookPoint.x, transform.position.y, lookPoint.z);
        transform.LookAt (heightCorrectedPoint);
    }

    public void FixedUpdate() {
        myRigidbody.MovePosition (myRigidbody.position + velocity * Time.fixedDeltaTime);

    }
}
using UnityEngine;
using System.Collections;

public class Projectile : MonoBehaviour {

    float speed = 10;

    public void SetSpeed(float newSpeed) {
        speed = newSpeed;
    }
 
    void Update () {
        transform.Translate (Vector3.forward * Time.deltaTime * speed);
    }
}

It’s a video tutorial, so you wrote this code. Perhaps you were just copying what was on-screen, but maybe you left something out or made some typos.

Anyway, presumably ‘weaponHold’ in GunController.cs is the object in your scene for the player’s hand?

No, I copied and pasted it, as stated in the OP. I know the code is correct, can’t figure out what I’ve done wrong when using it.

muzzle is the gameobject at the end of the gun to locate the instantiate…that works correctly but the rotation is sideways compared to the gun.

As for the gun spawn, Weapon Hold is an object on the player…the gun instantiates at it’s own prefab location rather than at Weapon Hold.

oh I missed that sentence. Technically you didn’t state that actually (who knows what “directly copied” means) but whatever it’s not important.

Well I’m stumped. The code all looks correct, so at this point I’d start putting in debug logging statements to see what’s happening. For starters, write this immediately after instantiating the gun in order to see what position Unity is reporting for weaponHold, and then methodically repeat this kind of thing elsewhere:

Debug.Log("instantiated gun: " + weaponHold.position + " " + equippedGun.gameObject.transform.position);

I wonder if it’s this bit:

equippedGun.transform.parent = weaponHold;

As of Unity 5 (IIRC), this direct assignment generates a warning; the “official” way to do it is to call transform.SetParent.

If you directly change the parent, I think it will keep the local position/rotation, which would not be what you want in this case, since you’ve already instantiated it at the weaponHold position/rotation — you’re essentially applying that translation & rotation twice.

So try changing the line above to a call to SetParent (with ‘true’ as the second parameter), or, do an end-run around the issue by assigning the position and rotation after changing the parent.

Actually Unity does not keep the local transform; read the description of the parent property (“parent-relative” is a synonym for “local”). It changes the local position/rotation when setting a parent directly, which is the entire reason they introduced the SetParent() command in Unity 5. Note that it defaults to ‘true’ if you don’t specifically tell it ‘false’.

Apparently when creating Unity they thought it was less confusing to maintain the same global position/rotation and change the local position/rotation. In other development tools you would expect objects to keep their local transform and Unity does not, so that was confusing.

My guess would be the weaponHold position is incorrect, hence the debug logging I suggested.

1 Like

Thanks for the help, about to head off to work so will try it out when I get home.

Ok, so it reports that weaponHold and the equippedGun positions are the same:

instantiated gun: (0.1, 0.8, 0.3) (0.1, 0.8, 0.3)

I created a Sphere and positioned it at 0.1, 0.8, 0.3 just to check and it matches where the gun should be (hand of the character) but the equippedGun isn’t appearing at that location…it’s above the character’s head.

I’m not sure how the global/local co-ordinate system works in Unity but the inspector shows my Weapon Hold game object is at 0.1, 0, 0.32

The Inspector shows local position while the code is showing global position, so that’s why those are different. It’s good thinking to put a sphere in the scene to check, but can you do that with the gun? I wonder what happens when you manually place the gun; perhaps the problem is your model.

I think you’re on the right track with my gun model causing the issue. The gun shows its co-ordinate system is based upon a point slightly below the barrel, centred in the other two directions. This seems perfectly fine.

When I dragged the prefab into the hierarchy it shows the position in bold, not sure if this is an area for concern, I assumed that just meant it was a prefab. Typing in the position as 0.1, 0.8, 0.3 puts it even further above the character.

So seems like something is going on with co-ordinate systems clashing.

Any other advice for me on this?

I’ve messed around trying to fix it for a few hours and can’t find the cause. Next step is to just restart from scratch and see if it happens again.

Even if that fixes it I’d still rather figure out what I’ve done wrong so I know what to do/avoid next time.

Where’d the model come from? Did you model it yourself, or get it off the asset store, or what?

Modeled it myself from three Cube objects, same way that the tutorial showed.

That’s sort of what the bold means, but that could be an important clue here. When you change part of a prefab instance in the scene from what’s in the base prefab, those changes show up bold. However I don’t think the position should be bold when you are adjusting the overall prefab object, only when you change things within it. So that makes me suspicious that your gun is actually parented to something else, and when you manually position the gun you aren’t selected that root object.

I’ve changed the gun to a single cube object to see if there was an issue with the three - same problem occurring.

As for the bold. The “Gun” prefab is the parent object, has a cube child and also an empty game object child for the muzzle position. When I drag the Gun prefab to the hierarchy and select the Gun parent the position etc is bold. If I click the Gun parent in my prefab folder without dragging it in then it isn’t in bold.

Just looked at the tutorial closely - The Gun model in the tutorial shows its origin towards the butt of the gun, matches the point for where it instantiates at his player.
Is there a way to manually change the origin of the local co-ordinate system?

When you’re modeling a gun, you control that in the modeling app. The origin of the coordinate system in your modeler will usually become the origin of the object when it’s exported.

So are you finding your test cube is being instantiated with its center at the position you’re telling it to instantiate at? (This is how it should work…)

The test cube is working that way, yes. This seems to be correct and I can move on.

In terms of how the gun was at first though, constructed of three cube objects that were grouped together their co-ordinate system origin was just underneath the “barrel” of the gun. When that was instantiated it appeared way over the character’s head and the gun co-ordinate origin did not match the instantiate location, however the debug reported that it did. Still not sure what went on there. I’ll watch the tutorial that did it closely one more time as I think he did something subtle with the origin of the gun as it was different to how mine worked out.