WynDiesel
WynDiesel

Reputation: 1214

Child object not instantiating on parent

I'm having a hard time grasping the concept of position in Unity.

Have a parent object (Player). On that player, I have a child object called "Gun". On the gun, I have a script to fire bullets. When I fire the bullets, it spawns to the left of the gun, and the player.

I've tried offsetting the bullet's position on spawn, but when I turn around, the location is incorrect (it's still not centered on the gun). I also have a feeling that the offset that I've tried is a hack, and that I've missed something somewhere.

My code for the firing script on the gun :

void Update()
{
    if (Input.GetAxisRaw("Fire1") > 0)
    {
        var pos = transform.position;
        print(pos.ToString());
        var proj = Instantiate(projectile, pos, Quaternion.identity);

        proj.transform.rotation = transform.rotation;

    }
}

The only other thing touching the bullet, is my BulletController, a script on the bullet :

void Start()
{
    rb = GetComponent<Rigidbody2D>();
    //rb.AddForce(transform.forward * 100, ForceMode.Impulse);
    rb.velocity = transform.up * 10;

}

Attached screenshot of my setup enter image description here

Upvotes: 2

Views: 2007

Answers (3)

WynDiesel
WynDiesel

Reputation: 1214

The problem was that I instantiated the sprite on the bullets on an offset, and not 0,0,0 relative to the actual gameobject.

Upvotes: 1

derHugo
derHugo

Reputation: 90813

feeling that the offset that I've tried is a hack

I don't see any offset .. you could do e.g.

public float offset = 0.5f;


if (Input.GetAxisRaw("Fire1") > 0)
{
    // add the offset here
    var pos = transform.position + transform.up * offset;
    print(pos.ToString());

    var proj = Instantiate(projectile, pos, Quaternion.identity);

    proj.transform.rotation = transform.rotation;
}

transform.position spawns the bullet at the same place as the gun. I added transform.up since it seems this is the direction your player is looking to (in 3D space it would e.g. be transform.forward but in 2D it is either transform.up or transform.right depending in which direction the player looks by default). offset is just how far you want the bullet be placed in the given direction in meters/units.


If you rather want a Vector3 offset for more control/for debugging which axis is the correct one you could instead use

public Vector3 offset;

//...

var proj = Instantiate(projectile, transform.position, Quaternion.identity);

proj.transform.rotation = transform.rotation;

// Now move it to the offset in local space
proj.transform.Translate(offset, Space.Self);

You don't want to spawn it as child ... because if you than move or rotate after, your bullets will all also move and rotate together with you!

Upvotes: 1

Battle
Battle

Reputation: 816

You want to position the bullet to a relative offset based on the facing of the gun, right? If you set the position as you do now, you do it in world position unrelated to the facing of the gun.

Now, there are 2 ways how you can do it:

Place the bullet as a child object of the gun with a relative local position and unparent it immediately. Not a nice solution and resembles more a hack.

Or use the following methods, which I created:

/// <summary> Returns a vector which is relative to the facing and position of 'c'. </summary>
public static Vector3 RelativePosition (Transform c, Vector3 target)
{
    return c.right * target.x + c.up * target.y + c.forward * target.z + c.position;
}

/// <summary> Returns a vector which is relative. </summary>
public static Vector3 RelativePosition (Vector3 position, Vector3 forward, Vector3 up, Vector3 right, Vector3 target)
{
    return right * target.x + up * target.y + forward * target.z + position;
}

And complementary this:

/// <summary> Returns a vector which is relative to the facing of 'c'. </summary>
public static Vector3 RelativePositionZero (Transform c, Vector3 target)
{
    return c.right * target.x + c.up * target.y + c.forward * target.z;
}

/// <summary> Returns a vector which is relative. </summary>
public static Vector3 RelativePositionZero (Vector3 forward, Vector3 up, Vector3 right, Vector3 target)
{
    return right * target.x + up * target.y + forward * target.z;
}

Usage: Use the RelativePosition method, provide the Transform of the gun as parameter and the relative offset for the Vector3 parameter. Example:

        item.position = RelativePosition (Camera.Main.transform, new Vector3 (1.5f, 0f, 4.0f));

This would place the position of 'item' 4 unity distance in front of the camera and 1.5 unity distance to the right.

Hint: RelativePosition will give you the resulting world position as it is. This is what you use to receive the relative position you seek as world position. RelativePositionZero will give you the relative offset from the Transform object to the given Vector3 position. That can be used to determine if something is left or right, above or below, in front or behind the given Transform.

Upvotes: 2

Related Questions