#pass data from scenes

1 messages · Page 1 of 1 (latest)

covert quest
#

could you explain that a bit further? I am having trouble to follow along with your idea a bit, sorry

short lynx
#

e.g.

public class Player : MonoBehaviour
{
    public static Player Player;

    public PlayerHealth health;
    //other components

    public void Awake()
    {
        if (Player == null) Player = this;
        else Destroy(gameObject);
    }
}
#

known as the "Singleton" pattern

covert quest
#

thanks for your time, I guess I will have to read what that is.
I appreciate your help :)

short lynx
#

np. The other way is some single manager script that handles passing the player reference into a scene once it loads:
e.g. GameManager loads scene, Finds some "SceneManager" component and gives it the player instance.
Then SceneManager can either provide it to other components, or others grab it from SceneManager.

if done this way, wait a frame before doing Find() to locate the Scene specific script.

covert quest
#

yeah in my research I came across the Find() solution, but I had heard somewhere that Find() is not good or something so I stayed away from it

short lynx
#

Id say its fine if used a singlular time when you loaded a new scene such as what i describe above.
If we limit it to that single instance then its not soo bad. You can also get the root objects of a newly loaded scene and find it amongst those.

covert quest
#

yeah that wouldnt really work, as every object that damages the player would need to use that. That doesn't sound that good to me

short lynx
#

The difference is one is easy but less flexible, the second way where a reference is passed more manually is harder but allows for easier testing and refactoring later.
It can be made easier if you just have a way to quickly grab and make a list of stuff to Init() and give dependencies to in your single scene script.
Many projects i work on use this approach.

#

You can look into dependency injection frameworks to do this stuff for you but tbh just pick what you want for now if you are learning stuff

covert quest
#

alright, I will look into that, thanks

covert quest
# short lynx The difference is one is easy but less flexible, the second way where a referenc...

sorry to bother you, but I am still having trouble with this.
I tried with the singleton pattern, but the field where I would add the Player GameObject in the Editor of the other scene is empty.
There is a unity forum post that explains my issue perfectly, but once again, I could not make their solution work.
https://discussions.unity.com/t/assigning-object-references-across-several-scenes-with-dontdestroyonload/800909

Is there any chance you could provide further help to me?
Thanks in advance :)

short lynx
#

The objects that depend on the player should not have a Serialized ref to it but instead either update their ref on scene load with the correct player instance or have them ref some script that manages the scene where the player reference can be updated.

E.g. Scene manager has a player reference, enemies and other things all ref scene manager to get the player.
On scene loads you tell the scene manager instance "this is the player reference, store it!"

#

I should remind you again the singleton pattern for the player also solves this.

#

Ofc don't do something like have each component find the player as that would be inefficient doing like 50+ finds.

covert quest
short lynx
#

what is "reference" in this case?

covert quest
#

give me a minute so I can provide further screenshots to be able to clarify it a bit better

short lynx
#

there isnt much more i can say, you just need to handle the dependencies better to support going between many scenes

covert quest
#

Scene A has the Player GameObject with the PlayerHealth script attached to it.
When I unload Scene A and load Scene B I have set the Player GameObject to DontDestroyOnLoad.
The PlayerHealth script has a function called TakeDamage which I want to call from a GameObject in Scene B

//inside of PlayerHealth script
public void TakeDamage(float damage)
{
    health -= damage;
    lerpTimer = 0f;
    durationTimer = 0;
    overlay.color = new Color(overlay.color.r,overlay.color.g,overlay.color.b,1);
}
//Script in Scene B
public class DamagePlayer : MonoBehaviour
{
    public PlayerHealth playerhealth;

    // Start is called before the first frame update
    void Start()
    {
        playerhealth.TakeDamage(20);
    }
}

What I mean by not being able to set the reference is in the editor of Scene B I can not select the Player, as he is in a different scene

short lynx
#

Yea you just cannot do this

covert quest
#

I did try with the Singleton pattern in the PlayerHealth script, but I still wasn't able to call the TakeDamage function in the DamagePlayer script

short lynx
#

No that will work, if the Player instance is stored in a static field, it should be usable anywhere (as long as you dont change it later)

#

What i explained earlier is you need to either do the singleton pattern correctly or give this DamagePlayer script the Player/PlayerHealth instance on the scene load.

covert quest
#

So this would be a correctly implemented singleton pattern?

public class PlayerHealth : MonoBehaviour
{

    public static PlayerHealth Instance;


    private static float health;
    private float lerpTimer;
    [Header("Health Bar")]
    public float maxHealth = 100f;
    public float chipSpeed = 2f;
    public Image frontHealthBar;
    public Image backHealthBar;

    [Header("Damage Overlay")]
    public Image overlay;
    public float duration;
    public float fadeSpeed;

    private float durationTimer;


    public void Awake()
    {
        if(Instance == null) Instance = this;
        else Destroy(gameObject);
    }```
short lynx
#

yes

#

You can then use PlayerHealth.Instance else where

covert quest
#

That means now I should be able to just say PlayerHealth.Instance.TakeDamage?

short lynx
#

Id handle things like this: (where a central service passes around the player instance)

covert quest
#

YES IT FINALLY WORKED

#

I was just incredibly stupid and using Instance.TakeDamage the entire time instead of PlayerHealth.Instance.TakeDamage

short lynx
#

static fields are accessed via the Type name as they do not belong to an instance

covert quest
#

My Guy thank you so much

#

This is incredible

#

I have been stuck on this for ages

short lynx
covert quest
#

Alright, will do

#

And thanks again