Hi all
I would like to deactivate all interactive uis other than special uis. After that I want to deactivate them and activate some other uis. I require it in making a tutorial in a game
Can I need to define a class for all interactive uis and keep it
public interface IActivateInteractiveUI{
void SetActive(bool _value);
}
public class CActivateInteractive:Monobehaviour,IActivateInteractiveUI{
[SerializeField]
Image image;
public void SetActive(bool _value){
image.RaycastTarget=_value;
}
public class CActivateUIController:Monobehaviour{
IActivateInteractiveUI currentActivateUI;
void SetActive(IActivateInteractiveUI _activateUI){
currentActivateUI.SetActive(false);
currentActivateUI=_activateUI;
currentActivateUI.SetActive(true);
}
}
}
I might try setting them with different parents, if that’s not too hard. Then just disable the parent when needed.
As for activating other UIs after that, there’s nothing unique about that; just activate them
There are a lot of buttons,images,etc in the panels. I intend to activate only the button,image,etc that the tutorial illustrates it. So a user can press it
Sounds like you need a statemachine. Make an independent statemachine handler (could be in the scene if you like, or just a static class) and have each of these different UIs register as listeners for the statemachine’s “state change” events. Then, based on the state being changed from, and changed to, you can activate/deactivate panels, images, highlight elements, etc… Clicking where you’re supposed to click to continue the tutorial would just point to the statemachine’s “NextState()” function and move things along.
I would personally make the list of states, and their data, with a ScriptableObject. It would just be a queue of data objects that represent each stage in the tutorial you’re making. This makes it trivial to update, and could also give an object identity to each state that can be referenced directly by the UI elements, ie: if (currentState == TutorialData.Tutorial1.State1) { // do stuff }. Otherwise you’ll have to do it with ID checks or enum values, like "if (currentState.ID == 15) { // do stuff }, etc…
Perfect
I wanted to use state machines for every tutorial. One part of it was activating and deactivating
So you use a queue to switch from one tutorial to another?
I have already utilized DFS depth first search to move from one tutorial to another one
You said that you create scriptableobject for every tutorial and assign it to related object?
data like texts, guide’s position
Thank you
That’s the idea- I don’t technically assign ScriptableObjects to anything except other ScriptableObjects though (usually), I tend to make them into static data managers that self-load when accessed. How I do this varies from case to case, but it usually involves putting them in resources and then something like:
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
[System.Serializable]
public class GameState
{
[SerializeField]
private int _stateID;
public int stateID
{
get { return _stateID; }
set { _stateID = value; }
}
[SerializeField]
private string _stateName;
public string stateName
{
get { return _stateName; }
set { _stateName = value; }
}
public GameState(int id, string name)
{
_stateID = id;
_stateName = name;
}
}
[CreateAssetMenu(fileName = "TutorialData", menuName = "Tutorial Data")]
public class TutorialData : ScriptableObject
{
[SerializeField]
private int _tutorialID;
public int tutorialID
{
get { return _tutorialID; }
set { _tutorialID = value; }
}
[SerializeField]
private string _tutorialName;
public string tutorialName
{
get { return _tutorialName; }
set { _tutorialName = value; }
}
[SerializeField]
private GameState[] _states;
public GameState GetStateAtPosition(int index)
{
if (index < 0 || index > _states.Length)
return null;
return _states[index];
}
public GameState GetState(int id)
{
return _states.FirstOrDefault(t => t.stateID == id);
}
public GameState GetState(string name)
{
return _states.FirstOrDefault(t => t.stateName == name);
}
}
[CreateAssetMenu(fileName = "TutorialDatabase", menuName = "Tutorial Database")]
public class TutorialDatabase : ScriptableObject
{
private const string PATH_DEFAULT = "TutorialDatabase";
private static TutorialDatabase _instance;
private static TutorialDatabase instance
{
get
{
if (_instance == null)
_instance = Resources.Load<TutorialDatabase>(PATH_DEFAULT);
return _instance;
}
}
[SerializeField]
private TutorialData[] _tutorials;
[SerializeField]
private TutorialData _tutorial1;
[SerializeField]
private TutorialData _tutorial2;
public static TutorialData tutorial1 { get { return instance._tutorial1; } }
public static TutorialData tutorial2 { get { return instance._tutorial2; } }
static public TutorialData GetTutorialAtPosition(int index)
{
if (index < 0 || index > instance._tutorials.Length)
return null;
return instance._tutorials[index];
}
static public TutorialData GetTutorial(int id)
{
return instance._tutorials.FirstOrDefault(t => t.tutorialID == id);
}
static public TutorialData GetTutorial(string name)
{
return instance._tutorials.FirstOrDefault(t => t.tutorialName == name);
}
}
I tossed in the “tutorial1” and “tutorial2” static properties to demonstrate a point. For the UI windows, you can do conditional checks with:
if(currentState == TutorialDatabase.GetTutorial("SomeTutorialName").GetState("SomeStateName"))
{
// do stuff
}
… but I don’t much like doing string or ID checks if the objects I’m looking for are well-defined. By tossing in the “tutorial1” and “tutorial2” properties, this can be cut down to:
if(currentState == TutorialDatabase.tutorial1.GetState("SomeStateName"))
{
// do something
}
… and is a bit easier to follow. Of course, this means you need to make serialized fields for each tutorial and drag and drop them into the references in the inspector, but that’s easy enough. You have to drag and drop them into the array anyways, so what the hell.
Thank you but I don’t get my answer
I want to deactivate all buttons and activate only buttons that we need them in the current tutorial. so a user can interact with them. My approach said above is suitable?
That was just how I I would set the assets up- to define the tutorial states themselves, and access them from anywhere in the program. You still need a state machine to actually move things along, and you need all of your UI windows/buttons to register for those state changes. The above shows how your UI can determine how they should react to the current state with conditionals when it changes, without needing to drag and drop any ScriptableObjects into any references on MonoBehaviours.