Get float from class in a SerializedProperty - unity3d

I am trying to start using sciptable objects as describe in this talk. Here is my code:
Here is my FloatVariable:
using UnityEngine;
[CreateAssetMenu]
public class FloatVariable : ScriptableObject
{
public float value;
}
Here is my FloatReference:
using UnityEngine;
using System;
[Serializable]
public class FloatReference
{
public bool use_constant = true;
public float constant_value;
public FloatVariable variable_value;
public float v
{
get
{
return use_constant ? constant_value : variable_value.value;
}
set
{
if (use_constant) throw new Exception("Cannot assign constant_value");
else variable_value.value = value;
}
}
}
Here is my GameplayManager where I have one FloatReference value:
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEditor;
using System;
public class GameplayManager : MonoBehaviour
{
public FloatReference pl_orb_mode;
}
Here is my GameplayManagerEditor where I try to get float from FloatVariable class:
using UnityEngine;
using UnityEditor;
using System;
[CustomEditor(typeof(GameplayManager))]
public class GameplayManagerEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
SerializedProperty pl_orb_mode = serializedObject.FindProperty("pl_orb_mode");
SerializedProperty variable = pl_orb_mode.FindPropertyRelative("variable_value");
SerializedProperty the_value = variable.FindPropertyRelative("value");
float test = the_value.floatValue;
Debug.Log(test);
}
}
When I try to get my float test = the_value.floatValue; I get an error:
NullReferenceException: Object reference not set to an instance of an object
GameplayManagerEditor.OnInspectorGUI () (at Assets/Shared/Scripts/Editor/GameplayManagerEditor.cs:18)
So I can get the FloatVariable variable class as a SerializedProperty but I can't get its value property. Why is that so and how to make it work?

Because FloatVariable is inherit from ScriptableObject, so variable_value becomes a reference not a property in SerializedObject.
You have 2 choice.
Don't use ScriptableObject:
[Serializable]
public class FloatVariable
{
public float value;
}
Or edit the reference object:
var so = new SerializedObject(((GameplayManager)target).pl_orb_mode.variable_value);
var the_value = so.FindPropertyRelative("value");
...
so.ApplyModifiedProperties();
Notice that the second way since FloatVariable is a reference object, change on it will change all other objects that refer to it.

Related

Unity2D - Why when I created an object of a class and initialized its properties, I got an error while running the game?

So I created a class named "TextManager" so I could create some objects and initialize some text in the new object's array. The problem is, I declared a new object of the class, gave the value I wanted, initiliazed the object in the Start() function and it gave me an error.
Here's the TextManager class:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TextManager : MonoBehaviour
{
public string description;
public string[] texts;
public TextManager() { }
public TextManager(string pDescription, string[] pTexts)
{
this.description = pDescription;
this.texts = pTexts;
}
}
Now here's the script to add to a gameObject:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GameController : MonoBehaviour
{
[SerializeField] Text mainText;
[SerializeField] GameObject frame;
private int currentPart = 0;
private int changeState = 0;
private float timer = 0.0f;
private bool coroutineStarted = true;
private TextManager introTXT = new TextManager;
private void Start()
{
mainText.text = "";
introTXT.description = "intro";
introTXT.texts[0] = "Text1";
introTXT.texts[1] = "Text2";
introTXT.texts[2] = "Text3";
introTXT.texts[3] = "Text4";
introTXT.texts[4] = "Text5";
introTXT.texts[5] = "Text6";
}
}
And here's the error I got:
NullReferenceException
I don't know why I got a null reference exception... So I'll be waiting for some help.
Thanks in advance guys :)

Unity The name 'PrefabUtility' does not exist in the current context

