Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Out of Range Index in UpdateMaskingOnAllSubmeshes()

A topic by Draque created Feb 14, 2026 Views: 191 Replies: 10
Viewing posts 1 to 11
(1 edit)

Ok, I am having trouble recreating this exact scenario, but the line it happens on appears below. I think this is a super edge case when materials are hot-swapped and the info member of the SuperTextMesh class is not updated in time for the call. If it fails once though, it seems to block the update happening later, as it kills the call from RecalculateMasking() before AppplyMaterials() can be called. I'm not sure whether it would work to simply return from UpdateMaskingOnAllSubmeshes() here, or if that would simply push problems downstream.

As you can see, I have a breakpoint in place here, and the next time it's hit, I will collect any relevant data that I'm able and post here. (also, I only realized as I'm looking at it now that the > should be a >=, but I didn't want to bother replacing the image ^^;).



Developer

Huhhh is this due to custom code editing the materials, or just as behaviour for STM? Just checking to be sure.

I made an update to UpdateMaskingOnAllSubmeshes last month, so was wondering if something like this would happen... still not sure why sampleInfoIndex would get out of sync with info.Count (use infoCount by the way, *that* value should be synced) but yeah I think making sure Submesh_infoIndex is greater than -1 and less than infoCount and returning otherwise would be fine. I'd really just expect this to happen when loading or something like that and correct itself, but if you can figure out the exact timing it happens, please let me know!

I am not sure of all the situations where this can come up, but I hit one just now. There's definitely something fishy going on which you can see in the inspector with the configuration error.

This is in 100% normal gameplay, btw. It's simply setting the text from one thing to another. Here's all the info I can really think to include:

info.Count = 75

Submesh_infoIndex = 167

test set to: "<e=excl=open><f=Retron2000Regular>Sooner you say goodbye, sooner you greet Din\' once again!<e=excl=close><e=excl=open> Smartsmart plan!<e=excl=close></f>"

