0
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ "or am I doing this wrong?" We can't tell you that unless you show us how you're doing it. Please include a minimal complete verifiable example of this problem, so we can reproduce the issue exactly as you're seeing it, and test potential solutions. \$\endgroup\$ – DMGregory Oct 24 '19 at 19:04
  • \$\begingroup\$ @DMGregory - I found the answer to the question while I was working on the minimum reproducible example, so thanks for pushing me to that. I had thought that maybe there was some known bug with scriptable objects. Answer below. \$\endgroup\$ – Chuck Oct 24 '19 at 19:43
2
\$\begingroup\$

The input isn't updating when I clicked around in the editor because inputs are only passed to Unity if you click the game view port in editor. By selecting the ScriptableObject instance, or the other GameObject, etc., I was actually clicking off of the Game view port, which stopped the inputs from being passed to Unity.

Once that happened, the ExampleReader (in the example I posted) is no longer getting any inputs, so there's just nothing to write. Nothing written, nothing to read, nothing to update, so of course the ScriptableObject instance and the ExampleReader look like they're not responding.

Super irritating to troubleshoot, but there you go.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.