the symptom, in your words

"BuildHash() overrides only compile on PanelComponent, not on a plain Component"

✓ verified on 26.07.15a
lane Building UIposted

▸ SYMPTOM

A headless dotnet build fails with:

snippet
CS0115: 'MyLogicComponent.BuildHash()': no suitable method found to override

on a component that is not a UI panel — even though the same BuildHash() => 0; line compiles fine on your panel classes.

▸ CAUSE

protected override int BuildHash() is a member of PanelComponent, not of a plain Component. A logic-only Component (state + per-frame drive, no render tree) has no BuildHash to override, so the override has nothing to bind to and the compiler rejects it with CS0115.

It's easy to hit when you split a UI feature into two components on one ScreenPanel — a logic Component that owns state and drives per frame, sitting beside its PanelComponent view — and then reflexively copy the "keep the tree stable" BuildHash() => 0; idiom (which every PanelComponent in the codebase uses) onto the logic component too.

▸ FIX

Delete the BuildHash override from the plain Component. It has no render tree to hash, so it doesn't need one — only the PanelComponent view does:

snippet
// logic Component — NO BuildHash override
public sealed class MyLogicComponent : Component
{
    // state + per-frame drive only
}

// view — BuildHash lives HERE
public sealed class MyView : PanelComponent
{
    protected override int BuildHash() => 0;   // keep the tree stable
}

▸ WHY IT WORKS

BuildHash exists so the panel system can decide whether a panel's render tree needs rebuilding — it's meaningful only where there is a tree, i.e. on PanelComponent. A logic component contributes no markup, so there is nothing for a hash to stabilize; the override isn't just unnecessary, there's no base method for it to override. Keeping BuildHash on the view and off the logic half of a split UI feature matches the type each responsibility actually lives on.

Verified on engine 26.07.15a: seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?
changelog
  • Published

Want to know when new guides or fixes drop? Join the community to help build this out. Report gotchas, flag outdated fixes, or just lurk.

Join the Discord