Relevant stack trace (line counts may be slightly off due to some comments I've added while exploring code):

Void SuperTextMesh:UpdateMaskingOnAllSubmeshes () (/Users/draquethompson/Unity/Transience/Assets/Clavian/SuperTextMesh/Scripts/SuperTextMesh.cs:7473)

Void SuperTextMesh:RecalculateMasking () (/Users/draquethompson/Unity/Transience/Assets/Clavian/SuperTextMesh/Scripts/SuperTextMesh.cs:7457)

Material STMMaskableGraphic:GetModifiedMaterial (Material) (/Users/draquethompson/Unity/Transience/Assets/Clavian/SuperTextMesh/Scripts/STMMaskableGraphic.cs:328)

Material STMMaskableGraphic:GetMaterialForRendering (Int32) (/Users/draquethompson/Unity/Transience/Assets/Clavian/SuperTextMesh/Scripts/STMMaskableGraphic.cs:319)

Void STMMaskableGraphic:UpdateMaterial () (/Users/draquethompson/Unity/Transience/Assets/Clavian/SuperTextMesh/Scripts/STMMaskableGraphic.cs:295)

Void STMMaskableGraphic:OnRebuild () (/Users/draquethompson/Unity/Transience/Assets/Clavian/SuperTextMesh/Scripts/STMMaskableGraphic.cs:228)

Void SuperTextMesh:Rebuild (Single, Boolean, Boolean) (/Users/draquethompson/Unity/Transience/Assets/Clavian/SuperTextMesh/Scripts/SuperTextMesh.cs:1652)

Void SuperTextMesh:InternalRebuild (Single, Boolean, Boolean) (/Users/draquethompson/Unity/Transience/Assets/Clavian/SuperTextMesh/Scripts/SuperTextMesh.cs:1530)

Void SuperTextMesh:set_text (String) (/Users/draquethompson/Unity/Transience/Assets/Clavian/SuperTextMesh/Scripts/SuperTextMesh.cs:257)

Void Assets.Scripts.TypeToTextmesh:TypeText () (/Users/draquethompson/Unity/Transience/Assets/Scripts/UI_Scripts/TypeToTextmesh.cs:383)

Void Assets.Scripts.ConversationUI:UpdateConversation () (/Users/draquethompson/Unity/Transience/Assets/Scripts/UI_Scripts/ConversationUI.cs:436)

Void Assets.Scripts.TransConversationState:ConversationUpdated () (/Users/draquethompson/Unity/Transience/Assets/Scripts/TransConversationState.cs:41)

Void Assets.Scripts.TransConversationState:set_CurrentConversation (TransConversationNode) (/Users/draquethompson/Unity/Transience/Assets/Scripts/TransConversationState.cs:18)

Void Assets.Scripts.ConversationUI:EndCall (Boolean) (/Users/draquethompson/Unity/Transience/Assets/Scripts/UI_Scripts/ConversationUI.cs:401)

Void <>c:<AddOnclickFunctions>b__7_4 () (/Users/draquethompson/Unity/Transience/Assets/Scripts/UI_Scripts/UIControls/ConversationVerticalButtonMenu.cs:20)

Void UnityEngine.Events.InvokableCall:Invoke () (Unknown Source:0)

Void UnityEngine.Events.UnityEvent:Invoke () (Unknown Source:0)

Void Assets.Scripts.FaceButton:MainButtonClick () (/Users/draquethompson/Unity/Transience/Assets/Scripts/UI_Scripts/UIControls/FaceButton.cs:51)

Void Assets.Scripts.FaceButton:<Awake>b__23_0 () (/Users/draquethompson/Unity/Transience/Assets/Scripts/UI_Scripts/UIControls/FaceButton.cs:39)

Void UnityEngine.Events.InvokableCall:Invoke () (Unknown Source:0)

Void UnityEngine.Events.UnityEvent:Invoke () (Unknown Source:0)

Void UnityEngine.UI.Button:Press () (/Users/draquethompson/Unity/Transience/Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:70)

Void UnityEngine.UI.Button:OnPointerClick (PointerEventData) (/Users/draquethompson/Unity/Transience/Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:114)

Void UnityEngine.EventSystems.ExecuteEvents:Execute (IPointerClickHandler, BaseEventData) (/Users/draquethompson/Unity/Transience/Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:57)

Boolean UnityEngine.EventSystems.ExecuteEvents:Execute (GameObject, BaseEventData, EventFunction`1) (/Users/draquethompson/Unity/Transience/Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:272)

Void UnityEngine.InputSystem.UI.InputSystemUIInputModule:ProcessPointerButton (ButtonState, PointerEventData) (/Users/draquethompson/Unity/Transience/Library/PackageCache/com.unity.inputsystem@1.14.0/InputSystem/Plugins/UI/InputSystemUIInputModule.cs:744)

Void UnityEngine.InputSystem.UI.InputSystemUIInputModule:ProcessPointer (PointerModel) (/Users/draquethompson/Unity/Transience/Library/PackageCache/com.unity.inputsystem@1.14.0/InputSystem/Plugins/UI/InputSystemUIInputModule.cs:489)

Void UnityEngine.InputSystem.UI.InputSystemUIInputModule:Process () (/Users/draquethompson/Unity/Transience/Library/PackageCache/com.unity.inputsystem@1.14.0/InputSystem/Plugins/UI/InputSystemUIInputModule.cs:2431)

Void UnityEngine.EventSystems.EventSystem:Update () (/Users/draquethompson/Unity/Transience/Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:530


Developer

Ok, it's probably due to some sync error with infoCount and  the array of submeshes and I'll look into that tuesday, but uhh... please check the other error you seem to have on STM there!

It looks like this is a UI STM object, but you have a mesh filter and a mesh renderer attached?

I don't normally have the mesh filter and mesh renderer attached. They appeared dynamically at the same time as the bug happened. Here is a capture of what it looks like before the error occurs.


Ok, I just popped the error again now, and this time it happened without those two additional components appearing... it's possible that those got added somehow when I was screwing around and trying to force it to appear. Regardless, it popped without them being present. Same exact stack trace.

Developer

Ok, good to know!


For now, yeah just try returning if the value is out of range, and let me know if anything appears wrong! I'll be able to dig into this on tuesday

Ok, I have found a way to reliably recreate this. It's somehow tied specifically to the STMMaskableGraphic class, as when I disable it on the SuperTextMesh object,the error no longer pops. Here are the steps:

1) Start up a STM instance with the same configuration as I have above (although the Shadow doesn't seem to matter, just the STMMaskableGraphic).

2) Set the text to "<e=excl=open><f=Retron2000Regular>Hi hi!<e=excl=close> So great it is you get to meet great master of trade, Din' K'blapp (THAT'S ME). Gots all my nice stuff an' maybe you help get more?<e=excl=open> Shiny coin for hard workers!<e=excl=close></f>" (obv the font name should be something you've got)

3) Set the text to "<f=Retron2000Regular>TODO</f>"

The exception should then pop. I included the exact strings I used in case they had any effect. The callbacks I have in there only change game speech volume (not for any sounds handled by STM incidentally, so no possibility of interaction there).

(1 edit)

Also potentially relevant. This code runs immediately before the new, erroring text is set. I'm free later in the afternoon on Monday if you were interested in doing any kind of screen share to look at code being run on a system where the error is guaranteed to pop.

public void SetSpeed()
{
    var multiplier = charConvVoice.GetTextSpeedMultiplier() * ReadSpeedMultiplier;

    // invert speed multiplier, then reduce the slope of the curve to get framerate mult
    var frameMult = 1 + (1 / multiplier - 1) * 0.4f;
    if (charConvShaderAnimation != null)
        charConvShaderAnimation.FrameLengthMultiplier = frameMult;
    superTextMesh.speedReadScale = multiplier;

    if (multiplier == 1 && superTextMesh.isSpeedReading)
        superTextMesh.RegularRead();
    else if (multiplier != 1 && !superTextMesh.isSpeedReading)
        superTextMesh.SpeedRead();
}

Developer

Ok yes, I'm able to reproduce this!

I think I've got it fixed, the problem was I was storing "sampleInfoIndex" in sharedMaterialData (per-game data), when it's really something that should be in submesh data. (per-mesh data) Seems to work now that that's moved over! Will try to publish this asap.

Tysm for the fast responses and killer work you do on this resource! ^^