I need to start by saying, this is probably a very simple issue I’m just overlooking.
I am instantiating a prefab at runtime, giving it a parent, and trying to set it’s position to (0, -0.5, 0) relative to the parent, so it’s just below the ground. No matter what way I try this, it keeps being created relative to the world coords in the middle of the map.
I’ve been searching this for hours, and all I keep hearing is “Set localPosition rather than position”, and I know that this should be the fix for this, but it’s not working. I must be missing something.
Here’s the guilty method, with the instantiating being right at the top. This method is being called in a script as part of the parent object, incase that’s relevant.
public void CollisionDetected(Collision collision) {
spikeChild = Instantiate(spikeChildPrefab, transform).transform;
spikeChild.localPosition = spikesDownPosition;
print("Spike Parent " + spikeChild.parent);
if (currentState == SpikeState.SpikesDown) {
currentState = SpikeState.Extending;
var targetsHealthSystem = null as HealthSystem;
if ((targetsHealthSystem = collision.gameObject.GetComponent<HealthSystem>()) != null) {
targetsHealthSystem.TakeDamageOverTime(5, 3);
}
}
}
The parent is being set fine, I’ve tried setting InstantiateInWorldSpace to false, everything I can think of, but the GODDAMN COORDS ARE LAUGHING IN MY FACE.
In the inspector, if the parent is at position (10, 1, 5), then the child shows up at (-10, -1.5, -5), because it’s being set to 0, -0.5, 0 in the world.
I thought the same thing about the parents scale/rotation, but even setting the scale to (1, 1, 1) and rotation to (0, 0, 0) doesn’t change anything. Same thing with the SetParent method, I’ve tried that, as well as just straight up doing transform.parent to set the parent, doesn’t change anything either.
It’s doing my head in to be honest. If I had to I could just position it in relation to the world using the parents transform, but I feel like whatever it is I’m missing could start to create bigger problems in the future when I’m working with more complex models, so I’d like to find out what it is that’s being weird.
I’ve read that localPosition works the same as position whenever there is no parent object, so I’m thinking there’s something I don’t know about parenting an object maybe? But that’s still being set correctly, so Idk at this point.
All I can think of is that maybe some other script is interfering … worst comes to worst I don’t think anyone’s gonna blame you for using a hacky workaround like child.transform.position = parent.transform.position + new Vector3(0, -0.5, 0). Or you could even try waiting a frame and then setting localPosition. If that still doesn’t work, I would suspect some script is interfering.
Other than that I can only suggest the obvious, like ensuring that they actually do get parented (i.e. one is below the other in the hierachy) and that the parent is actually at 10, 1, 5 and not actually at 0, 0, 0, like you say. I would also double-check that the ‘transform’ you are parenting it to is actually the correct transform.
Might just be one of those weird things. I’ve had similar problems before - I think there’s possibly something wrong with Unity under the hood. Or maybe it’s just not as easy as we think
Here’s an image of the inspector the moment after the Log is printed. I’ve printed the value of spikesDownPosition, the actual value of spikeChild.position after it’s localPosition is being set, as well as printing transform.parent, and it’s showing SpikeTrap as the parent, which matches with the list on the left.
Spikes, selected in the inspector, is the child object which was just created, and it’s position in the inspector is different than it’s position in the Debug.Log. The Debug.Log position is where it should be in the world, because the parent is at (10, 1, 5), but it’s not. (Note: The -1.442968 is because it immediately starts moving upwards once the trap is triggered, it’s actually created at -1.5).
I’ve also included the modified method with the Debug’s included, just incase there’s any confusion.
public void CollisionDetected(Collision collision) {
spikeChild = Instantiate(spikeChildPrefab, transform).transform;
spikeChild.localPosition = spikesDownPosition;
Debug.Log($"spikeDownPosition: {spikesDownPosition}");
Debug.Log($"Actual spike Position: {spikeChild.position}");
Debug.Break();
print("Spike Parent " + spikeChild.parent);
if (currentState == SpikeState.SpikesDown) {
currentState = SpikeState.Extending;
var targetsHealthSystem = null as HealthSystem;
if ((targetsHealthSystem = collision.gameObject.GetComponent<HealthSystem>()) != null) {
targetsHealthSystem.TakeDamageOverTime(5, 3);
}
}
}
Thanks this thread and PraetorBlue!
I had the same problem with script interference: one tries to reposition child to new parent and another tries to reposition the same child relative to it’s original position (from original parent).