Unity3D [SerializeField] Menu Array not showing - c#

So I'm following Rugbug Redfern's tutorial on how to make Photon multiplayer but the Menu SerializeField array isn't showing. Please help.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MenuManager : MonoBehaviour
{
public static MenuManager Instance;
[SerializeField] Menu[] menus;
void Awake()
{
Instance = this;
}
public void OpenMenu(string menuName)
{
for(int i = 0; i < menus.Length; i++)
{
if(menus[i].menuName == menuName)
{
menus[i].Open();
}
else if(menus[i].open)
{
CloseMenu(menus[i]);
}
}
}
public void OpenMenu(Menu menu)
{
for(int i = 0; i < menus.Length; i++)
{
if(menus[i].open)
{
CloseMenu(menus[i]);
}
}
menu.Open();
}
public void CloseMenu(Menu menu)
{
menu.Close();
}
}

Related

Unity 2d İ had some error ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection

Hello guys I'm newbie in unity and c# i was trying make little game but i have a an error i cant fix that can you help me? and whats wrong? you explain so I can learn? I'm making a mistake somewhere but I don't understand where...
I also looked at the friends who got the same error in the forums, but I could not find the relevance of what was said with my code.I also made these codes with the things I learned on youtube, so if there are mistakes, please excuse me
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.UI;
public class LobbyNetworkManager : MonoBehaviourPunCallbacks
{
int number;
public Text su;
private List<RoomItemUI> _roomList = new List<RoomItemUI>();
[SerializeField] private RoomItemUI _roomItemUIPrefab;
[SerializeField] private Transform _roomListParent;
[SerializeField] private Text _statusField;
[SerializeField] private Button _leaveRoomButton;
private void Start()
{
Initialize();
Connect();
}
#region PhotonCallbacks
public override void OnConnectedToMaster()
{
Debug.Log("Connected to master server");
PhotonNetwork.JoinLobby();
}
public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
UpdateRoomList(roomList);
}
public override void OnDisconnected(DisconnectCause cause)
{
Debug.Log("Disconnect");
}
public override void OnJoinedLobby()
{
Debug.Log("Joined Lobby!");
}
public override void OnJoinedRoom()
{
_statusField.text = "Joined" + PhotonNetwork.CurrentRoom.Name;
Debug.Log("Joined Room " + PhotonNetwork.CurrentRoom.Name);
_leaveRoomButton.interactable = true;
}
public override void OnLeftRoom()
{
_statusField.text = "Lobby";
Debug.Log("Left Room");
_leaveRoomButton.interactable = false;
}
#endregion
private void Initialize()
{
_leaveRoomButton.interactable = false;
}
private void Connect()
{
PhotonNetwork.NickName = "Player" + Random.Range(0, 5000);
PhotonNetwork.ConnectUsingSettings();
PhotonNetwork.AutomaticallySyncScene = true;
}
private void UpdateRoomList(List<RoomInfo> roomList)
{
//clear current list of room
for (int i = 0; i < roomList.Count; i++)
{
Destroy(_roomList[i].gameObject);
}
_roomList.Clear();
//Generate a new list with the updated info
for(int i = 0; i < roomList.Count; i++)
{
//skip empty rooms
if(roomList[i].PlayerCount == 0) { continue; }
RoomItemUI newRoomItem = Instantiate(_roomItemUIPrefab);
newRoomItem.LobbyNetworkParent = this;
newRoomItem.SetName(roomList[i].Name);
newRoomItem.transform.SetParent(_roomListParent);
_roomList.Add(newRoomItem);
}
}
public void JoinRoom(string roomName)
{
PhotonNetwork.JoinRoom(roomName);
}
public void CreateRoom()
{
number = Random.Range(1000000, 9999999);
PhotonNetwork.CreateRoom(su.text + number, new RoomOptions() { MaxPlayers = 4 }, null);
}
public void LeaveRoom()
{
PhotonNetwork.LeaveRoom();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;
public class RoomItemUI : MonoBehaviour
{
public LobbyNetworkManager LobbyNetworkParent;
[SerializeField] private Text _roomName;
public void SetName(string roomName)
{
_roomName.text = roomName;
}
public void OnJoinPressed()
{
LobbyNetworkParent.JoinRoom(_roomName.text);
}
}

Unity Click and Pass WaitForSeconds

I'm making simple 2d game. This is opening scene. (Logos images showing).I want to if mouse click down (0) Time passes and other image show. How can i do it ?
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class OpeningCanvasScript : MonoBehaviour
{
void Start()
{
StartCoroutine(otherImage());
}
private void Deactivate()
{
for (int i = 0; i < transform.childCount; i++)
{
transform.GetChild(i).gameObject.SetActive(false);
}
}
private IEnumerator otherImage()
{
for (int i = 0; i < transform.childCount; i++)
{
Deactivate();
transform.GetChild(i).gameObject.SetActive(true);
yield return new WaitForSeconds(3f);
// I want to if mouse click down (0) Time passes and other image show
}
SceneManager.LoadScene(2);
}
}```
I think i did it this way
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class OpeningCanvasScript : MonoBehaviour
{
bool finished = false;
void Start()
{
StartCoroutine(otherImage());
}
private void Deactivate()
{
for (int i = 0; i < transform.childCount; i++)
{
transform.GetChild(i).gameObject.SetActive(false);
}
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
finished = true;
}
}
private IEnumerator otherImage()
{
for (int i = 0; i < transform.childCount; i++)
{
finished = false;
Deactivate();
transform.GetChild(i).gameObject.SetActive(true);
StartCoroutine(waitSeconds());
yield return new WaitUntil(()=>finished);
}
SceneManager.LoadScene(2);
}
private IEnumerator waitSeconds()
{
yield return new WaitForSeconds(3f);
finished = true;
}
}

How can I add a Conversations on top level above the Dialogues?

At the dialogue trigger script top I added a new List type string:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
public class DialogueTrigger : MonoBehaviour
{
public List<string> conversation = new List<string>();
public List<Dialogue> dialogue = new List<Dialogue>();
[HideInInspector]
public int dialogueNum = 0;
private bool triggered = false;
private List<Dialogue> oldDialogue;
private void Start()
{
//oldDialogue = dialogue.ToList();
}
public void TriggerDialogue()
{
if (triggered == false)
{
if (FindObjectOfType<DialogueManager>() != null)
{
FindObjectOfType<DialogueManager>().StartDialogue(dialogue[dialogueNum]);
dialogueNum += 1;
}
triggered = true;
}
}
private void Update()
{
if (DialogueManager.dialogueEnded == true)
{
if (dialogueNum == dialogue.Count)
{
return;
}
else
{
FindObjectOfType<DialogueManager>().StartDialogue(dialogue[dialogueNum]);
DialogueManager.dialogueEnded = false;
dialogueNum += 1;
}
}
}
}
Then in the editor script:
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
[CustomEditor(typeof(DialogueTrigger))]
public class DialogueTriggerEditor : Editor
{
private SerializedProperty _dialogues;
private SerializedProperty _conversations;
private void OnEnable()
{
// do this only once here
_dialogues = serializedObject.FindProperty("dialogue");
_conversations = serializedObject.FindProperty("conversation");
}
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();
serializedObject.Update();
_conversations.arraySize = EditorGUILayout.IntField("Conversation Size", _conversations.arraySize);
// Ofcourse you also want to change the list size here
_dialogues.arraySize = EditorGUILayout.IntField("Dialogue Size", _dialogues.arraySize);
for (int x = 0; x < _conversations.arraySize; x++)
{
for (int i = 0; i < _dialogues.arraySize; i++)
{
var dialogue = _dialogues.GetArrayElementAtIndex(i);
EditorGUILayout.PropertyField(dialogue, new GUIContent("Dialogue " + i), true);
}
}
// Note: You also forgot to add this
serializedObject.ApplyModifiedProperties();
}
}
I'm doing a loop of the _conversations on the loop of the _dialogues.
But this is not what I wanted.
I want that in the Inspector on the top level there will be only "Conversations Size".
If the Conversations Size is 0 there is nothing.
But if the Conversations Size for example is 5.
Then it will create 5 Conversations(Conversation 1, Conversation 2....Conversation5). And under each Conversation there will be a Dialouge Size and then I can make many dialogues per conversation.
That way it will be easier to identify later the conversations and dialogues.
Instead as before that there was one long dialogues.
I added the conversation List before that it was just without the conversation/s and working fine but now I want to add the conversations. So each conversation will have it's own dialogues.
This is the scripts according to the solution:
Created the class:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Conversation
{
public string Id;
public List<Dialogue> Dialogues = new List<Dialogue>();
}
Then the trigger script:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
public class DialogueTrigger : MonoBehaviour
{
public List<Conversation> conversations = new List<Conversation>();
public List<Dialogue> dialogue = new List<Dialogue>();
[HideInInspector]
public int dialogueNum = 0;
private bool triggered = false;
private List<Dialogue> oldDialogue;
private void Start()
{
//oldDialogue = dialogue.ToList();
}
public void TriggerDialogue()
{
if (triggered == false)
{
if (FindObjectOfType<DialogueManager>() != null)
{
FindObjectOfType<DialogueManager>().StartDialogue(dialogue[dialogueNum]);
dialogueNum += 1;
}
triggered = true;
}
}
private void Update()
{
if (DialogueManager.dialogueEnded == true)
{
if (dialogueNum == dialogue.Count)
{
return;
}
else
{
FindObjectOfType<DialogueManager>().StartDialogue(dialogue[dialogueNum]);
DialogueManager.dialogueEnded = false;
dialogueNum += 1;
}
}
}
}
And last the trigger editor script:
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
[CustomEditor(typeof(DialogueTrigger))]
public class DialogueTriggerEditor : Editor
{
private SerializedProperty _dialogues;
private SerializedProperty _conversations;
private void OnEnable()
{
_conversations = serializedObject.FindProperty("conversations");
}
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();
serializedObject.Update();
_conversations.arraySize = EditorGUILayout.IntField("Conversations Size", _conversations.arraySize);
for (int x = 0; x < _conversations.arraySize; x++)
{
var conversation = _conversations.GetArrayElementAtIndex(x);
var Id = conversation.FindPropertyRelative("Id");
EditorGUILayout.PropertyField(Id);
_dialogues = conversation.FindPropertyRelative("Dialogues");
_dialogues.arraySize = EditorGUILayout.IntField("Dialogues size", _dialogues.arraySize);
for (int i = 0; i < _dialogues.arraySize; i++)
{
var dialogue = _dialogues.GetArrayElementAtIndex(i);
EditorGUILayout.PropertyField(dialogue, new GUIContent("Dialogue " + i), true);
}
}
serializedObject.ApplyModifiedProperties();
}
}
And a screenshot result:
I think that all the Id's in the Inspector should be children of the Conversations Size and all the Dialogues Size should be child of the Id and then the Dialogues should be childs of the Dialogues Size.
Conversation Size
Id 1
Dialogues Size
Dialogue 1
Name
Sentences
Dialogue 2
Something like that.
You should instead have a proper class
[Serializable]
public class Conversation
{
public string Id;
public List<Dialogue> Dialogues = new List<Dialogue>();
}
and than instead have a list of that in
public DialogueTrigget : MonoBehaviour
{
public List<Conversation> Conversations = new List<Conversation> ();
...
}
Than you can use exactly the same script I gave you last time but with
_conversations = serializedObject.FindProperty("Conversations");
and accordingly one for loop more similar to what you tried already .. something like
[CustomEditor(typeof(DialogueTrigger))]
public class DialogueTriggerEditor : Editor
{
private SerializedProperty _dialogues;
private SerializedProperty _conversations;
private void OnEnable()
{
_conversations = serializedObject.FindProperty("conversation");
}
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();
serializedObject.Update();
_conversations.arraySize = EditorGUILayout.IntField("Conversation Size", _conversations.arraySize);
for (int x = 0; x < _conversations.arraySize; x++)
{
var conversation = _conversations.GetArrayElementAtIndex(x);
var id = conversation.FindPropertyRelative("I'd");
EditorGUI.indentLevel ++;
EditorGUILayout.PropertyField(Id);
var dialogues = conversation.FindPropertyRelative("Dialogues");
dialogues.arraySize = EditorGUILayout.IntField("Dialogues size", dialogues.arraySize);
for (int i = 0; i < dialogues.arraySize; i++)
{
var dialogue = _dialogues.GetArrayElementAtIndex(i);
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(dialogue, new GUIContent("Dialogue " + i), true);
EditorGUI.indentLevel--;
}
EditorGUI.indentLevel--;
}
serializedObject.ApplyModifiedProperties();
}
}
or alternatively simply
EditorGUILayout.PropertyField(_conversations, new GUIContent ("Conversations"), true);
but this would not print "Dialogue 1, Dialogue 2" etc
Again I strongly recommend you have a look at the nested ReorderableList you will see it is awesome once you got it working.
Typed on my smartphone so no warranty

I cant use the variable in a different script (unity 2D). Any suggestions

i want to use variables levelButtons and levelunlocked from the script below :-
public class LevelSelector : MonoBehaviour
{
public Button[] levelButtons;
private void Start()
{
int levelunlocked = 1;
int levelReached = PlayerPrefs.GetInt("levelReached", levelunlocked);
for (int i = 0; i < levelButtons.Length; i++)
{
if (i + 1 > levelReached)
{
levelButtons[i].interactable = false;
}
}
}
}
and use them in this script below. it would be a huge help.
public class Level : MonoBehaviour
{
[SerializeField] int breakableBlocks;
SceneLoader sceneloader;
private void Start()
{
sceneloader = FindObjectOfType<SceneLoader>();
}
public void CountBreakableBlocks()
{
breakableBlocks++;
}
public void BlockDestroyed()
{
breakableBlocks--;
if (breakableBlocks <= 0)
{
sceneloader.LoadWinScreen();
}
}
}
any ideas?? its unity c#.
You can declare levelunlocked and levelReached outside of the Start method and make them public, like this:
public class LevelSelector : MonoBehaviour
{
public Button[] levelButtons;
public int levelunlocked = 1;
public int levelReached;
private void Start()
{
levelReached = PlayerPrefs.GetInt("levelReached", levelunlocked);
for (int i = 0; i < levelButtons.Length; i++)
{
if (i + 1 > levelReached)
{
levelButtons[i].interactable = false;
}
}
}
}
Then to access levelunlocked and levelReached, get a reference to LevelSelector by using GetComponent, or make the fields static and access them by doing LevelSelector.levelunlocked or LevelSelector.levelReached.

How do I fix this Idle-Car Game Script

I am trying to have a game, in which everyone can buy cars (and I save that data to playerprefs). So I have 9 trails for the cars in my game and I am trying to write some code so that when you press a button the car & the trail for that car will show up.
When the button next to it is clicked, it saves that data so when people restart the game, they will still have the car & trail open and won't need to press the button again.
Here's my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine; using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
public Button[] TrailLevel;
public GameObject[] Cars, Trails;
public Text text;
public int CurrentCarToSpawn = 0;
private void Start()
{ }
private void FixedUpdate()
{
UpdateCar();
}
public void InstantiateCar()
{
TrailLevel[CurrentCarToSpawn].gameObject.active = false;
MineLevel[CurrentCarToSpawn+1].interactable = true;
PlayerPrefs.SetInt("TrailCountA", PlayerPrefs.GetInt("TrailCountA") + 1);
PlayerPrefs.Save();
CurrentCarToSpawn++;
UpdateCar();
}
void UpdateCar()
{
int TrailCountA= PlayerPrefs.GetInt("TrailCountA", 1);
for (int i = 0; i < TrailLevel.Length; i++)
{
if (i + 1 > TrailCountA)
{
TrailLevel.interactable = false;
}
if (TrailLevel.interactable)
{
Trains[CurrentCarToSpawn].gameObject.active = true;
Mines[CurrentCarToSpawn].gameObject.active = true;
}
}
text.text = PlayerPrefs.GetInt("TrailCountA").ToString();
}
}
From what I can see with your code, this is how I would approach it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine; using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
public Button[] TrailLevel;
public GameObject[] Cars, Trails;
public Text text;
public int CurrentCarToSpawn = 0;
private void Start()
{
// Load the current car. ADDED
CurrentCarToSpawn = PlayerPrefs.getInt("savedSelection", 0);
// Since we are loading the last selection, we need to call our
// instantiation method so it can activate the appropriate
// GameObjects.
InstantiateCar();
}
private void FixedUpdate()
{
UpdateCar();
}
public void InstantiateCar()
{
TrailLevel[CurrentCarToSpawn].gameObject.active = false;
MineLevel[CurrentCarToSpawn+1].interactable = true;
PlayerPrefs.SetInt("TrailCountA", PlayerPrefs.GetInt("TrailCountA") + 1);
// Save that this is our current selection.
PlayerPrefs.SetInt("savedSelection", CurrentCarToSpawn);
PlayerPrefs.Save();
CurrentCarToSpawn++;
UpdateCar();
}
void UpdateCar()
{
int TrailCountA= PlayerPrefs.GetInt("TrailCountA", 1);
for (int i = 0; i < TrailLevel.Length; i++)
{
if (i + 1 > TrailCountA)
{
TrailLevel.interactable = false;
}
if (TrailLevel.interactable)
{
Trains[CurrentCarToSpawn].gameObject.active = true;
Mines[CurrentCarToSpawn].gameObject.active = true;
}
}
text.text = PlayerPrefs.GetInt("TrailCountA").ToString();
}
}

Categories