- Home /
How can I replace an object while keeping the references to that object?
Basically I have a player character object and when the player hits a button I want to replace that character object with a different character object. I have that working fine with this code:
spawnposition = GameObject.FindWithTag("player").transform.position;
Destroy (GameObject.FindWithTag ("player"));
GameObject newplayer = Instantiate(prefabtospawn, spawnposition, transform.rotation) as GameObject;
However, I have a camera and certain enemies whose movement is based on the player character and they have references to the player character set up as such:
_playerposition = GameObject.FindGameObjectWithTag("player").transform;
So when I execute the first set of code above, it works as intended, getting the correct spawn position, killing off the old object, spawning the new one, but then of course I get error messages because the camera / enemies are trying to access the old player position and that object no longer exists.
I'm not really sure what to do about this. I figure that I either...
A. Instead of killing the original object and creating a new one, just switch it out somehow (is this even possible?)
Or if that isn't possible...
B. Find all references to the old object and set them to the new object. No idea how to do this though.
What would be the best way to handle this and where would I start?
Answer by whydoidoit · Feb 21, 2014 at 04:29 AM
Why not instantiate your characters as children of the object that your enemies know about then you can destroy and create what you like and the reference will remain the same.
I actually haven't done much parent / children stuff yet, total n00b here. Are you basically saying that the parent object would be an empty object and then the actual playable character would be a child of that object? And then you just kill one child and add another? But the references are to the parent so they're ok?
Yes, though you would want the child to move the parent object I guess so that the reference is to something that represents the player's location.
Are you just instantiating a new model or does it have lots of different scripts on it?
For context, this is a 2D sprite-based game. Currently all the button does is "make the character 3 times bigger", but I'm using a new object because I don't just want to stretch the old one. Otherwise it is pretty much the same thing with the same scripts. BUT... I have future plans for buttons that would change the player into a completely new thing... for instance I want one that replaces the character with a mech that would control differently and have different scripts attached. It would still have the scripts that the camera / enemies are referencing too though (basically all they do is check the position of the player), so I should be able to keep that all working. So yeah I definitely need to learn how to change to something different eventually, might as well figure it out now.
I'm still a bit confused though, let me see if I have this straight... so for instance there is this empty parent, and a child character attached to it that has my player character object. The child has movement scripts of course, so when those execute... what would I expect to happen? The child would move away from the parent? But since I want them to stick together I'd need to add something to the child movement script that also moves the parent? Or could I just have the child movement script move the parent only and the child would automatically move because children move with parents, correct? I think. Like I said, haven't done too much with parent / child relationships yet.
Yeah - this is one of those "it's a bit tricky to write down what to do" questions. I'll try to make more sense. So firstly you are right, you would do one of those two things to keep them together.
So having read your new comment I have a different idea, which would make having different control systems more easy.
Attach a script to each of the characters:
public class Player : $$anonymous$$onoBehaviour {
public static Player instance;
void Awake() {
instance = this;
}
}
Now you just make all of your enemies use Player.instance when they need to find the player, rather than using your tag lookup at the start. This solution remains very fast, but is dynamic, when you create a new character the instance is updated.
I like the simplicity of this new player script but it is leaving me a tad bit confused. Currently in the camera script, for instance, I create a reference to the player object in Awake, which I access every single LastUpdate to check the current player position and set my camera accordingly. If I used this new player script on all of my characters, how exactly would I reference it in my camera script, for instance? Do I still need to initialize it in Awake and then access it each time in LastUpdate?
Sorry if I'm missing some obvious thing, I basically just started game program$$anonymous$$g in November with Unity 4.3 so a lot of this stuff is still Greek to me.
Answer by PuneetK · Feb 21, 2014 at 05:35 AM
You can also just change the texture of your Player, assuming you are using a Sprite/unity2D. If its a 3d model, make the "player" as an empty gameObject, and make the character that represents your player a child of this "player".
So, player-Handles all interactions Player-child- Is the actual character which you would be switching out at runtime
Your answer
Follow this Question
Related Questions
Referencing instantiated objects at runtime 2 Answers
Reference by Instance ID? 2 Answers
Instantiate and destroy on given location 1 Answer
gameObject are not referenced 2 Answers
object not spawning but no error message 2 Answers