Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Getting transforms of objects in other scenes?

Discussion in 'Scripting' started by ATLAS-INTERACTIVE, Dec 27, 2014.

  1. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    About a week ago now, I was tasked to create a Skyrim functioning door system, where you could give the script the player object, a new scene, and an object name, and it load the new level without destroying the character, find the object via its name and send the player to that objects transform, I think I am about half way there, but not sure.
    As I am a 3D artist, I had to do my best with the limited scripting knowledge I had.

    Can anyone help me complete this? All help is hugely appreciated.

    P.S. For anyone who manages to get this working how I need it to, will get a date driven event system for stuff like timed Christmas, New Years and Easter objects, if they want it.

    Code (JavaScript):
    1. #pragma strict
    2.  
    3. var PlayerCharacter : Transform;
    4. var SpawnPoint : String = "";
    5. private var drawGUI = false;
    6. var Spawner : Vector3;
    7. var NewScene : String = "";
    8. var toText : String = "";
    9.  
    10. function Update ()
    11. {
    12. if (drawGUI == true && Input.GetKeyDown(KeyCode.F))
    13. {
    14.      LoadNewScene();
    15. }
    16. }
    17.  
    18. function OnTriggerEnter (theCollider : Collider)
    19. {
    20.     if (theCollider.tag == "Player")
    21.     {
    22.         drawGUI = true;
    23.     }
    24. }
    25.  
    26. function LoadNewScene ()
    27. {
    28.     DontDestroyOnLoad(PlayerCharacter);
    29.     Application.LoadLevel(NewScene);
    30.     yield WaitForSeconds (0.2);
    31.     Spawner = GameObject.Find(SpawnPoint).transform.position;
    32.     //Vector3 position = Spawner.transform;
    33.     PlayerCharacter.transform.Translate(Spawner);
    34.    
    35. }
    36.  
    37. function OnGUI()
    38. {
    39.     if (drawGUI == true)
    40.     {
    41.         //GUI.Label (Rect (Screen.width*0.5-0, 200, 120, 22), "Press F to open to");
    42.         //GUI.Label (Rect (Screen.width*0.5-35, 220, 150, 22), toText);
    43.        
    44.     //GUI.color = new Color(1,1,1,1.0f);
    45.     GUI.skin.box.fontSize=15;
    46.     GUI.backgroundColor = Color(0, 0, 0, 0);
    47.     GUI.BeginGroup (Rect (Screen.width / 2 - 75, Screen.height / 2 - 0, 150, 50));
    48.  
    49.     GUI.Box (Rect (0,0,150,25), "Press F to open to");
    50.     GUI.Box (Rect (0,22,150,25), toText);
    51.    
    52.     GUI.EndGroup ();
    53.     }
    54. }
    55.  
    56. function OnTriggerExit (theCollider : Collider)
    57. {
    58.     if (theCollider.tag == "Player")
    59.     {
    60.         drawGUI = false;
    61.     }
    62. }
     
  2. Sbizz

    Sbizz

    Joined:
    Oct 2, 2014
    Posts:
    250
    You're using a coroutine without using StartCoroutine (I don't know if it is necessary with UnityScript ??).

    Also, you should use the event "OnLevelWasLoaded" if you want to teleport the player when the level is loaded. Currently, you're trying to get a spawn even if the level was not loaded.. so it can fail.

    - in your LoadNewScene function, remove everything from "yield WaitForSeconds (0.2)".
    - create a game object "Spawn" in your new scene (where the player should be) and assign it a script (SpawnSpot ?)
    - within "OnLevelWasLoaded", find the player character and teleport him to the current position.

    Your player character must have something unique if you want to find him (tag ? game object name ? a component ?).
     
  3. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    I don't think in this instance I need to state a StartCoroutine, and this provides no errors.
    The player is the only object with the tag Player, why do I need a script on Spawn and what needs to go in it?
     
  4. Sbizz

    Sbizz

    Joined:
    Oct 2, 2014
    Posts:
    250
    If you don't use StartCoroutine, how do you start your Coroutine ? Put a Debug.Log in "LoadNewScene", the function will not be executed because you didn't use StartCoroutine (I just checked on Unity Documentation, I wasn't sure you need to use StartCoroutine with UnityScript but it appears you have to use it). And yes, if you try to launch a Coroutine without using StartCoroutine, no error will be displayed, I don't know why..

    Edit: Nevermind ! I didn't read the entire description.. "When using JavaScript it is not necessary to use StartCoroutine, the compiler will do this for you. When writing C# code you must call StartCoroutine.". Anyway, in C#, no error is displayed if you don't call StartCoroutine.

    I told you what your Spawn game object needs to do : implement the event "OnLevelWasLoaded" (find the player using his tag and teleport it to the Spawn position).
     
  5. fire7side

    fire7side

    Joined:
    Oct 15, 2012
    Posts:
    1,819
    I think you would only want to use DontDestroyOnLoad one time. I do this in an init scene in an awake and then load the next scene in the start. If you put it all over the place and the player returns to the level, you will have two players. I don't know about the door you are talking about, never played Skyrim.
     
  6. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    in the main world (outside) we will be having multiple doors to other locations, how do i determine one from the other if I am only using find via component for the spawn point?
     
  7. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    So far, I have this.
    The only problem is when it goes to print the objects coords, it prints the location of another object with that script on, instead of the object named in the script.

    Code (JavaScript):
    1. #pragma strict
    2.  
    3. var PlayerCharacter : Transform;
    4. var Player;
    5. var SpawnPoint : String = "";
    6. private var drawGUI = false;
    7. var Spawner;
    8. var SpawnerPos;
    9. var NewScene : String = "";
    10. var toText : String = "";
    11.  
    12. function Update ()
    13. {
    14. if (drawGUI == true && Input.GetKeyDown(KeyCode.F))
    15. {
    16.      LoadNewScene();
    17. }
    18. }
    19.  
    20. function OnTriggerEnter (theCollider : Collider)
    21. {
    22.     if (theCollider.tag == "Player")
    23.     {
    24.         drawGUI = true;
    25.     }
    26. }
    27.  
    28. function LoadNewScene ()
    29. {
    30.     DontDestroyOnLoad(PlayerCharacter);
    31.     Application.LoadLevel(NewScene);
    32.    
    33. }
    34.  
    35. function OnLevelWasLoaded ()
    36. {
    37.     Player = GameObject.FindGameObjectsWithTag ("Player");
    38.     Spawner = GameObject.Find (SpawnPoint);
    39.     SpawnerPos = transform.position;
    40.     Debug.Log (SpawnerPos);
    41. }
    42.  
    43. function OnGUI()
    44. {
    45.     if (drawGUI == true)
    46.     {
    47.         //GUI.Label (Rect (Screen.width*0.5-0, 200, 120, 22), "Press F to open to");
    48.         //GUI.Label (Rect (Screen.width*0.5-35, 220, 150, 22), toText);
    49.        
    50.     //GUI.color = new Color(1,1,1,1.0f);
    51.     GUI.skin.box.fontSize=15;
    52.     GUI.backgroundColor = Color(0, 0, 0, 0);
    53.     GUI.BeginGroup (Rect (Screen.width / 2 - 75, Screen.height / 2 - 0, 150, 50));
    54.  
    55.     GUI.Box (Rect (0,0,150,25), "Press F to open to");
    56.     GUI.Box (Rect (0,22,150,25), toText);
    57.    
    58.     GUI.EndGroup ();
    59.     }
    60. }
    61.  
    62. function OnTriggerExit (theCollider : Collider)
    63. {
    64.     if (theCollider.tag == "Player")
    65.     {
    66.         drawGUI = false;
    67.     }
    68. }
     
  8. Sbizz

    Sbizz

    Joined:
    Oct 2, 2014
    Posts:
    250
    Okay, so there is a problem if you have several spawns. You should use DontDestroyOnLoad on the trigger too ;

    Code (JavaScript):
    1. var PlayerCharacter : Transform;
    2. var SpawnPoint : String = "";
    3. var NewScene : String = "";
    4.  
    5. private var drawGUI = false;
    6. private var hasToBeDestroyed = false;
    7.  
    8. function Update ()
    9. {
    10.     if (drawGUI == true && Input.GetKeyDown(KeyCode.F))
    11.     {
    12.          LoadNewScene();
    13.     }
    14. }
    15. function OnTriggerEnter (theCollider : Collider)
    16. {
    17.     if (theCollider.tag == "Player")
    18.     {
    19.         drawGUI = true;
    20.     }
    21. }
    22. function LoadNewScene ()
    23. {
    24.     // Don't destroy the player
    25.     DontDestroyOnLoad(PlayerCharacter);
    26.  
    27.     // Don't destroy this trigger because we want it to handle the teleportation of the player
    28.     DontDestroyOnLoad(gameObject);
    29.  
    30.     // When the level will be loaded, we must know which trigger has to be destroyed
    31.     hasToBeDestroyed = true;
    32.  
    33.     // Load the new scene ; a room or "outside"
    34.     Application.LoadLevel(NewScene);
    35. }
    36.  
    37. // Called once the level is fully loaded
    38. function OnLevelWasLoaded ()
    39. {
    40.     if (hasToBeDestroyed)
    41.     {
    42.         // We need to find the right spawn point (so it MUST have a unique name)
    43.         var spawner = GameObject.Find (SpawnPoint);
    44.  
    45.         // Teleport the player to the spawn point
    46.         PlayerCharacter.position = spawner.transform.position;
    47.  
    48.         // Destroy the trigger because we don't need it anymore
    49.         Destroy(gameObject);
    50.     }
    51. }
    52. function OnGUI()
    53. {
    54.     if (drawGUI == true)
    55.     {
    56.         // GUI stuff
    57.     }
    58. }
    59. function OnTriggerExit (theCollider : Collider)
    60. {
    61.     if (theCollider.tag == "Player")
    62.     {
    63.         drawGUI = false;
    64.     }
    65. }
    There are maybe some code mistakes (I never used UnityScript).

    In your world (outside), you can have several triggers that lead to different scene (and / or spawn points). We keep the trigger alive just to know which spawn is used to teleport the player. The variable "hasToBeDestroyed" is used to know which trigger has been kept alive (when you will load the "world" scene, if you do not check this variable, all triggers will execute the code within "OnLevelWasLoaded").
     
  9. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    I don't know why you're not following the suggestions from the other thread(s).
     
  10. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    I don't think having Don'tDestroyOnLoad is a good idea on the trigger, because I will have a trigger to load that level in a place that makes no sense (not all the levels doors are in the same place (myfault)).

    But as we are creating something with a similar functioning door to Skyrim, we were actually trying to create doors to new scenes that allow the player to dart back and forth, Skyrim was the best example I could think of, its not the easiest thing to explain as you can probably imagine. That was why I was trying to find the spawn via its name, so when you go back to the original outdoors world, you can set it to go back to the right door.

    This is the main bit I am having trouble with.

    Code (JavaScript):
    1. #pragma strict
    2.  
    3. var PlayerCharacter : Transform;
    4. var Player;
    5. var SpawnPoint : String = "";
    6. private var drawGUI = false;
    7. var Spawner;
    8. var SpawnerPos;
    9. var NewScene : String = "";
    10. var toText : String = "";
    11.  
    12. function Update ()
    13. {
    14. if (drawGUI == true && Input.GetKeyDown(KeyCode.F))
    15. {
    16.      LoadNewScene();
    17. }
    18. }
    19.  
    20. function OnTriggerEnter (theCollider : Collider)
    21. {
    22.     if (theCollider.tag == "Player")
    23.     {
    24.         drawGUI = true;
    25.     }
    26. }
    27.  
    28. function LoadNewScene ()
    29. {
    30.     DontDestroyOnLoad(PlayerCharacter);
    31.     Application.LoadLevel(NewScene);
    32.    
    33. }
    34.  
    35. function OnLevelWasLoaded ()
    36. {
    37.     Player = GameObject.FindGameObjectsWithTag ("Player");
    38.     Spawner = GameObject.Find (SpawnPoint);
    39.     SpawnerPos = transform.position;
    40.     Debug.Log (SpawnerPos);
    41. }
    42.  
    43. function OnGUI()
    44. {
    45.     if (drawGUI == true)
    46.     {
    47.         //GUI.Label (Rect (Screen.width*0.5-0, 200, 120, 22), "Press F to open to");
    48.         //GUI.Label (Rect (Screen.width*0.5-35, 220, 150, 22), toText);
    49.        
    50.     //GUI.color = new Color(1,1,1,1.0f);
    51.     GUI.skin.box.fontSize=15;
    52.     GUI.backgroundColor = Color(0, 0, 0, 0);
    53.     GUI.BeginGroup (Rect (Screen.width / 2 - 75, Screen.height / 2 - 0, 150, 50));
    54.  
    55.     GUI.Box (Rect (0,0,150,25), "Press F to open to");
    56.     GUI.Box (Rect (0,22,150,25), toText);
    57.    
    58.     GUI.EndGroup ();
    59.     }
    60. }
    61.  
    62. function OnTriggerExit (theCollider : Collider)
    63. {
    64.     if (theCollider.tag == "Player")
    65.     {
    66.         drawGUI = false;
    67.     }
    68. }
     
  11. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    @Suddoha As I have stated, I am NOT a programmer, I very rarely touch things like this, the only programming I do on a regular basis, and that isnt even very often is HTML, CSS and Asp.Net so not everything posted is much use to me as I don't understand half of it.
     
  12. Sbizz

    Sbizz

    Joined:
    Oct 2, 2014
    Posts:
    250
    I think my code works well and do what you want. I made the code for you and I tried to explain it.

    I don't understand why you don't try it ? I understood what you want, I played Skyrim (and it's not a "Skyrim thing", all games do that).

    Please.. even if you're not a programmer, can you read at least my comments ? The trigger will be destroyed once the level will be loaded. We don't care if it makes sense or not, it works and it is not "ugly". It may exist another solution (a better one) but as you said, you're NOT a programmer so I can't do something more complex.
     
  13. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    What you basically just said is:

    "I am not a driver, I very rarely operate vehicles, the only driving I do on a regular basis is ride my riding lawn mower around. So not everything posted about driving a car down the highway I need to get down is much use to me as I don't understand half of it."

    Well it sounds to me like it's time for you to either start understanding it, or find/hire someone who understands it.
     
  14. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    I've understood that from the beginning. That's why i kept it pretty simple and even documented my code and posted an additional description and a HowTo. Don't get me wrong, It's okay to look for another solution but for me it seemed you haven't even tried to use it.

    Once again, i know you're not a programmer and there's probably also an easier way to achieve that (in one script, less code etc) but in order to make it re-usable and seperate the differents tasks, you have to think a bit further.

    As you just said, you don't think it's a good idea to take the trigger with you and i agree on that. Regarding that I had already mentioned in the other thread numerous times that you should split that up and put every functionality into a single script which is then re-usable for different obects/prefabs or even purposes.

    When i wrote the example, i kept in mind you want something which can be dragged from the project window and and dropped into the scene. Once set up, there wouldn't be anything else to do than the latter and select the level to be loaded as far as i remember.
     
  15. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    @Sbizz
    After removing a few bugs (caused by my horrible GUI method not your code) It works, this has been bugging me for days.

    The only problem I am having now is when I am going back to the original scene (looping back round) Unity seems to crash, I think this is due to the multiple characters now occupying the scene, is there any way to delete the old character and keep the new one?
     
  16. Sbizz

    Sbizz

    Joined:
    Oct 2, 2014
    Posts:
    250
    What ? Is the Player Character dynamically created (using a script) or is he already created in the scene ?

    Edit: can I have a link to the other thread ?
     
  17. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    @Suddoha
    First of all, sorry about all of this.
    I understand it can be very infuriating for people, I get the same problem when I try to explain 3D artwork and modelling to audio artists and concept artists so I know what its like.

    Bits and pieces of what you have all supplied have helped hugely with this, I just find some languages harder than others, I can pick up most web development languages up quite quickly, but clearly I need to take the time to learn a LOT more about scripts like Javascript and C#.
     
  18. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    @Sbizz
    The player is placed in the scene, I was going to instantiate it in there, but thought I would still have the same problem with that, as they would be still left in the scene upon returning, so never got round to it.
    By dynamically I assume you do mean instantiating?

    I think I know how to do this, I just avoided it as I thought it would present me with the same problem.

    The other thread is here:
    http://forum.unity3d.com/threads/skyrim-style-doors.287060/
     
  19. Sbizz

    Sbizz

    Joined:
    Oct 2, 2014
    Posts:
    250
    Okay, I saw the other thread. Apparently, the Player Character is already created in the main scene, so every time you'll load this scene, you'll create another Player Character. You have 2 solutions:

    - If your Player Character has a script, you can check in the Start or Awake function if a player already exists. It it does, destroy it. I don't really like this option, but it's gonna work.
    - When you start your game, you instantiate yourself the Player Character. Because you start the game only once, there will be no problem to load several times the main scene.

    Also, @Suddoha doesn't like my method too and I checked his solution ; it works, but if your building has several doors, it will fail ; imagine a castle.. you enter using the DoorA, you leave it using the DoorB (he keeps the last position / rotation of your player character had in the main scene). You should know what you want, so If you have only one door per building, so you can use his method. But I prefer my method, even if we don't destroy directly the trigger (it will be destroyed once the level is loaded).
     
  20. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    If I were to instantiate my character, I couldn't do it in a regular script, it would have to be something that could only be done once per new game, so how would this be done? How would I stop the script instantiating the character every time I loaded that scene?
     
  21. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    I only disliked to use DontDestroyOnLoad on the trigger.
    It's a basic idea to play around with, as he didn't know how to apporach it:). You could also add variables which hold positional data (or as he probably attempted to, a name to find the spawnPoint) and use those to spawn the player.
     
  22. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    Holding the positional data of the character is not a big issue for me, as I may want to have a house with multiple exits, so you may come out somewhere completely different, so having a position you can set independantly with GameObjects was a much more viable option for me, As we are using custom textures for triggers in editor which are hidden on playing, this method also allowed us to future determine what doors do what, go where, come out where and are connected to what location.

    The only issue now is to work out how to instantiate the player ONCE only, so I can save the game, close it and load it up again without it instantiating again.
     
  23. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    I have hit a snag with Instantiating the object, because this door script requires you to drag the player object onto the script, it cannot be done with instantiated objects, I have tried to get it to find the object via name instead but have had no luck yet.
     
  24. Sbizz

    Sbizz

    Joined:
    Oct 2, 2014
    Posts:
    250
    You should find the player by his tag (GameObject.FindGameObjectWithTag) or you can have a script which contains a static variable referencing to the player character (as @Suddoha said in the other thread). With this variable, you could also check if another Player Character is trying to appears and destroy it (If I remember well, @Suddoha told you that in the other thread too).

    I can't do the game for you, if you're not a programmer you should hire one. You can't ask to Unity's members to do everything (except 3D).
     
  25. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    We did have a programmer, up until December.
    The only problem now is that we haven't got everything we need complete.

    Anyway, thank you for all your help, if you are interested, you are welcome to the events script, it isn't big but does have potential for driving event objects.
     
  26. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    Sorry to resurrect this, but how would I make the character face a certain direction, say if I face the Spawner with its local X in a certain direction, could I get the player to face that local X?
     
  27. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Make sure the Spawner's Y is facing world up and Z is facing in the direction you want the player to face and then just set the player's rotation to be the same as the Spawner's rotation.
     
  28. MonkeyZero

    MonkeyZero

    Joined:
    Feb 20, 2013
    Posts:
    37
    Okay, I am a 3D/2D Art department type too, and i really have been trying to follow along with this thread as it is something i want to do as well.

    Correct me is I am wrong, but would it not be more stable is you create a persistent "Don't Destroy" game object to hold all details of the player's character (Health, Skills, Mission, Weapons and ammo, Armor and what ever else) that is loaded when the player starts a game session and is what is truly saved when the player decided it is quitting time.

    The Character Controller is just how the player moves about the scenes and how they see it. The rest of that can actually be housed in another Game Object and given a script for the controller to link to that data.

    Most Character controller I have set up are prefabs. That way a SpawnMarker prefab can actually be created that sits there, and waits for a message to fire off it's task. Say for instance Instantiating a Prefab Controller to stand right where this is placed and face where ever it is rotated.

    The Character Controller need not be protected from destruction because it's just the way the player Moves, Interacts and Sees the game world. The SpawnMarker make this appear in game.

    The Player details (The one that does not get destroyed) could then be created so that is is aware of what scene the player is going to and the Exit Side (Door/Trigger Prefab) will write to this the SpawnMarker Address.

    When the next scene is loaded, the player is presented with a loading screen allowing the Player Details or Data Manager to look for all Objects with the SpawnMarker Tag, and of all these objects find our which one has the Matching Address variable (String Maybe?) that is needed to spawn a fresh new controller that is rigged to pay close attention to the player Details object.

    Once Found, The SpawnMarker that matches, get a Message and presto a new controller is made right where the designer wants is and facing right direction needed to promote the transitions from one place to another.

    It may be a bit complicated. I really don't know how to code this all up myself. Been trying to create a C# version of this myself. Hit many walls due to my lack of code skills. But the idea seems logical and sound.

    It looks, to me, like you are trying to place the character controller into a scene directly. A controller with all the Details character has rather then just the functions you need for it to work. Then when you arrive in a scene, move that controller over to the next scene.

    In the Main menu, a generic player details object can be created that is essentially blank data. New could load all the Default new player details and send them to the very first SpawnMarker of the game. Load Saved game to the Last known scene or what have you. Might even be able to record where in X,Y,Z there are standing that the moment of saving the game thus creating a new character controller with an emergency Spawn from the Player Details script when no controller is present nor any one SpawnMarker is used.

    I don't know, this is all long winded and just a observational theory that may actually not be practical at all. I really wouldn't know.

    If some one made a system like this, I would totally buy it for 15-30 ($-USD) But it would have to be able to support whatever Character controller I decide to have it spawn into game. Standard Assets FPSWalker, uFPS, Third Person right or any other. That is a must. (Private Commission offerings welcome I would guess.)

    I hope I added to the conversation in a positive way and hope that it gets sorted out. Heck, I even going to give whats here already a go when i am a bit more awake. This is just a late night insomnia post for me.

    Later and I'll keep an eye on this one...