Saving Position, Rotation and Scale of GameObject on Scene Transition
Hello everyone,
I have a game object in Scene 1, which the player moves, rotates, and scales. I want to save these three manipulations, so that the object remains as it was manipulated for the next 3 scenes.
I make the transitions with GUI buttons and SceneManager.LoadScene in my workflow. I have read about DontDestroyOnLoad but havent found an implementation that I understood and worked for me - a total newbie with Unity...
Thanks in advance! Michael
Answer by Rickywild · Nov 29, 2016 at 06:08 PM
Hey Michael,
What you need is a singleton. This will persist through scene changes. This is what a singleton may look like,
using UnityEngine;
using System.Collections;
using System;
using UnityEngine.SceneManagement;
//using System.Runtime.Serialization.Formatters.Binary;
//using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
public class GameManager : MonoBehaviour
{
public static GameManager instance = null;
void Awake ()
{
//Create one instance of object and make persistant.
if(instance == null)
{
instance = this;
//PlayerPrefs.DeleteAll();
}
else if(instance != this)
{
Destroy(gameObject);
}
DontDestroyOnLoad(gameObject);
}
void Start(){}
void Update(){}
}
Once this script is saved, attach it onto an empty gameobject in your first scene. This will now be present in every scene, which means you can access it from any other script by simply typing,
GameManager.SavePosition(float x, float y, float z, float rot_x, float rot_y, float rot_z, bla bla bla);
Obviously that function must be coded into your GameManager. When you do get to that point, keep in mind all variables in the GameManager must be set to
public static bool example = true
The same can be said for your functions that you'll wanna call,
public static void Example() { //do something }
That should get you off to a fighting chance, good luck, hope this was helpful!
Why don't just save away the Transform in some proxy object?
Answer by michaeldoukas · Nov 30, 2016 at 09:13 AM
Thanks for the answer! I have read about the Singleton implementation but a guy told me to avoid it. Since I am not a developer and what I am trying to do does not require "professional coding" it does not really matter.
I have the following script attached to an empty GameObject in Unity:
using UnityEngine;
using System.Collections;
using System;
using UnityEngine.SceneManagement;
using System.IO;
public class ObjectManager : MonoBehaviour
{
public static ObjectManager instance = null;
void Awake ()
{
//Create one instance of object and make persistant
if(instance == null)
{
instance = this;
}
else if(instance != this)
{
Destroy(gameObject);
}
DontDestroyOnLoad(gameObject);
}
void SavePosition()
{
PlayerPrefs.SetFloat ("posX", this.transform.position.x);
PlayerPrefs.SetFloat ("posY", this.transform.position.y);
PlayerPrefs.SetFloat ("posZ", this.transform.position.z);
PlayerPrefs.SetFloat ("rotX", this.transform.eulerAngles.x);
PlayerPrefs.SetFloat ("rotY", this.transform.eulerAngles.y);
PlayerPrefs.SetFloat ("rotZ", this.transform.eulerAngles.z);
PlayerPrefs.SetFloat ("scaleX", this.transform.localScale.x);
PlayerPrefs.SetFloat ("scaleY", this.transform.localScale.y);
PlayerPrefs.SetFloat ("scaleZ", this.transform.localScale.z);
}
void LoadPosition()
{
transform.position = new Vector3(PlayerPrefs.GetFloat("posX"), PlayerPrefs.GetFloat("posY"), PlayerPrefs.GetFloat("posZ"));
transform.eulerAngles= new Vector3(PlayerPrefs.GetFloat("rotX"), PlayerPrefs.GetFloat("rotY"), PlayerPrefs.GetFloat("rotZ"));
transform.localScale= new Vector3(PlayerPrefs.GetFloat("scaleX"), PlayerPrefs.GetFloat("scaleY"), PlayerPrefs.GetFloat("scaleZ"));
}
}
Howerver, I am surely missing something and it does not work...How do i make reference to the game object, whose data I want to save across scenes?
I think you maybe misusing the singleton.
Ok if you have done this, don't attach your Object$$anonymous$$anager script to the actual object that's being moved, scaled or rotated. Ins$$anonymous$$d put it onto an empty game object in your first scene (will always be present after moving from first scene) Call the game object, Obj$$anonymous$$anager and attached your singleton script to it.
Then the actual object that's transform is being manipulated, will need it own separate script. Call it whatever you like. In this script you can make the call to your Object$$anonymous$$anager singleton without any reference needed.
So for example,
using UnityEngine;
using System.Collections;
public class Example : $$anonymous$$onoBehaviour
{
private bool changes$$anonymous$$ade;
void Start ()
{
changes$$anonymous$$ade = false;
}
void Update ()
{
//Unknow code that moves, sclaes and rotates here?
if(!changes$$anonymous$$ade) //If you have not done the above yet, then do it in this if statement.
{
//move,scales and rotations code here.
//Ok we've done that now, let's flag it to not happen again.
changes$$anonymous$$ade = true;
Obj$$anonymous$$anager.SavePos(); //Here we make a call to a function called Save() in the singleton.
}
}
}
The SavePos function will need to be coded out into your singleton.
public static void SavePosition(float posX, float posY, float posZ)
{
x = posX;
y = posY;
Z = posZ;
}
You will need to put the variables x, y and z into your singleton class obviously. This approach can also be used for saving your scales and rotation. Just simply follow the above code sample and change accordingly.
Once this stuff is out the way with, you can make it so your singleton will pass these variables when needed. So when you go to your next scene, the Start() is always called. You can assign here all the saves variables to your object that's been moved,scaled,rotated from previous scene. For example,
void Start ()
{
this.transform.position = Object$$anonymous$$anager.GetPos();
changes$$anonymous$$ade = false;
}
Object$$anonymous$$anager singleton will need the GetPos() obviously. You could code out something like,
public static Vector3 GetPos()
{
return new Vector3(x, y, z); //x,y,z being member variables (floats) in the singleton.
}
Or whatever works best for you.
public static float GetPosX()
{
return x;
}
I know what i'm saying here is a little abstract but i don't know how exactly you're making your transform manipulations. Anyways hope this has helped
Thank you for your suggestions Rickywild! I implement my manipulations: - with TapToPlace for picking and placing the GameObject on the Spatial $$anonymous$$esh - Voice Commands "Bigger" and "Smaller" for scaling the GO - Tap and Drag for rotating the Object
I will try your suggestions and let you know!
Sounds interesting! Hope you get it working, good luck!
Your answer
Follow this Question
Related Questions
How to load a score form a saved game vs. the level just completed 0 Answers
Some help with Data Save/Load would be most appreciated 3 Answers
Having issues carrying variables between scenes when reloading a scene. 0 Answers
how can i save highest played level?,how can i save number of highest played level? 0 Answers
Change scene after event (time or clicking on object) 0 Answers