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
Related
I need to call a protected variable from a public class into an if statement in a private method of another public class
I am programing a video game in unity and I need to use a bool variable (that shows if the character is out of stamina) in an if statement to determine whether or not the character can run
This is what my code looks like excluding everything unrelated to the problem
Public class CharacterStats : MonoBehaviour
{
[SerialzeField] protected bool Tired;
}
Public class PlayerMovement : MonoBehaviour
{
Private void HandleRunning()
{
If (Input.GetKeyDown(KeyCode.LeftShift) && X != True)
{
Speed = RunSpeed;
}
}
}
X is where I want the Tired variable to be.
Use a public readonly property like e.g.
public class CharacterStats : MonoBehaviour
{
// Keep you serialized field protected
[SerialzeField] protected bool tired;
// Have a public read-only accessor property
public bool Tired => tired;
}
and then e.g.
public class PlayerMovement : MonoBehaviour
{
// Somehow you will need to get a reference to the CharacterStats instance
// e.g. via the Inspector
[SerializeField] private CharacterStats stats;
[SerializeField] private float RunSpeed;
private float Speed;
private void HandleRunning()
{
if (Input.GetKeyDown(KeyCode.LeftShift) && !stats.IsTired)
{
Speed = RunSpeed;
}
}
}
Alternatively (and my apologies to #aybe who had answered this) you can actually directly serialize a property using explicitely
[field: SerializeField] public bool Tired { get; protected set; }
this is a property which can be accessed by everyone but only this and inherited classes (and due to the serialization now the Inspector) have the permission to set the value.
In general: Fix your casing! In c# all keywords are lower key!
Can i create custom region with grouped methods for list onClick like dynamic and statics?
like this
Yes and no! ^^
Yes, you can create your own event type taking a parameter and assign dynamic callbacks to it. What you are looking for is UnityEvent.
For the dynamic parameterized ones see UnityEvent<T0> to UnityEvent<T0, T1, T2, T3> depending on how many parameters you need.
For the example with a single int it would be (exactly as in the API example)
// Since Unity doesn't support direct serialization of generics you have to implement this [Serializable] wrapper
[Serializable]
public class MyIntEvent : UnityEvent<int>
{
}
public class ExampleClass : MonoBehaviour
{
public MyIntEvent m_MyEvent;
}
No, you can not simply change the existing implementation of UI.Button.onClick which is parameterless.
What you could do, however, is build a new component and attach it on a button like
[RequireComponent(typeof(Button))]
public class ExampleClass : MonoBehaviour
{
[SerializeField] private Button _button;
public MyIntEvent onClickWithIntParameter;
private void Awake()
{
if(!_button) _button = GetComponent<Button>();
_button.onClick.AddListener(HandleOnClick);
}
private void HandleOnClick()
{
// Wherever you get your int from
var value = 123;
onClickWithIntParameter.Invoke(value);
}
}
In the case that [Serializable] isn't working for you try [System.Serializable] or using System; at the top.
For Those who want to create a custom event Script:
I made a collision detection script. The events set in the inspector are called when a collision is detected. Just like a button.
https://i.stack.imgur.com/r4epP.png
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngine.Events;
public class CollisionCallFunc : MonoBehaviour {
[System.Serializable]
public class CollisionEvent : UnityEvent<object> {
public object value;
}
[SerializeField]
private CollisionEvent collisionEvents = new();
private void OnCollisionEnter(Collision collision) {
try {
collisionEvents.Invoke(collisionEvents.value);
} catch(System.Exception exception) {
Debug.LogWarning("Couldn't invoke action. Error:");
Debug.LogWarning(exception.Message);
}
}
private void OnCollisionEnter2D(Collision2D collision) {
try {
collisionEvents.Invoke(collisionEvents.value);
} catch(System.Exception exception) {
Debug.LogWarning("Couldn't invoke action. Error:");
Debug.LogWarning(exception.Message);
}
}
}
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.
Is it possible to put parent gameObject in UnityEditor and see child gameObjects from code? I tried to create custom class with necessary structure, nut unity doesn't understand it.
public Path Path1;
public Path Path2;
public Path Path3;
public Path Path4;
[Serializable]
public class Path : MonoBehaviour
{
public List<Way> Ways;
public Path ()
{
}
}
Way class
[Serializable]
public class Way : MonoBehaviour
{
public Transform StartPoint { get; set;}
public Transform[] EndPoints { get; set;}
public Transform[] AngleWaypoints { get; set;}
public Way ()
{
}
public Way (Transform startPoint, Transform[] endPoints, Transform[] angleWaypoints)
{
this.StartPoint = startPoint;
this.EndPoints = endPoints;
this.AngleWaypoints = angleWaypoints;
}
}
Your class needs to inherit from MonoBehaviour, maybe it is it that your missing.
It should look like
class myClass : MonoBehaviour{
}
You have selected your GameManager script. Try selecting Path_1, all public variables of Path class should appear in the UnityEditor.
Also you can change the UnityEditor Mode to Debug, which will show much more information UnityEditor Debug Mode
Does anyone know how make complex UnityEvent appear in editor?
public class Test : MonoBehaviour
{
public UnityEvent myEvent;
public UnityEvent<string> myAnotherEvent;
}
myEvent appears just fine, but myAnotherEvent does not.
Thanks in advance.
UPD Also tried to override the UnityEvent like:
public class NewEvent : UnityEvent<string>
{
}
public class Test : MonoBehaviour
{
public UnityEvent myEvent;
public NewEvent myAnotherEvent;
}
didn't seem to help.
[System.Serializable]
public class NewEvent : UnityEvent<string>
{
}
public class Test : MonoBehaviour
{
public NewEvent myAnotherEvent;
}
You need to inform that your new class is serializable.