playMaker

Author Topic: How to have prefabs reference game objects without global variables?  (Read 6978 times)

Snowbird

  • Playmaker Newbie
  • *
  • Posts: 25
I am just encountering numerous situations for entirely separate reasons where I'd like to have prefabs reference a game object (usually it's location, but sometimes other reasons as well).

The solutions I have worked with so far are:
1. Have the game object reference the prefab instead of vice versa, but this isn't always a practical solution, and will definitely not work in every situation as the main character would need countless FSM's.
2. Create a global variable and have things reference that. This seems like a terrible method so far as sometimes my global variables just randomly disappear. I would prefer to just stay away from this entirely and find other methods.
3. Find less-than-ideal workarounds (for example I can just have big collision boxes appear and run trigger checks with all sorts of different tag names in order to know the correct direction, or lots of things similar that I mentioned in point #1.)

So just as an example, what would be a way to get a prefab wolf to know the exact location of the player, at anytime, without using global variables? The wolf doesn't need to know this the second it is created, but needs to know this during combat. 2d btw.

Any help is much appreciated.

Athin

  • Full Member
  • ***
  • Posts: 163
Re: How to have prefabs reference game objects without global variables?
« Reply #1 on: November 12, 2018, 11:42:15 PM »
There are a few ways to do this.

#1 If you use a TAG for the player and then a Find Object, you can search for that tag. 

#2 If you only have one player the wolfs need to track, I'd use a global game object variable that is the player and use that to reference for the wolfs.  The wolfs can use a simple Get position action on that game object but this only works if you got one character to track.

#3 Have the player store its location every frame in an FSM.  Then the wolfs can use the Get FSM Vector2 action whenever they want to know where the player is.

Without knowing exactly how your FSM are working I can't really say the best solution but hopefully these ideas can help you out.

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
Re: How to have prefabs reference game objects without global variables?
« Reply #2 on: November 13, 2018, 12:08:06 AM »
Hi,

 you can also broadcast an event if you know all the interested fsm are live and running. Your player can send "HELLO IT IS ME" global event and you use the action Get Event Info to know the sender GameObject.

 Bye,

 Jean

Snowbird

  • Playmaker Newbie
  • *
  • Posts: 25
Re: How to have prefabs reference game objects without global variables?
« Reply #3 on: November 13, 2018, 12:34:47 AM »
Cool thanks for the ideas guys. I'll try them out tomorrow and get back if I have any questions still.

Thore

  • Sr. Member
  • ****
  • Posts: 480
Re: How to have prefabs reference game objects without global variables?
« Reply #4 on: November 13, 2018, 05:06:20 PM »
Another method is to use a kind of singleton approach: have one “Game Manager” game object with an FSM that can store variables. Now everything of import can find the manager and store itself (or some other variable) into the game manager. This hinges on the fact that you know, and take for granted, that this game manager definitely exists in the scene, under a fixed name or tag, and thus can always be found, even if everything else changes dynamically. Now the wolf can get the reference from the Game Manager.

However, it many situations its better to keep parts self sufficient, i.e. make the wolf find player by tag, by name etc. You can also use a game object under the player to store a tag when you need the player holder to use a different tag. Then you find that child object, and then its parent etc.
« Last Edit: November 13, 2018, 05:12:47 PM by Thore »

Snowbird

  • Playmaker Newbie
  • *
  • Posts: 25
Re: How to have prefabs reference game objects without global variables?
« Reply #5 on: November 25, 2018, 03:51:28 AM »
Another method is to use a kind of singleton approach: have one “Game Manager” game object with an FSM that can store variables. Now everything of import can find the manager and store itself (or some other variable) into the game manager. This hinges on the fact that you know, and take for granted, that this game manager definitely exists in the scene, under a fixed name or tag, and thus can always be found, even if everything else changes dynamically. Now the wolf can get the reference from the Game Manager.

Okay this is a good idea. However, what if I have a projectile prefab that collides with an enemy prefab and there needs to be a complicated damage formula that the game manager needs to do?

Both (the projectile and the enemy) are prefabs and both can't send events to the game manager when the collision occurs. So how can I get the game manager to know about the collision to do the damage calculation and subtract HP from the right enemy?

I might be able to do jeanfabre's suggestion but it doesn't sound like the kind of thing I want to be doing all the time, in some cases multiple times a second. Or am I wrong about that?

(bonus question: this isn't exactly related, but what happens if 2 enemies get hit at once? What problems are likely to occur?)

waveform

  • Playmaker Newbie
  • *
  • Posts: 28
Re: How to have prefabs reference game objects without global variables?
« Reply #6 on: November 25, 2018, 07:41:05 AM »
in my case, i dont use prefab at all, because prefab cant store gameobject reference, so i just simply create a gameobject in scene then give it name "Prefab", unactive it,now i just put all gameobject as child of this "Prefab" object and re use them as prefab,the only situation i use unity prefas is then it`s only a model

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7615
    • jinxtergames
Re: How to have prefabs reference game objects without global variables?
« Reply #7 on: November 25, 2018, 11:27:59 AM »
Hi,
What i usually do is :
Have a gameobject variable on the prefab (called gamemanger for example)
Then when i create or spawn the prefab @ runtime, store the created/spawned object.
Then use a 'set fsm gameobject' and store the object that needs the reference.

Snowbird

  • Playmaker Newbie
  • *
  • Posts: 25
Re: How to have prefabs reference game objects without global variables?
« Reply #8 on: November 25, 2018, 08:29:56 PM »
Hi,
What i usually do is :
Have a gameobject variable on the prefab (called gamemanger for example)

Okay, just to make sure I understand. The prefab in question, in one of its FSM's, will have a gameobject variable called "gamemanager". (or another name I see fit)

Quote
Then when i create or spawn the prefab @ runtime, store the created/spawned object.

Okay, so lets say at runtime I spawn 5 arrows (projectile), deactivated, ready to be used when the character fires an arrow as part of my pooling system. However, this is where I am confused @ what you are saying.

I want to, when these arrows are created, "store the created/spawned object"? Like store it in the gameobject variable called "gamemanager" that I just created? How do I do that if the instance of the prefab doesn't exist yet? Also I am going to have 5 of them.


Quote
Then use a 'set fsm gameobject' and store the object that needs the reference.

This part I am having difficulty understanding as well. I will still have the same problem of trying to edit an FSM that the prefab can't reference, will I not?


Sorry I am having difficulty understanding this. I figured I was doing so well but am pretty confused again. Been trying at it for a long time in Unity and can't figure it out. I really appreciate the help.

Athin

  • Full Member
  • ***
  • Posts: 163
Re: How to have prefabs reference game objects without global variables?
« Reply #9 on: November 25, 2018, 11:35:45 PM »
So just as an example, what would be a way to get a prefab wolf to know the exact location of the player, at anytime, without using global variables? The wolf doesn't need to know this the second it is created, but needs to know this during combat. 2d btw.

Any help is much appreciated.

Going back to the start on this one.

All you simply need for this is have the player have a tag of "Player" or whatever you like to call it.  Then on the wolf prefab,  whenever it needs to find the player do the Find Game object action with the tag filter of "Player".  Then you will have the player as a Game object variable to then use the Get Position Action.

I think you might be over thinking the problem a bit and getting confused on the process but if the example above is what you need,  the answer above should work fine.

Let me know if you still need help though.

Snowbird

  • Playmaker Newbie
  • *
  • Posts: 25
Re: How to have prefabs reference game objects without global variables?
« Reply #10 on: November 26, 2018, 01:31:52 AM »


Going back to the start on this one.

All you simply need for this is have the player have a tag of "Player" or whatever you like to call it.  Then on the wolf prefab,  whenever it needs to find the player do the Find Game object action with the tag filter of "Player".  Then you will have the player as a Game object variable to then use the Get Position Action.

I think you might be over thinking the problem a bit and getting confused on the process but if the example above is what you need,  the answer above should work fine.

Let me know if you still need help though.

Yeah I got that one solved a while ago, and your solution was the one I ended up using. My problem now is I need instances of prefabs to communicate certain things to objects in the scene. (such as collision info, variables on the prefab instances, etc. I got 2 answers but I can't figure one of them out, and the other solution offered of just "not using prefabs" probably won't work for this project very well)
« Last Edit: November 26, 2018, 01:33:53 AM by Snowbird »

Athin

  • Full Member
  • ***
  • Posts: 163
Re: How to have prefabs reference game objects without global variables?
« Reply #11 on: November 26, 2018, 03:31:09 AM »
Ah sorry was at work and thought you had the same issue happening. 

So if I understand the problem correctly, you want to be able to detect if a projectile hits the target and when it does do "X"math depending on what got hit?

If thats the case you can try what I like to do in these cases. I assign an 'Armor ID' int value on anything that will be effected by the bullet (Think as 0=light armor, 1=heavy armor ect...).  Then I'd make a empty game object (We'll call it Battle Manager) that handles all the math when something gets hit. Once I do that I'd use a trigger event on a bullet with a tag filter to detect anything it hits.

When the bullet hits a target, I send the game object var it hit to the Battle Manager using the Set FSM Game Object action.  The Battle manager now knows who he needs to look at and will now use the Get FSM Int Action to find out his Armor ID.  A simple Int Switch from there will then determine the formula to use and once its done its calculations, it will then send the info back to the object that got it. 

That may be way more complex then what you actually need but I figured that you might be able to use some of that to help with your problem.  Hopefully I've helped out and not confused ;)   

Thore

  • Sr. Member
  • ****
  • Posts: 480
Re: How to have prefabs reference game objects without global variables?
« Reply #12 on: November 26, 2018, 06:27:32 AM »
For projectiles, use the pair of Set Event Data on the sender and Get Event Info on the receiver.

Brief: There is some condition (collision, trigger etc), and the sender knows about the receiver. Then, the sender sends an event over to the receiver, let’s say “HIT”. The receiver starts up, and with get event info reads a package of variables, like how much damage, from whom and so on.

Example. The weapon spawns (or switches on, or takes from pool) a damage dealer object, let’s call that projectile (it doesn’t have to fly around, can also be the sword blade, or invisible object that only does the mechanics, while it looks whatever you like).

This projectile has some mechanics on it to make it move, shoot, fall down, or may do nothing at all. In any case, make a standalone state not connected to any other state. Then add a global event to it, and from the system event list pick On Collision Enter or On Trigger Enter. Depending on what you use. Also beware, the if you specifically use 2D physics, you always need to pick the corresponding 2D actions. That means, when it hits, or something passes through it, it will then start the new unconnected state and go from there.

In this state, you place the Set Event Data, and a Send Event. The data contains the values you want to ship over, and the send event is to let the target know, so it picks up that data. Send Event uses a global event, let’s call this “HIT”

Now the target has a health FSM. Inside, it also has a state with a global event, that waits for “HIT”. Then, place Get Event Info, which makes it pick up the event data from the projectile.

Next, you want to process the data and run it through damage formula. The easiest is to substract from current health points. But you can add modifers before etcetera. After that you want to check if health is left and if not, do the death and despawn/respawn etc. If it was just a scratch, and everything is done, make sure to NULL out the variables that were used, i.e. set them to contain no relevant data to prevent that leftovers create bugs the next time.

Thore

  • Sr. Member
  • ****
  • Posts: 480
Re: How to have prefabs reference game objects without global variables?
« Reply #13 on: November 26, 2018, 06:39:26 AM »
Also, when you want to use armor types or resistances etc, you can store the type in a string in event data. Then on the receiver, before damaga calculation, do a string switch that then leads it through the desired formula.

A more robust way is with Enums though, but that’s currently not directly possible with this approach. The target could however get an fsm enum from the projectile, if that action exists. Then you are sure to work with standardised categories.

Generally though: the projectile should not care about what the target does with the info. It should simply say: you got hit by me, I deal 23 damage of type fire.

The target then says, kthxbye, checks if “fire” means anything to it, and if it does, “haha, I am 50% resistant to fire!” take the damage and multiply it by 0.5. And if it takes twice fire damage, multipy it with 2 and so on.
« Last Edit: November 26, 2018, 06:43:56 AM by Thore »

Snowbird

  • Playmaker Newbie
  • *
  • Posts: 25
Re: How to have prefabs reference game objects without global variables?
« Reply #14 on: November 26, 2018, 04:05:30 PM »
When the bullet hits a target, I send the game object var it hit to the Battle Manager using the Set FSM Game Object action.

This is my entire question. I can't communicate to the battle manager because the projectile and the enemy are both prefabs.

Let me try and explain the situation in full, as you guys are trying to help me with stuff that I've already done and solved a while ago, and then brushing over the part that I don't understand.

We have 4 things:
Character - not prefab - has attributes like strength and agility that should affect arrow damage
Battle Manager - not prefab - takes in attributes from player, arrow projectile prefab, and wolf enemy prefab, does a calculation using the variables from all 3 of those, and then spits a number to the wolf enemy
Arrow Projectile - prefab - has a damage variable
Wolf Enemy - prefab - has a health variable and a physical resist variable


-Character creates an arrow.
-Arrow flies at enemy and collides with enemy
-Battle manager would now like to know of this collision, and grab information from the character, the arrow, and the wolf
-Battle manager does a calculation and sends that number to the wolf
-The wolf subtracts its health equal to the number sent to it by the battle manager

So as you see, I can do all this very easily enough. It is no problem for me. The problem occurs when I make the wolf and arrow into prefabs. Now I don't know how to communicate to the battle manager. Another thing to consider is there could be many arrow instances and many wolf instances all spawned from the same prefab, as well as tons of different types of attacks and tons of different types of enemies, making it nice to be able to use the same battle manager for everything.

(something I could do is store all this type of information in the scene, such as arrow damage, wolf armor, etc. but then I still need the battle manager to know of the collision that occurs and also how to send information to a specific instance of a prefab)
« Last Edit: November 26, 2018, 04:14:39 PM by Snowbird »