- Home /
Scriptable object variable not updating when changed, only when game stopped
Hello everyone, this question can be a bit complicated
I have a GUI that contains slots that you can put items inside. Each item represents a scriptable object. Whenever a new item is dropped in the slot, the slot manager then gets the items stored on each slot and saves it in its own variables. Everything works, but the items didn't show up on the manager code. It only shows up when I stopped the game.
I have a video to show you what I mean: https://youtu.be/ducUaWU0Dk0
CODES: 1 SlotDrop_Handler (storing the item dragged into the slot)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class SlotDrop_Handler : MonoBehaviour, IDropHandler {
public Inventory_Controller inventory;
public PowerCore_Controller powercoreControl;
public Item currentItem = null;
public List<Item> itemList;
public GameObject slot{
get{
if(transform.childCount > 0){
return transform.GetChild(0).gameObject;
}else{
return null;
}
}
}
public void OnDrop(PointerEventData eventData){
if(slot.GetComponent<Image>().sprite == null){
Item draggedObject = eventData.pointerDrag.GetComponentInParent<Inventory_Slot>().item;
inventory.RemoveItemFromList(draggedObject);
currentItem = draggedObject;
Debug.Log("Combining with " + draggedObject.name);
for (int i = 0; i < itemList.Count; i++)
{
if(itemList[i].name == draggedObject.name){
slot.GetComponent<Image>().sprite = itemList[i].icon;
slot.GetComponent<Image>().enabled = true;
break;
}
}
powercoreControl.CallCombinationManager();
}
}
}
2 PowerCore_Controller (calls the combination manager to check for new items in each slot)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PowerCore_Controller : MonoBehaviour {
public GameObject currentPowercore = null;
public PowerCore powercoreObject;
public GameObject crosshair, textMessage;
public GameObject basicLayout;
public List<GameObject> powerCores;
void Start(){
UpdatePowerCore();
}
public void PickupPowerCore(PowerCore powercorepickup){
currentPowercore = powercorepickup.referenceObject;
powercoreObject = powercorepickup;
UpdatePowerCore();
}
public void UpdatePowerCore(){
if(currentPowercore == null){
crosshair.SetActive(false);
textMessage.SetActive(true);
return;
} else {
Debug.Log("Update Power Core");
crosshair.SetActive(true);
textMessage.SetActive(false);
DisableAllCores();
string findCore = currentPowercore.name;
for (int i = 0; i < powerCores.Count; i++){
if(findCore == powerCores[i].name){
powerCores[i].SetActive(true);
break;
}
}
{
}
}
}
//Call relevant combination manager to update combination
public void CallCombinationManager(){
currentPowercore.GetComponent<CoreCombination_Manager>().UpdateCombination(this, basicLayout);
}
void DisableAllCores(){
for (int i = 0; i < powerCores.Count; i++)
{
powerCores[i].SetActive(false);
}
}
}
3 CoreCombination_Manager (gets the variables from the layout handler to store)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CoreCombination_Manager : MonoBehaviour {
[Header("Basic Layout")]
public Item basicPrimary;
public Item basicSecondary, basicPassive;
void Start(){
ResetCombinations();
}
public void UpdateCombination(PowerCore_Controller powercoreControl, GameObject layout){
if(powercoreControl.currentPowercore.name == "BasicCore - 0"){
layout.GetComponent<Layout_Handler>().GetBasicCombinations(this);
Debug.Log("Get Basic Combinations");
ResetCombinations();
if(basicPrimary == null){
basicPrimary = layout.GetComponent<Layout_Handler>().primaryItem;
}
if(basicSecondary == null){
basicSecondary = layout.GetComponent<Layout_Handler>().secondaryItem;
}
if(basicPassive == null){
basicPassive = layout.GetComponent<Layout_Handler>().passiveItem;
}
}
}
void ResetCombinations(){
basicPrimary = null;
basicPassive = null;
basicSecondary = null;
}
}
Last but not least, 4 Layout_Handler (Goes through each slot and stores the item stored in the slot)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Layout_Handler : MonoBehaviour {
public Item primaryItem, secondaryItem, passiveItem;
public void GetBasicCombinations(CoreCombination_Manager combinationManager){
int allExceptLast = transform.childCount - 1;
for (int i = 0; i < allExceptLast; i++)
{
GameObject slot = transform.GetChild(i).gameObject;
if(slot.name == "PrimarySlot"){
if(slot.GetComponent<SlotDrop_Handler>().currentItem != null){
primaryItem = slot.GetComponent<SlotDrop_Handler>().currentItem;
Debug.Log("basicPrimary is now " + slot.GetComponent<SlotDrop_Handler>().currentItem.name);
}else{
combinationManager.basicPrimary = null;
}
}else if (slot.name == "SecondarySlot"){
if(slot.GetComponent<SlotDrop_Handler>().currentItem != null){
secondaryItem = slot.GetComponent<SlotDrop_Handler>().currentItem;
Debug.Log("basicSecondary is now " + slot.GetComponent<SlotDrop_Handler>().currentItem.name);
}else{
combinationManager.basicSecondary = null;
}
}else if (slot.name == "PassiveSlot"){
if(slot.GetComponent<SlotDrop_Handler>().currentItem != null){
passiveItem = slot.GetComponent<SlotDrop_Handler>().currentItem;
Debug.Log("basicPassive is now " + slot.GetComponent<SlotDrop_Handler>().currentItem.name);
}else{
combinationManager.basicPassive = null;
}
}
}
}
}
This has been very long, but I hope I've provided enough details to help you help me. What am I saying. But anywho, thank you in advance.
Looks like an editor ui bug. Anyway, you can try this: Create new serializable wrapper class for 3 item combination (primary, secondary, passive) and use it as containter object to pass these 2 items across your scripts, it should also simplify your code...
@misher Hi there, thank you for your response. Apparently, I'm just a novice programmer and I have no idea what's a serializable wrapper class. I'll try learning about it myself but if you could show me an example that would be great.
Also, if the problem is an editor bug, I'll try updating my Unity version to 2018.2.5 from my current 2018.2.3, hopefully they fixed the bug on that version.
Answer by SmolPadok · Aug 25, 2018 at 01:25 PM
Okay, it works now but it's not the best for customization.
Turns out, the gameobject the script is in that I wanted to change is a prefab. And the gameobject with the variables that I wanted to copy from has to be a prefab as well in order to work, but I don't wanna mess with a lot more prefab problems.
SOLUTION
So I cut short the calling procedure by taking the variables from the SlotDrop_Handler (in a normal gameobject) right to the PowerCore_Controller (also in a normal gameobject) without passing through CoreCombination_Manager (in a prefab). That way I don't pass any prefabs throughout the process.
I also followed @misher 's way of saving the items in a serialized wrapper class. It's not really the solution for this but it helps simplify the code.
Yes, you should never pass monobehaviour as a data container, use simple serializable classes or better define data structure in a scriptable objects (this will help you with customization as well). Generally it is far better to separate data layer from visualisation layer. Data should live on their own independently of where they are used. $$anonymous$$ultiple $$anonymous$$onoBehaviours (scene objects or prefabs, even in different scenes) can reference the same data via some initialisation process or, doing it in unity way, by referencing common assets (Scriptable Objects). I would also recommend using scriptable object as event dispatcher to achieve truly loosely coupled architecture, a can share some code... Here: https://github.com/kolodi/SceneAgnostic
Your answer
Follow this Question
Related Questions
Several problems: variables references, managing and displaying variable values in the GUI 0 Answers
Problem with var in C# (Vector3, transform and similiar) 1 Answer
Calling a variable based on a variables name? 1 Answer
Methods and loops problem 0 Answers
GUI calling function with return value. I dont know why this doesnt work. 0 Answers