I'm trying to be better about structuring my code, and I think I'm doing it right. The issue I've got right now is I need to get joystick inputs, scale those values appropriately, and then use that scaled data on any number of MonoBehaviour scripts.
I'm trying to split the input conditioning from the end user, and I'd like to do that by using a ScriptableObject to hold the conditioned data.
I was thinking that a MonoBehaviour script would run, get the joystick data, scale it, and then push that data to variables in the ScaledJoystickData ScriptableObject. Later, a second MonoBehaviour script would access the variables in the ScaledJoystickData and use those to move the things in the game.
I'm understanding the benefits of structuring the code this way, especially in that I can access the ScriptableObject from the editor and manipulate those values; I don't actually need to have a joystick connected, and I'm free to test either end of the input handling independently.
The problem is that, if I am looking at the ScriptableObject instance in the editor, it stops updating as soon as I click away from it (to the consuming GameObject). If I click back to the ScriptableObejct instance, none of the values update. Nothing on the GameObject's script updates unless I start the game with that GO selected in-editor, and again THAT fails to update if I click off and click back.
The GameObject script is currently using the values from the ScriptableObject instance and piping them to public variables, and the public variables aren't updating.
Is there some bug with ScriptableObjects, or am I doing this wrong?
:EDIT:
Here's an example. Make a script called "ExampleSO" and replace the contents with:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu]
public class ExampleSO : ScriptableObject
{
public float stashedVar = 0f;
}
Make a script called "ExampleWriter" and replace the contents with:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ExampleWriter : MonoBehaviour
{
public float scaling = 2f;
public float scaledInput = 0f;
public ExampleSO exampleSO = null;
// Update is called once per frame
void Update()
{
if(exampleSO!=null)
{
scaledInput = scaling * (Input.GetKey(KeyCode.LeftArrow) ? 1f : 0f);
exampleSO.stashedVar = scaledInput;
}
}
}
Make a script called "ExampleReader" and replace the contents with:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ExampleReader : MonoBehaviour
{
public float display = 0f;
public ExampleSO exampleSO = null;
void Update()
{
if(exampleSO!=null)
{
display = exampleSO.stashedVar;
}
}
}
Create an instance of the ExampleSO, add the ExampleWriter to a game object, and put the ExampleSO instance into the ExampleWriter slot.
Highlight the game object holding ExampleWriter and run it. Push the left arrow key and see the value toggle 0/2.
Click the ExampleSO instance. Nothing is happening there now. Click back on the game object, and now it doesn't update either.
If you have the ExampleReader on the same game object then it won't work at all. ExampleReader will read fine, if you have it on a separate GameObject, but again if you click off and click back then it stops responding.