Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How can I destroy the player than bring her back at the same point?

Discussion in '2D' started by Cobble, Nov 11, 2016.

  1. Cobble

    Cobble

    Joined:
    May 9, 2015
    Posts:
    33
    Hi! I made a script that loads and additive level, then unloads that additive level once you beat it. However, the player in Scene A seems to be moving at the same time as the player in Scene B. Is there any way to destroy the player in Scene A, and bring her back once you beat Scene B? I've been trying to figure this out for hours but I can't seem to get anything to work. Thanks!
     
  2. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    Could you set the gameobject to inactive and then back to active?
     
  3. Cobble

    Cobble

    Joined:
    May 9, 2015
    Posts:
    33
    How would I go about doing that? I've searched online and I'm able to set the player to inactive, but I can't set her back to active.
     
  4. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    Something in the scene will need a reference to that object to do that. Perhaps whatever is doing the level switching will have a GameObject variable and store a reference to the player before switching. Then use player.gameObject.SetActive(false), and switch the scene. Then when returning to the other scene, use player.gameObject.SetActive(true).
     
  5. Cobble

    Cobble

    Joined:
    May 9, 2015
    Posts:
    33
    I tried doing that, but I got this error.

    error CS0103: The name `player' does not exist in the current context
     
  6. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    "player" would be a variable that you add to the class, and assign on Start, or before the scene changes. It's what will hold the reference to the player. You'll have to do a FindObjectOfType<PlayerScript>(), or a GameObject.FindObjectWithTag("PlayerTag"), or a GameObject.Find("PlayerName") to get a reference to the player. If the player exists in the scene beforehand, you can make the variable public and drag the player into the inspector for that component.
     
    Last edited: Nov 11, 2016
  7. Cobble

    Cobble

    Joined:
    May 9, 2015
    Posts:
    33
    I can't figure it out. I'm new to coding. Here are the original scripts to load and unload the mini game.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class LoadMini : MonoBehaviour {
    6.  
    7.  public string loadLevel;
    8.  
    9.  void OnTriggerEnter2D(Collider2D other) {
    10.  
    11.  if (other.gameObject.name == "Scarlet")
    12.  {
    13.  Debug.LogError("Collisiondetected,TryingtoLoad");
    14.  SceneManager.LoadScene(loadLevel, LoadSceneMode.Additive);
    15.  Destroy (gameObject);
    16.  }
    17.  }
    18. }
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class UnloadMini: MonoBehaviour {
    6.  
    7.  public string unloadLevel;
    8.  
    9.  IEnumerator OnTriggerEnter2D(Collider2D other) {
    10.  
    11.  if (other.gameObject.name == "Scarlet")
    12.  {
    13.  Debug.LogError ("Collisiondetected,TryingtoUnload");
    14.  yield return new WaitForEndOfFrame ();
    15.  SceneManager.UnloadScene (unloadLevel);
    16.  }
    17.  }
    18. }
     
  8. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
  9. Cobble

    Cobble

    Joined:
    May 9, 2015
    Posts:
    33
    I think I did it right, but I'm getting this error

    error CS1061: Type `string' does not contain a definition for `gameObject' and no extension method `gameObject' of type `string' could be found (are you missing a using directive or an assembly reference?)

    Here are my new scripts.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class LoadMini : MonoBehaviour {
    6.  
    7.  public string loadLevel;
    8.  public string Player;
    9.  
    10.  void Start () {
    11.  
    12.  Player.gameObject.SetActive (false);
    13.  
    14.  }
    15.  
    16.  
    17.  void OnTriggerEnter2D(Collider2D other) {
    18.  
    19.  if (other.gameObject.name == "Scarlet")
    20.  {
    21.  Debug.LogError("Collisiondetected,TryingtoLoad");
    22.  SceneManager.LoadScene(loadLevel, LoadSceneMode.Additive);
    23.  }
    24.  }
    25. }
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class UnloadMini: MonoBehaviour {
    6.  
    7.  public string unloadLevel;
    8.  public string Player;
    9.  
    10.  void Start () {
    11.  
    12.  Player.gameObject.SetActive (true);
    13.  
    14.  }
    15.  
    16.  
    17.  IEnumerator OnTriggerEnter2D(Collider2D other) {
    18.  
    19.  if (other.gameObject.name == "Scarlet")
    20.  {
    21.  Debug.LogError ("Collisiondetected,TryingtoUnload");
    22.  yield return new WaitForEndOfFrame ();
    23.  SceneManager.UnloadScene (unloadLevel);
    24.  }
    25.  }
    26. }
     
  10. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    The player variable is of the type "string", a series of characters (like "bob") and you cannot get a gameobject from a string. You should have the player variable be of type "GameObject" and assign the players gameobject. Like this:

    Code (csharp):
    1. public GameObject Player;
    One simple way to do that is
    Code (csharp):
    1. Player = GameObject.Find ("MyPlayerGameobjectName");
    Or alternatively you could just drag and drop the player gameobject through the inspector.

    Later when you do setactive use
    Code (csharp):
    1. Player.SetActive (false);
    I'd recommend you do this work from a single script instead of two, and not attached to the player as it will get disabled with the gameobject. Attach it to a game master object or something along those lines, that gets maintained between scenes.

    It seems you use the start method of two different scripts so I would just instead, have a couple methods called "EnablePlayerGO()" and "DisablePlayerGO()" or something, and use those as publicly accessible ways to enable and disable the player, from some management script.
     
    Last edited: Nov 12, 2016
  11. Cobble

    Cobble

    Joined:
    May 9, 2015
    Posts:
    33
    I tried that. The player disappears, but when it's time for her to come back, she doesn't. Here are my scripts.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class LoadMini : MonoBehaviour {
    6.  
    7.  public string loadLevel;
    8.  public static GameObject Player;
    9.  
    10.  void Start () {
    11.  
    12.  
    13.  }
    14.  
    15.  
    16.  void OnTriggerEnter2D(Collider2D other) {
    17.  
    18.  if (other.gameObject.name == "Scarlet")
    19.  {
    20.  Debug.LogError ("Collisiondetected,TryingtoLoad");
    21.  SceneManager.LoadScene(loadLevel, LoadSceneMode.Additive);
    22.  Player = GameObject.Find ("Scarlet");
    23.  Player.SetActive (false);
    24.  }
    25.  }
    26. }
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class UnloadMini: MonoBehaviour {
    6.  
    7.  public string unloadLevel;
    8.  public static GameObject Player;
    9.  
    10.  void Start () {
    11.  
    12.  
    13.  }
    14.  
    15.  
    16.  IEnumerator OnTriggerEnter2D(Collider2D other) {
    17.  
    18.  if (other.gameObject.name == "Scarlet")
    19.  {
    20.  Debug.LogError ("Collisiondetected,TryingtoUnload");
    21.  yield return new WaitForEndOfFrame ();
    22.  SceneManager.UnloadScene (unloadLevel);
    23.  Player = GameObject.Find ("Scarlet");
    24.  Player.SetActive (true);
    25.  }
    26.  }
    27. }
     
  12. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    Ok your making some pretty basic mistakes here that your missing, so it'd really be better for you to take a break from this, and go take many more basic tutorials to figure out the basics of c# and object oriented programming.

    Once you learn some more stuff this will be easier for you to get done.

    For one thing, you don't find the gameobject in the trigger entry part, usually you do that in Start () or Awake ().
     
  13. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
  14. Cobble

    Cobble

    Joined:
    May 9, 2015
    Posts:
    33
    This is what my scripts look like right now. Although the player disappears, she's not coming back.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class LoadMini : MonoBehaviour {
    6.  
    7.  public string loadLevel;
    8.  public GameObject Player;
    9.  
    10.  void Start () {
    11.  
    12.  Player = GameObject.Find ("Scarlet");
    13.  
    14.  }
    15.  
    16.  
    17.  void OnTriggerEnter2D(Collider2D other) {
    18.  
    19.  if (other.gameObject.name == "Scarlet")
    20.  {
    21.  Debug.LogError ("Collisiondetected,TryingtoLoad");
    22.  SceneManager.LoadScene(loadLevel, LoadSceneMode.Additive);
    23.  Destroy (gameObject);
    24.  Player.SetActive (false);
    25.  }
    26.  }
    27. }
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class UnloadMini: MonoBehaviour {
    6.  
    7.  public string unloadLevel;
    8.  public GameObject Player;
    9.  
    10.  void Start () {
    11.  
    12.  Player = GameObject.Find ("Scarlet");
    13.  
    14.  }
    15.  
    16.  
    17.  IEnumerator OnTriggerEnter2D(Collider2D other) {
    18.  
    19.  if (other.gameObject.name == "Scarlet")
    20.  {
    21.  Debug.LogError ("Collisiondetected,TryingtoUnload");
    22.  yield return new WaitForEndOfFrame ();
    23.  SceneManager.UnloadScene (unloadLevel);
    24.  Player.SetActive (true);
    25.  }
    26.  }
    27. }
     
  15. Hyblademin

    Hyblademin

    Joined:
    Oct 14, 2013
    Posts:
    725
    Is Scarlet part of the scene that you're unloading? If it is, it will be deleted when you call the unload. Any chance this is causing an issue? Seems like it maybe isn't, but I wanted to check. Did you check the inspector to make sure it wasn't being reactivated?
     
    Last edited: Nov 15, 2016
  16. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    Why do this in two separate scripts?
     
  17. Cobble

    Cobble

    Joined:
    May 9, 2015
    Posts:
    33
    It's hard to explain.

    When Scarlet loads the additive scene by colliding with an enemy, she must complete a mini game. At the end of the mini game, the additive scene is unloaded. When the mini game is loaded, Scarlet disappears. I'm trying to make it so that she comes back once the additive scene is unloaded.

    If you're wondering, in the game, you must kill enemies by beating their mini games.
     
  18. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    Ok, so Scarlet is the player character then? Why do you do this work in two separate scripts? Lol I keep asking this :p

    I say that because like, that whole "enable" and "disable" of the player character should occur in some SINGLE management script, and be called on when needed from other more "situational" scripts that go off when a mini game starts or whatever.

    If it were on a single script, you could do one single call to find the gameobject (you should avoid doing gameobject.find too much) of the player, then just enable or disable it as needed from the same script.

    You could have a method called "DisableScarlet()" and "EnableScarlet()" which could be publicly accessible and if your doing it on a management script, the manager would probably have a static instance for itself (like GameMaster._Instance variable of a static "GameMaster.cs" class to access easily) that you could use to easily make those enable and disable calls from anywhere..

    You could then have a script attached to the player which loads the additive scene right... and it would look for that to happen, then tell "gamemaster._instance" or whatever to either enable, or disable the player object.

    You see what I am saying? Why do this in two separate scripts and have to "Find" the player twice for no real benefit, when it is simpler to just have them do it in one place and one place only, and just call on it from other places....

    I hope that all makes sense, haha.
     
  19. Hyblademin

    Hyblademin

    Joined:
    Oct 14, 2013
    Posts:
    725
    @Cobble

    That makes sense, just making sure that Scarlet wasn't an object in the additive scene. However, I'd still like you to check the inspector to make sure that the object isn't being reactivited (trying to consider all possibilities-- did the object get moved somehow without you knowing?)

    I do agree with MD_Reptile; it's probably best for maintainability to do this in one script. It's technically not necessary, but it does help cut down on tracing problems like this to their sources.

    Here's another question for you, regarding this:

    Code (CSharp):
    1. IEnumerator OnTriggerEnter2D(Collider2D other) {
    2.  
    3. if (other.gameObject.name == "Scarlet")
    4. {
    5.         //...
    6.         Player.SetActive (true);
    7. }
    8.  
    9. }
    If Scarlet is disabled before this runs, then how does it enter this trigger? Is Scarlet still active when you call GameObject.Find()?
     
  20. Cobble

    Cobble

    Joined:
    May 9, 2015
    Posts:
    33
    The additive scene has a separate Scarlet.

    Also, how would I go about combining my two scripts? I've tried to do it, but it's not working.
     
  21. Hyblademin

    Hyblademin

    Joined:
    Oct 14, 2013
    Posts:
    725
    If the additive scene has its own Scarlet while the original one is disabled, and the unload script is in that scene, then you're probably getting a reference to additive Scarlet when you use GameObject.Find(); when you go to reactivate Scarlet, nothing happens because you have the wrong Scarlet, and it's about to be unloaded anyway.

    Since you're already checking to see if Scarlet is the object entering the trigger, you can just use other.gameObject as the reference to the player object before the scene loads. Use this same reference when you reactivate the object.

    You can combine the scripts by making two methods in one script, where one loads the new scene and one unloads it. Use the scripts on the trigger objects to call these methods. If you don't want to do it like this, you'll have to pass the reference to "main" Scarlet to the unload script in some way.

    Do you have a game manager or controller object? It might be a good idea to keep a static reference to the player in there.
     
    Last edited: Nov 21, 2016