Search Unity

Problem with Instantiate

Discussion in 'Getting Started' started by Xenoun, Sep 24, 2015.

  1. Xenoun

    Xenoun

    Joined:
    Sep 2, 2015
    Posts:
    201
    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:

     
  2. jhocking

    jhocking

    Joined:
    Nov 21, 2009
    Posts:
    814
    Can you post the code you wrote? It's impossible to know what you did wrong without knowing what you did.
     
  3. Xenoun

    Xenoun

    Joined:
    Sep 2, 2015
    Posts:
    201
    It isn't my code, it's from the tutorial and worked fine in that. Here it is:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class GunController : MonoBehaviour {
    5.  
    6.     public Transform weaponHold;
    7.     public Gun startingGun;
    8.     Gun equippedGun;
    9.  
    10.     void Start() {
    11.         if (startingGun != null) {
    12.             EquipGun(startingGun);
    13.         }
    14.     }
    15.  
    16.     public void EquipGun(Gun gunToEquip) {
    17.         if (equippedGun != null) {
    18.             Destroy(equippedGun.gameObject);
    19.         }
    20.         equippedGun = Instantiate (gunToEquip, weaponHold.position,weaponHold.rotation) as Gun;
    21.         equippedGun.transform.parent = weaponHold;
    22.     }
    23.  
    24.     public void Shoot() {
    25.         if (equippedGun != null) {
    26.             equippedGun.Shoot();
    27.         }
    28.     }
    29. }
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Gun : MonoBehaviour {
    5.  
    6.     public Transform muzzle;
    7.     public Projectile projectile;
    8.     public float msBetweenShots = 100;
    9.     public float muzzleVelocity = 35;
    10.  
    11.     float nextShotTime;
    12.  
    13.     public void Shoot() {
    14.  
    15.         if (Time.time > nextShotTime) {
    16.             nextShotTime = Time.time + msBetweenShots / 1000;
    17.             Projectile newProjectile = Instantiate (projectile, muzzle.position, muzzle.rotation) as Projectile;
    18.             newProjectile.SetSpeed (muzzleVelocity);
    19.         }
    20.     }
    21. }
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. [RequireComponent (typeof (PlayerController))]
    5. [RequireComponent (typeof (GunController))]
    6. public class Player : MonoBehaviour {
    7.  
    8.     public float moveSpeed = 5;
    9.  
    10.     Camera viewCamera;
    11.     PlayerController controller;
    12.     GunController gunController;
    13.  
    14.     void Start () {
    15.         controller = GetComponent<PlayerController> ();
    16.         gunController = GetComponent<GunController> ();
    17.         viewCamera = Camera.main;
    18.     }
    19.  
    20.     void Update () {
    21.         // Movement input
    22.         Vector3 moveInput = new Vector3 (Input.GetAxisRaw ("Horizontal"), 0, Input.GetAxisRaw ("Vertical"));
    23.         Vector3 moveVelocity = moveInput.normalized * moveSpeed;
    24.         controller.Move (moveVelocity);
    25.  
    26.         // Look input
    27.         Ray ray = viewCamera.ScreenPointToRay (Input.mousePosition);
    28.         Plane groundPlane = new Plane (Vector3.up, Vector3.zero);
    29.         float rayDistance;
    30.  
    31.         if (groundPlane.Raycast(ray,out rayDistance)) {
    32.             Vector3 point = ray.GetPoint(rayDistance);
    33.             //Debug.DrawLine(ray.origin,point,Color.red);
    34.             controller.LookAt(point);
    35.         }
    36.  
    37.         // Weapon input
    38.         if (Input.GetMouseButton(0)) {
    39.             gunController.Shoot();
    40.         }
    41.     }
    42. }
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. [RequireComponent (typeof (Rigidbody))]
    5. public class PlayerController : MonoBehaviour {
    6.  
    7.     Vector3 velocity;
    8.     Rigidbody myRigidbody;
    9.  
    10.     void Start () {
    11.         myRigidbody = GetComponent<Rigidbody> ();
    12.     }
    13.  
    14.     public void Move(Vector3 _velocity) {
    15.         velocity = _velocity;
    16.     }
    17.  
    18.     public void LookAt(Vector3 lookPoint) {
    19.         Vector3 heightCorrectedPoint = new Vector3 (lookPoint.x, transform.position.y, lookPoint.z);
    20.         transform.LookAt (heightCorrectedPoint);
    21.     }
    22.  
    23.     public void FixedUpdate() {
    24.         myRigidbody.MovePosition (myRigidbody.position + velocity * Time.fixedDeltaTime);
    25.  
    26.     }
    27. }

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Projectile : MonoBehaviour {
    5.  
    6.     float speed = 10;
    7.  
    8.     public void SetSpeed(float newSpeed) {
    9.         speed = newSpeed;
    10.     }
    11.  
    12.     void Update () {
    13.         transform.Translate (Vector3.forward * Time.deltaTime * speed);
    14.     }
    15. }
     
  4. jhocking

    jhocking

    Joined:
    Nov 21, 2009
    Posts:
    814
    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?
     
  5. Xenoun

    Xenoun

    Joined:
    Sep 2, 2015
    Posts:
    201

    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.
     
  6. jhocking

    jhocking

    Joined:
    Nov 21, 2009
    Posts:
    814
    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);
     
  7. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I wonder if it's this bit:
    Code (CSharp):
    1. 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.
     
  8. jhocking

    jhocking

    Joined:
    Nov 21, 2009
    Posts:
    814
    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.
     
    Last edited: Sep 24, 2015
    JoeStrout likes this.
  9. Xenoun

    Xenoun

    Joined:
    Sep 2, 2015
    Posts:
    201
    Thanks for the help, about to head off to work so will try it out when I get home.
     
  10. Xenoun

    Xenoun

    Joined:
    Sep 2, 2015
    Posts:
    201
    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
     
  11. jhocking

    jhocking

    Joined:
    Nov 21, 2009
    Posts:
    814
    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.
     
  12. Xenoun

    Xenoun

    Joined:
    Sep 2, 2015
    Posts:
    201
    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.
     
  13. Xenoun

    Xenoun

    Joined:
    Sep 2, 2015
    Posts:
    201
    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.
     
  14. jhocking

    jhocking

    Joined:
    Nov 21, 2009
    Posts:
    814
    Where'd the model come from? Did you model it yourself, or get it off the asset store, or what?
     
  15. Xenoun

    Xenoun

    Joined:
    Sep 2, 2015
    Posts:
    201
    Modeled it myself from three Cube objects, same way that the tutorial showed.
     
  16. jhocking

    jhocking

    Joined:
    Nov 21, 2009
    Posts:
    814
    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.
     
  17. Xenoun

    Xenoun

    Joined:
    Sep 2, 2015
    Posts:
    201
    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.
     
  18. Xenoun

    Xenoun

    Joined:
    Sep 2, 2015
    Posts:
    201
    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?
     
  19. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    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...)
     
  20. Xenoun

    Xenoun

    Joined:
    Sep 2, 2015
    Posts:
    201
    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.
     
  21. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Watch out for "Pivot" vs. "Center" tool handle mode:



    If that "Pivot" button says "Center" for you, click it now and never touch it again. :) Center mode draws the tool handle (e.g. the move axes or rotation circles) at the centroid of the selected object and all its children objects. This makes it very hard to tell what the object's actual origin is.

    I always work in "Pivot" mode, which puts the tool handles at the position of the selected object.

    So my guess is that when you assembled your gun, your child objects (boxes) were actually quite far from the position of the parent object, which is what defines the pivot point (i.e. what actually gets positioned when you assign to the position of the object). But because you were in Center mode, you had no easy way to see that.

    Try it again, in Pivot mode, and take care of how your boxes are positioned relative to the container object.

    Finally, to make it easier, you should probably work at the origin. When you create your empty container object, it will get a position based on whatever was selected before, which is usually not what you want — immediately check its position and reset it to 0,0,0. Then add your child objects (boxes or whatever), positioned relative to the origin how you want them to be.

    HTH,
    - Joe
     
    jhocking likes this.
  22. Xenoun

    Xenoun

    Joined:
    Sep 2, 2015
    Posts:
    201
    Alright, sounds relatively straight forward...and like an easy mistake to make for a new user

    Thanks for the help, I'll give it a shot.
     
    JoeStrout likes this.
  23. Xenoun

    Xenoun

    Joined:
    Sep 2, 2015
    Posts:
    201
    All working now, even got the 3-cube Gun back in and instantiating in the correct position.

    Thanks a lot for the help @jhocking and @JoeStrout
     
    holliebuckets and JoeStrout like this.
  24. Neolance123

    Neolance123

    Joined:
    Sep 3, 2021
    Posts:
    1
    Worked like a charm! Thank you for posting and thank you for whoever coded this.