I'm trying to build a Unity game, and keep getting the error:
Assets\charaterselection.cs(34,9): error CS0103: The name 'PrefabUtility' does not exist in the current context
The issue is I imported UnityEditor, I'm not sure what's going on
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.SceneManagement;
public class charaterselection : MonoBehaviour
{
public SpriteRenderer sr;
public List<Sprite> skins = new List<Sprite>();
private int selecectedSkin;
public GameObject player;
public void Next()
{
selecectedSkin=selecectedSkin+1;
if (selecectedSkin== skins.Count)
{
selecectedSkin=0;
}
sr.sprite= skins[selecectedSkin];
}
public void back()
{
selecectedSkin = selecectedSkin - 1;
if (selecectedSkin < 0)
{
selecectedSkin = skins.Count - 1;
}
sr.sprite = skins[selecectedSkin];
}
public void play()
{
PrefabUtility.SaveAsPrefabAsset(player, "Assets/Players/FROGY.prefab");
SceneManager.LoadScene(1);
}
}
Thank you guys for your help, I literately just made a file called "Editor" and it worked.

NullReferenceException using ScriptableObjects in Unity

I have setup a Scriptableobject in database called "Card" and am attempting to make a searchable list of those items in the scriptableobject. I attached CardDatabase script to an empty gameobject called _CardDatabase. I am not sure if I am attaching it incorrectly or what I have done wrong here.
I am still getting the following error:
NullReferenceException: Object reference not set to an instance of an object
CardDatabase.GetCardByID (System.String abbr) (at Assets/Scripts/CardDatabase.cs:33)
// CardDatabase.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class CardDatabase : MonoBehaviour
{
public CardList cards;
private static CardDatabase instance;
private void Awake()
{
if (instance = null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
public static Card GetCardByID(string abbr)
{
return instance.cards.AllCards.FirstOrDefault(i=> i.abbr == abbr);
}
}
// CardList.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Cards Database",menuName = "Cards Database")]
public class CardList : ScriptableObject
{
public List<Card> AllCards;
}

Can't draw Serializable class on Unity Inspector

This is my Example class and MonoBehaviour script:
using UnityEngine;
using System;
[Serializable]
public class TestSerializableClass
{
public int a;
public string b;
}
public class TestScript : MonoBehaviour
{
public TestSerializableClass field1;
[HideInInspector] public TestSerializableClass field2;
}
and this is the editor script for the MonoBehaviour Script
using UnityEditor;
[CustomEditor(typeof(TestScript))]
public class TestScriptEditor : Editor
{
SerializedProperty testClass;
public override void OnInspectorGUI()
{
DrawDefaultInspector();
SerializedProperty testField = serializedObject.FindProperty("field2");
EditorGUILayout.PropertyField(testField, true);
}
}
This is how my inspector for TestScript looks.
Why doesn't it draw the "field2" varialble like the first one?
Can I do it with Editor script and property field? How?
(the includeChildre flag is true)
Remove the HideInInspector attribute from field2

Accessing struct list on Start() gives NullReferenceError

What in the name of god am I doing wrong here? Every time I run the game I get this: "NullReferenceException: Object reference not set to an instance of an object". I know what that means I just don't get why it is saying that?
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
public class Inventory : MonoBehaviour {
public static Inventory instance;
public List<InventoryItems> INVENTORY_ITEMS = new List<InventoryItems>();
void Awake(){
instance = this;
}
void Start(){
Debug.Log(instance.INVENTORY_ITEMS); // ERROR
Debug.Log(INVENTORY_ITEMS); // ERROR
}
}
[Serializable]
public struct InventoryItems
{
public string name;
}
This is how you should write this code:
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
public class Inventory : MonoBehaviour {
public static Inventory instance;
public List<InventoryItems> INVENTORY_ITEMS;//do not initialize here
void Awake(){
instance = this;
INVENTORY_ITEMS = new List<InventoryItems>();//init here instead
}
void Start(){
Debug.Log(instance.INVENTORY_ITEMS); //no ERROR
Debug.Log(INVENTORY_ITEMS); //no ERROR
}
}
[Serializable]
public struct InventoryItems
{
public string name;
}
Added note:
The reason for this error is that the value of a public serializable member in monobehaviour is being read from the editor (inspector) overwriting any value being assigned to it prior to Awake.
I suggest either change the list accessor to internal, or make it a property, or keep it public but let inspector handle the initialization and adding the initial elements.
Added another note:
According to Programmer and Uri Popov, your original code most certainly will work on unity 5.4 and later.