Skip to content

t1k:unity:rendering:feel-juice

FieldValue
Modulerendering
Version3.1.7
Effortmedium
Tools
/t1k:unity:rendering:feel-juice
[feature-name | chaosforge | screen-shake | haptics | loot-toast]

MoreMountains Feel v5.9.1 integration guide for Unity 6 + DOTS-AI. Feel is Mono-only — never call from Burst/ISystem. Use the bridge pattern.

You want to…Action
Decide if Feel is right for this featureDecision Matrix
Wire Feel to DOTS eventsBridge Pattern
Configure an MMF_PlayerMMF_Player Anatomy
Add haptics on iOS/AndroidNiceVibrations Guide
Debug a Feel integrationGotchas
See ChaosForge exampleChaosForge Integration

Package: Assets/Feel/ — MMFeedbacks + MMTools + NiceVibrations 4.1.2 Version: v5.9.1 | Engine: Unity 6000.3.9f1 | Pipeline: URP only

Use Feel only for presentation-layer polish — sounds, haptics, screen shake, UI toasts, particles. Never for gameplay logic.

Signal typeOwner
Floating damage numbersDamageNumberSystem (DOTS lib) — NOT Feel
Hit flashHitFlashTriggerSystem + HitFlashAnimateSystemNOT Feel
Hit stop (slow-mo frame)HitStopSystem + HitStopEventNOT Feel (TimeScale conflict)
Crit damage variantDamageNumberStyleSO.crit branch — NOT Feel
Screen shake (trigger)CameraTraumaAuthoring + TraumaShakeSystem — keep producer
Screen shake (consumer)Feel MMF_CinemachineImpulsereplace CinemachineCameraBridge
Death dissolve VFXHybrid: DOTS triggers dissolve animation; Feel adds debris/audio/haptics
Loot drop toastFeel wins: MMF_Position + MMF_CanvasGroup + MMF_Sound + MMF_NiceVibrations
Boss phase shakeFeel MMF_Player variant — replace BossPhaseShakeSystem consumer

Full 9-item ChaosForge checklist: Decision Matrix

Feel is Mono-only (main-thread, managed heap). The canonical bridge:

  1. DOTS ISystem (Burst) writes DynamicBuffer<FeelEvent> on an ECS singleton entity
  2. FeelCombatBridge MonoBehaviour polls the buffer in LateUpdate()
  3. Bridge calls mmf_player.PlayFeedbacks(position, intensity)
  4. Bridge clears the buffer

NEVER call Feel from inside ISystem.OnUpdate, a Job struct, or any [BurstCompile] context. Results in UnityException: main thread only.

Full implementation: DOTS Bridge Pattern

MMF_Player (formerly MMFeedbacks) is the runtime container. Key fields:

  • Feedbacks list — ordered; each entry has Delay, Timing, Label
  • Initialization ModeStart (default), Awake, or Script (call Initialization() manually)
  • Can Play While Already Playing — set per feedback; pool exhaustion risk if unchecked
  • Cooldown — global re-trigger guard (seconds)
  • MMChannelData — cross-component routing by channel ID

API: PlayFeedbacks(), PlayFeedbacks(Vector3 position, float intensity), StopFeedbacks(), PauseFeedbacks(), PlayFeedbacksInReverse()

Full field reference: MMF_Player Anatomy

Performance Budget (Mobile — Snapdragon 665+)

Section titled “Performance Budget (Mobile — Snapdragon 665+)”
  • Total Feel budget: 5–10ms/frame at 60 FPS (portrait 2160×1080)
  • Concurrent event ceiling: ~50 events/frame
  • NiceVibrations: 0.1ms overhead; Android vibrator is async (fire-and-forget)
  • Screen shake: Cinemachine Impulse < 0.5ms; MMF_CameraShake < 0.3ms
  • Particle bursts: cap at 200 particles/burst for mobile; use ParticleSystem.Emit(n) not Play
  • NiceVibrations requires Assets/Feel/NiceVibrations/Scripts/... in any assembly that calls it. iOS 6s+ and Android API 26+ only. Desktop = no-op (safe).
  • URP post-processing feedbacks (bloom, vignette) need Universal RP package AND Post Process Layer NOT enabled via HDRP path. See Gotchas #7.
  • Coroutine-based feedbacks (MMF_WaitForSeconds, MMF_Hold) ignore Time.timeScale. Use TimescaleModes.Unscaled for slow-mo compatibility. See Gotchas #5.
  1. Triggering Feel inside entity iteration → frame hitch
  2. Cross-thread invocation → UnityException: main thread only
  3. Feel refs in SubScene → broken after bake — keep in main scene
  4. NiceVibrations time skew — call same frame as visual
  5. Coroutines ignore timeScale — use Unscaled mode in slow-mo
  6. Pool exhaustion under high event rate — check IsPlaying before re-trigger
  7. URP/HDRP post-process parity gaps
  8. Prefab variant corruption after MMF_Player edit

All expanded with symptom / cause / fix: Gotchas