#Additive gui scene
1 messages · Page 1 of 1 (latest)
I'm trying to set up 6 different scenes (which at the moment are blank and they just have the background image) and an additive scene (the scrollbar) which is usable in every other scene
I managed to add it but:
- I repetedly get an error in console
- it doesn't stay in position (it resets its cordinates every time I change scene
I just fixed the console error by removing the event system in the gui scene... but I still don't know how to fix the other problem
do you need a separate scene for each item?
do you have code that runs in the scrollbar scene that may cause the scripts to re-run?
when you unload a scene, store the scrollbar value, then, on scene load, assign the scrollbar value back. maybe it'll be fast enough to keep its current position . . .
I do
nope, the scroll doesn't have any script
only the buttons on the scrollbar have scripts
how can i do that?
https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.html
subscribe to the events to get notified when a scene has loaded and unloaded. store the scrollbar value when the scene has unloaded; assign the scrollbar value when the (new) scene has loaded. hopefully, it'll retain its position and not pop . . .
let me try
how can I store the scrollbar value?
I've never worked with c# before, don't know anything about it
string hand = GameObject.Find("/GUI/Scroll/Panel").transform.position;
this doesn't seem to work
that's a big issue. smth you to program and make games with unity. it's hard to help someone without the basic/intro knowledge of c#, especially if they don't understand the help given
essentially, you need to subscribe to the load and unload events. add a method to each event: one that stores the scrollbar value on unload, and one that assigns scrollbar value to the stored value on load . . .
Yeah I know, I'm still getting used to it
I'm a python master so I don't think I'll have a lot of problems understanding this
what I'm trying to say is that I understand the logic
I just don't know the correct syntax
I need to create a variable that stores the scrollbar's position, then check if the scene already changed and then change the scrollbar's position with the variable I created before
https://docs.unity3d.com/ScriptReference/GameObject.Find.html I was looking at this documentation
but it doesn't seem to find the scrollbar
first, you need to create a script to handle all of this and place it on a GameObject in the scene . . .
so I don't have to associate the script to the scrollbar?
since it will be handling the scrollbar position . . .
you can place it on the scrollbar GameObject, a parent GameObject, or a separate handler/manager GameObject in the ui scene . . .
alr
no need to use Find. your script will have a variable to reference the Scrollbar component to access its members . . .
ok
just like this, am I right?
yep. now subscribe to the events from the SceneManager link . . .
https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager-activeSceneChanged.html this one should work, right?
are you unloading and loading your scenes?
I guess so
just jumping between scenes
which I think it means I'm unloading a scene and loading another one
ok, but what method do you call/execute to do that?
yeah yeah, just opened the changescene script, I'm loading them
SceneManager.LoadScene(sceneID);
but not unloading, is that something I should do?
it's fine, but you want to use the other two events instead of activeSceneChanged . . .
oh ok
but how can I save the coordinates of the scrollbar since the script starts when the scene already changed?
a scene is unloaded before a new one is loaded. the script listens for the unload event to store the position. it also listens for the load event to assign the position back . . .
alright
how to do that
lol
I'm really sorry
but I've been reading the documentations until now and I don't understand anything
click on the link for the events. they have example code . . .
this shows how to use events: https://learn.unity.com/tutorial/events-uh#
that is what you will do with both of the load events . . .
there's a problem
I don't have a camera
I can't have one
not in the gui scene at least
because it makes a conflict with the cameras of other scenes
huh? you don't need one . . .
it says I need to change the event manager script attached to the camera... am i wrong?
it's an example. you shows you how to set it up and subscribe to an event. that's the only part you need . . .
this is a snippet from the link i sent. this is how you subscribe and unsubscribe from an event . . .
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
public class KeepPosition : MonoBehaviour
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
public class KeepPosition : MonoBehaviour
{
void OnEnable()
{
SceneManager.sceneUnloaded += OnSceneUnloaded;
}
void OnDisable()
{
SceneManager.sceneUnloaded -= OnSceneUnloaded;
}
private void OnSceneUnloaded(Scene current)
{
Debug.Log("OnSceneUnloaded: " + current);
}
void keepPosition()
{
Vector3 pos = transform.position;
pos.y = Random.Range(1.0f, 3.0f);
transform.position = pos;
}
}
does this make any sense?
the method that is called from the event is where you place your code. Teleport moves the object to a different position. your code will assign the value of the scrollbar in one method, and store the value of the scrollbar in a different method (used with the other event) . . .
yeah, but the keepPosition method is unnecessary. you need to put the code you want to execute when a scene is unloaded inside of the OnSceneUnloaded — which is storing the value of the scrollbar . . .
ok
done
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
public class KeepPosition : MonoBehaviour
{
void OnEnable()
{
SceneManager.sceneUnloaded += OnSceneUnloaded;
}
void OnDisable()
{
SceneManager.sceneUnloaded -= OnSceneUnloaded;
}
private void OnSceneUnloaded(Scene current)
{
Vector3 pos = transform.position;
transform.position = pos;
}
}
I don't get what those:
SceneManager.sceneUnloaded -= OnSceneUnloaded
SceneManager.sceneUnloaded += OnSceneUnloaded;
are supposed to do
the code within the method has nothing to do with the scrollbar. but before fixing that, you need to do the same thing when a scene is loaded . . .
So I create another script?
SceneManager.sceneUnloaded += OnSceneUnloaded;```
this subscribes the method `OnSceneUnloaded` to the `SceneManager.sceneUnloaded` event. the event contains a list of delegates (all of its subscribers). when `sceneUnloaded` is invoked, it loops through the list and executes each delegate (in your case, the `OnSceneUnloaded`) . . .
SceneManager.sceneUnloaded -= OnSceneUnloaded```
this removes the delegate (your method) from the list of subscribers contained in the event . . .
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
using System;
public class KeepPosition : MonoBehaviour
{
void OnEnable()
{
SceneManager.sceneUnloaded += OnSceneUnloaded;
SceneManager.sceneLoaded -= OnSceneLoaded;
}
void OnDisable()
{
SceneManager.sceneUnloaded -= OnSceneUnloaded;
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnSceneUnloaded(Scene current)
{
Vector3 pos = transform.position;
}
private void OnSceneLoaded(Scene current)
{
transform.position = pos;
}
}
does this make sense then?
just place a log in each method so you can see the logs and the order of execution from the console. remove the position stuff. that is just saving the GameObject position which has nothing to do with the scrollbar value . . .
doesn't it?
no . . .
aren't we trying to store the coordinates of the gameobject?
the GameObject position as nothing to do with the scrollbar component and its members . . .
you're not moving the GameObject, you're moving the value property of the Scrollbar component. the component is attached to a GameObject. they are not the same thing . . .
right
I'm starting to understand
private void OnSceneUnloaded(Scene current)
{
Debug.Log("Unloading scene");
}
private void OnSceneLoaded(Scene current)
{
Debug.Log("Loading scene");
}
correct?
yeah, change scenes and test if they're called in the proper order . . .
apparently it needs to be done like this
so
what next
your'e trying to remove the subscription when enabled and add it when disabled. you can't remove smth that wasn't added in the first place . . .
you can't. you have errors . . .
fixed them
the same way you test anything for a game . . .
I had to add LoadSceneMode mode)
make sure you have the correct parameters . . .
do I have to attach it to something?
attach what?
if it's not attached to a script, how can it run? have you looked at any videos or tutorials? how'd you get your other stuff to run?
also, didn't you already do that?
did you change scenes? did you put the script on a GameObject?
I'm getting only "loading scene" though
that's probably because in my changescene script I don't unload the scene, I just load another one
the example doesn't show needing the unload, so i took a change it'd work . . .
instead, unload the scene, then load the next scene in your code and see if that works . . .
it works
that was my original intention to begin with . . .
so now I just need to change what happens in the methods
you store the scrollbar value when the scene is unloaded, and assign it back to the scrollbar value when the scene is loaded . . .
it should be similar in any programming language. how would you access a field/member of an object in python?
but I don't know how to access that value
like what's the variable's name
I thought that the find function could help me
then you need to look up the Scrollbar component from the unity scripting API to look at its members: fields, properties, methods, events . . .
hum
no, you have to read the description/definition of the Find method. it only finds and returns a GameObject based on the name provided . . .
you need to create a variable to reference the Scrollbar component . . .
what if I add:
GameObject scrollbar;
and then I add:
Vector3 pos = scrollbar.transform.position;
to the OnSceneUnloaded method
this should work, right?
and then I add
scrollbar.transform.position = pos
to the OnSceneLoaded method
this is what I'd do in python
close, but no. again, you are not storing the position of the GameObject. you need to store the value member of the Scrollbar component . . .
you created a GameObject type named scrollbar. so scrollbar references a GameObject component. you need to reference a Scrollbar component . . .
everything is a GameObject. only GameObjects exists in a scene, but a GameObject is just a container storing a list of components . . .
every GameObject has a Transform component by default which is why each GameObject you lcik on has one at the top . . .
this is all stuff you learn at the beginning from tutorials and would have made this much simpler . . .
ah
ups
I guess I'll watch some tutorial later on
I need to access the Pos X value then
any idea on how to do that?
no, do you even know where the Scrollbar component is?
how are you scrolling through the images?
okay, so it's a ScrollRect, not a Scrollbar. that's the type/component you need to make your variable, then you can reference it in the scene to access its members . . .
Ok, give me a couple minutes and I’ll try that
void OnSceneUnloaded(Scene current)
{
Debug.Log("Unloading scene");
Vector3 pos = ScrollRect.transform.position;
}
void OnSceneLoaded(Scene current, LoadSceneMode mode)
{
Debug.Log("Loading scene");
ScrollRect.transform.position = pos;
}
like this?
GameObject ScrollRect;
and this on top
no, this is the same thing you've been doing before. you only changed the name of the variable. it's still a GameObject component . . .
a GameObject position is what moves in space of the scene. you are not physically moving a GameObject in the scene. you are changing/updating the value of a memeber (either a field or a property) that belongs to a ScrollRect component . . .
how do you make an integer variable?
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
using System;
using static UnityEditor.PlayerSettings;
using UnityEngine.UI;
public class KeepPosition : MonoBehaviour
{
ScrollRect Scrollbar;
Vector3 pos;
void OnEnable()
{
SceneManager.sceneUnloaded += OnSceneUnloaded;
SceneManager.sceneLoaded += OnSceneLoaded;
}
void OnDisable()
{
SceneManager.sceneUnloaded -= OnSceneUnloaded;
SceneManager.sceneLoaded -= OnSceneLoaded;
}
void OnSceneUnloaded(Scene current)
{
Debug.Log("Unloading scene");
Vector3 pos = Scrollbar.transform.position;
}
void OnSceneLoaded(Scene current, LoadSceneMode mode)
{
Debug.Log("Loading scene");
Scrollbar.transform.position = pos;
}
}
the type is correct, but for the last time: stop getting the GameObject position. i don't know how else to say it. you are not moving the GameObject in the scene. you are changing a value from the ScrollRect component . . .
you need to look at the API for ScrollRect to find the member: field or property, that stores the position . . .
Do you think it might be something like this?
https://docs.unity3d.com/2018.2/Documentation/ScriptReference/UI.ScrollRect-normalizedPosition.html
bingo . . .
LESGO
Ahahahaha
Can’t access the pc for a couple hours, I’ll test as soon as I can
still haven't fixed it :( lol
moved in https://discord.com/channels/489222168727519232/497874004401586176 cause there were more people online... if you want you can pass by
just try storing the normalizedPosition to a Vector2 variable when the scene unloads, then assign that stored variable back to normalizedPosition and see if it works . . .
that's what I did
and it still popped?
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
using System;
using static UnityEditor.PlayerSettings;
using UnityEngine.UI;
public class KeepPosition : MonoBehaviour
{
public ScrollRect Scrollbar;
public Vector3 position;
//private void Awake()
//{
// DontDestroyOnLoad(this.gameObject);
//}
void OnEnable()
{
SceneManager.sceneUnloaded += OnSceneUnloaded;
SceneManager.sceneLoaded += OnSceneLoaded;
}
void OnDisable()
{
SceneManager.sceneUnloaded -= OnSceneUnloaded;
SceneManager.sceneLoaded -= OnSceneLoaded;
}
void OnSceneUnloaded(Scene current)
{
Debug.Log("Unloading scene");
position = Scrollbar.normalizedPosition;
}
void OnSceneLoaded(Scene current, LoadSceneMode mode)
{
Debug.Log("Loading scene");
Scrollbar.normalizedPosition = position;
}
}
change the varaible type to Vector2. also, log the value of normalizedPosition in both of the methods to see their values and test it . . .
is position assigned in the inspector at all when you load a scene?
it does print the correct values when unloading
but it resets them to 0 after the loading
the other guys told me that the script "destroys" itself when I unload a scene or something like that
try putting the DontDestroyOnLoad on it (i see in the comments) . . .
it has to be on the parent GameObject, so try transform.root.gameObject as the argument for it . . .
Ohhhh, yes. Totally missed that
Another alternative is to have a script on a separate root-level object that holds values you want saved, and just pass the position into THAT script, and draw from it when the scene loads. If you don't want to save everything from the root down
but it still reset the coordinates
do you suggest trying to do that?
It really depends on what you want. It's a little more setup.
If you want to keep the MainCanvas and all its children from being destroyed, just do it how Random suggested here (#1148981016665522198 message), it's easier
Now, when you said it creates the DDOL scene, did it also put the MainCanvas IN that scene?
yeah, that's fine I guess
let me see
yeah
everything
and the additive scene is empty
OOOOO
IT WORKS
I removed this line from the changescene script:
SceneManager.LoadScene(8, LoadSceneMode.Additive);
apparently the DDOL and the additive scene where having a contrast
Ok nice.
Another alternative, since you're already doing Additive scene loading, is just keep the MainCanvas on a base scene that isn't unloaded
but now how do I tell him where I want it to be there and where I don't?
That is the issue with DDOL for sure.
dang
You have to handle that in code outside of the scene structure
Or do a basescene for when you're in the "set" of scenes that need the canvas and have it live there. Then only when you DON'T need it AT ALL, remove that scene.
Or, like I said earlier, just have a script with values in DDOL. And draw from it when needed, so the MainCanvas can be unloaded and loaded safely whenever you want
oh, the script works just like this:
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
using System;
using static UnityEditor.PlayerSettings;
using UnityEngine.UI;
public class KeepPosition : MonoBehaviour
{
public ScrollRect Scrollbar;
public Vector2 position;
private void Awake()
{
DontDestroyOnLoad(this.transform.root.gameObject);
}
}
let me try
you don't need this . . .
oh ok
if(SceneManager.GetSceneByName == "test")
{
DontDestroyOnLoad(transform.root.gameObject);
}
I was trying to do something like this
does it make sense in first place?
because I was thinking that I could make the DDOL scene run only in certain scene?