0
\$\begingroup\$

so I need to check a List of strings belonging to an AudioManager script, from another script, to see if it contains a specific string. Accessing that List wasn't hard. What's surprising me is that the method List<T>.Contains(T) is returning true when it should return false. I think this is because it returns true when a substring in the List matches the string I am checking for.

My first idea was to just run a for-each loop, but I assumed that was naiive; that I should use a List method. Should I just use a for-each loop? Here are the offending scripts:

This script is on my GameManager prefab. It has the AudioManager tag and the script is called AudioManager.cs.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class AudioManager : MonoBehaviour
{
    private static AudioManager instance = null; // static (class level) variable
    public static AudioManager Instance { get { return instance; } } // static getter (only accessing allowed)

    public List<string> anims_w_soundFX;

    public AudioSource bgm;
    private Scene currentScene;

    void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }

        else
        {
            if (this != instance) { Destroy(gameObject); }
        }
        currentScene = SceneManager.GetActiveScene();

        anims_w_soundFX = new List<string>()
        {
            "Luigi_Jump_start_wSound",
            "Luigi_Jump_down_wSound",
            "Luigi_Jump_end_wSound",
            "Luigi_Walk_wSound",
            "Luigi_Run_wSound",
            "Luigi_Battle_Punch_wSound",
            "Luigi_Battle_PunchTimed_wSound"
        };
        //@StackExchange users: ^ THIS IS ALL YOU NEED TO READ FOR THIS SCRIPT!
    }

    //(...) there's more but it only affects background music
}

This next script is called SFX_Event.cs. I use the SetSFX() function from this script when I place an animation event on an animation clip:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SFX_Event : MonoBehaviour
{
    private Animator anim;
    private AnimatorClipInfo[] currentClipInfo;
    private AudioClip sfxClip;
    private GameObject audioManager;
    private List<string> anims_w_soundFX;
    public AudioSource source;

    void Start()
    {
        anim = GetComponent<Animator>();
        audioManager = GameObject.FindGameObjectWithTag("AudioManager");
        anims_w_soundFX = audioManager.GetComponent<AudioManager>().anims_w_soundFX;
    }
    public void SetSFX()
    {
        currentClipInfo = anim.GetCurrentAnimatorClipInfo(0);
        string ccName = currentClipInfo[0].clip.name;
        if (anims_w_soundFX.Contains(ccName))
        {
            switch (ccName)
            {
                case "Luigi_Jump_start_wSound":
                    sfxClip = Resources.Load<AudioClip>("SFX/smrpg_jump");
                    PlaySFX();
                    break;

                case "Luigi_Jump_down_wSound":
                    sfxClip = Resources.Load<AudioClip>("SFX/freesfx_falling_quick");
                    PlaySFX();
                    break;

                case "Luigi_Jump_end_wSound":
                    sfxClip = Resources.Load<AudioClip>("SFX/smrpg_click");
                    PlaySFX();
                    break;

                case "Luigi_Walk_wSound":
                    sfxClip = Resources.Load<AudioClip>("SFX/step-floor");
                    PlaySFX();
                    break;

                case "Luigi_Run_wSound":
                    sfxClip = Resources.Load<AudioClip>("SFX/step-floor");
                    PlaySFX();
                    break;

                case "Luigi_Battle_Punch_wSound":
                    sfxClip = Resources.Load<AudioClip>("SFX/smrpg_mario_shell");
                    PlaySFX();
                    break;

                case "Luigi_Battle_PunchTimed_wSound":
                    sfxClip = Resources.Load<AudioClip>("SFX/smrpg_mario_hammer");
                    PlaySFX();
                    break;

                default:
                    Debug.LogError("Something went wrong finding the sfxClip in the cases. Check spelling");
                    break;
            }
        }
        else
        {
            Debug.LogError(ccName + " isn't known to the AudioManager. Add it to the list in AudioManger.cs");
        }
    }

    private void PlaySFX()
    {
        source.PlayOneShot(sfxClip);
    }
}

Now, at runtime, I go nuts with my character and start jumping all over the place. every once in a while, I will see this in my Console:

Luigi|Jump_down isn't known to the AudioManager. Add it to the list in AudioManger.cs
UnityEngine.Debug:LogError(Object)
SFX_Event:SetSFX() (at Assets/Scripts/SFX_Event.cs:70)

We shouldn't get far enough to see this error. I don't know how that string (ccName) is being passed or returning false in the first place because

  1. That animation doesn't have an Event that calls this script--in fact, it is read-only.
  2. I did DUPLICATE that animation, renamed it "Luigi_Jump_down_wSound", and that one DOES have an event pointing to this script, is in the list, and works in another scene. But that animation is not being used by any animation states that get accessed in THIS scene. is Unity sometimes confusing the original jump_down animation for the one I duplicated?

I am sorry that this is so complicated.

\$\endgroup\$
0
\$\begingroup\$

so this will frustrate somebody because of the title and all, but I think the problem has nothing to do with substrings and everything to do with (as usual) transitions between animation states that have animation events and those that do do not. I am getting error logs for other animation states that have no events in them.

My theory is that an animation that does have the event calling SetSFX() transitions to an animation without the event, while that function is called. So it is checking against an animation it should not be.

I can fix this by turning off Exit Time and setting Duration to 0, but my animations will be jankier. I will have to think how I want to resolve this. It isn't actually hurting the game, it is just annoying. That something is quietly misfiring a few times a minute.

| improve this answer | |
\$\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.