Hi,
I have a simple side-based shooter. Units fire projectiles; the projectiles hit opponents; opponents die if health is less than zero. I’d like that to extend further so that opponent dies and the launcher of the projectile gains experience. However, how do I handle or store the connection between projectile and its original owner? What is the best way to do this? I don’t want to have to keep a reference to the game object that fired it, or is that the actual solution? Again, I’m not a C# or Unity expert and I’m not sure of any memory implications for storing things like that, especially as I intend on running the game on a mobile platform.
If there is a link to help with this elsewhere, that’d be appreciated too.
EDIT: I’ve found this post here (How can i make it give u a certain xp everytime u kill someone? - Questions & Answers - Unity Discussions), which mentions searching for a particular game object to assign experience too when required. The issue I have is that there will be many user and enemy game objects that will have to call this fairly repeatedly, which could slow things down tremendously and doesn’t seem sensible.
I have another idea. Is it possible to store a reference to a script attached to the original shooter game object in the projectile gameobject itself that, if it kills the enemy gameobject, will first update the referenced script, then destroy itself?
Thanks!
Is it possible to store a reference to
a script attached to the original
shooter game object in the projectile
gameobject itself that, if it kills
the enemy gameobject, will first
update the referenced script, then
destroy itself?
Yes! ^^
That’s the usual solution. In most cases referencing gameobjects is pretty pointless. It’s always better to reference a script component that you actually need. Even when you don’t have a script referencing the Transform usually makes more sense.
Imagine this script on a projectile:
public class Projectile : MonoBehaviour
{
public PlayerScript owner;
// call this from your hit detection code
void GiveXPToOwner(float aXP)
{
if (owner != null)
owner.AddXP(aXP);
}
}
And this would be the script on the Player:
public class PlayerScript : MonoBehaviour
{
// this is the prefab reference that the player uses to fire a projectile
public Projectile prefab;
public float XP = 0;
public void AddXP(float aXP)
{
XP += aXP;
}
void Fire()
{
Projectile p = Instantiate(prefab, yourSpawnPos, yourRotation);
p.owner = this; // set the owner to this script instance.
// do your other firing here.
}
}
Note: The amount of XP might depend on what the projectile hit actually hit. This could be handled in your hit detection code if needed, An enemy could have a script attached that holds a variable with the XP that this enemy gives when killed / hit.
I think @Bunny83’s answer works and gets straight to the point, and since you asked for a design pattern, I’ll only add this one which you may find handy as your game gets bigger: The Observer Pattern.
Imagine that the player is shooting at an enemy. They want to know when the enemy is killed so they can gain XP. It’s simple enough for the enemy to get a reference to the player (in the above example, through the projectile) and then call a function to tell the player that they killed the enemy.
Now let’s add a scoreboard that updates a counter every time an enemy is killed. I suppose you could attach the scoreboard to the player or the enemy, but that means their code needs to know and care about scoreboards. Now add achievement tracking. Again, if we’re holding references to scripts and calling functions, either our enemy or player code needs to care about achievement tracking too.
This can get messy very quickly.
The Observer Pattern tells us that an enemy shouldn’t care about telling the player, scoreboard and achievement system that it has died. It should just make an announcement, and anyone who cares can listen to it and react accordingly. It can go about its business of being an enemy without needing to specifically handle the needs of other game objects.
This pattern may take a bit of time to wrap your head around, but it won’t take you very much time to write the code because C# delegates and events make it easy. The MSDN calls it the Event Pattern which is pretty much the same principle.
Good luck!