Het doorbreken van de fysieke grenzen: onze custom Force System in Unity

Unity is een krachtige game-engine met veel flexibiliteit en opties voor game-ontwikkelaars. Het stelt ontwikkelaars in staat om complexe en meeslepende ervaringen te creëren, en biedt een reeks functies voor physics, inclusief een krachtig ingebouwd rigidbody-systeem. Echter, voor onze game, waren de standaard rigidbody-functies van Unity, zoals addForce(), niet voldoende flexibel. We voelden dat het Unity Physics systeem te algemeen was voor onze behoeften. We hadden een fijnere controle nodig over de krachten in onze game, en daarom hebben we besloten om ons eigen Force System te creëren.

Wat wij willen is een system dat het mogelijk maakt om een personage met een onzichtbare kracht ergens naartoe te trekken, de duur en intensiteit van deze kracht in detail in te stellen, en om controle te hebben over welke krachten actief zijn en welke niet. Er zijn momenten in onze game waarop we misschien alle krachten willen bevriezen, bijvoorbeeld als een personage even stil hangt omdat hij wordt geraakt door iets, of als een object zo’n klap krijgt dat alle krachten tijdelijk worden uitgeschakeld, behalve die van de klap zelf. Maar: hoe doe je dat met een RigidBody, waar alle forces worden samengevoegd in één velocity vector?

Zwaartekracht, movement en een ‘push’ force, alle drie tegelijk aan het werk. Gevisualiseerd door ons debug systeem.

In onze nieuwe aanpak, maken we nog steeds gebruik van bepaalde Unity-functies zoals (primitive) Colliders en Raycasts, maar we hebben de standaard Rigidbody en PhysicsSystem vervangen door onze eigen ForceBody en ForceSystem. Het hart van ons systeem is de ‘Force‘. Enkele voorbeelden van forces in ons systeem zijn:

  • Een speler die wil springen – jump force
  • Een speler die zich ergens naar toe pulled – pull force
  • Een speler die objecten wegbeukt – push force
  • Een speler die enemies een klap geeft – hit force
  • Een entity die met zwaartekracht naar beneden wil vallen – gravity force
  • Bounce forces (als bijvoorbeeld enemies in fuzzy state rond stuiteren)
  • Knockback forces (als je bijvoorbeeld een combo uitvoert op enemies)

Het grote verschil met de Rigidbody forces is dat deze forces meer instellingen hebben. Zo kun je bijvoorbeeld instellen hoelang een force werkt en hoe de ‘curve’ is van de force. Ook blijven forces altijd los van elkaar bestaan en worden ze niet ‘definitief’ samengevoegd in één velocity vector. Een ‘ForceBody’ kan zo meerdere forces in een lijst actief hebben. Ook kunnen Forces gepauzeerd klaar staan om weer verder te gaan waar ze gebleven zijn

Een Force in ons systeem is ‘serializable’, wat betekent dat we deze in de Unity-editor kunnen instellen. Er zijn verschillende parameters die kunnen worden aangepast, zoals de unieke ID van de force, de richting en impact van de force, de duur van de force, en hoe deze force zich vermengt met andere forces. Je kan ook instellen of deze force de zwaartekracht uitschakelt (zolang deze force actief is) en zelfs of de force uniek is. Forces kunnen multipliers krijgen, zoals bijvoorbeeld een stack multiplier, waarbij alle huidige forces worden gestackt in één force.

Custom Property Drawer voor een Force, in dit geval onze jump Force

Om ons force systeem te gebruiken, voeg je het ForceBody component toe aan elk object dat met het force systeem moet kunnen werken. Het ForceBody component heeft verschillende methods om de forces te beïnvloeden, zoals Add, SetPosition, Remove en ClearForces.

De curve bepaald per force hoe de direction wordt verdeeld in tijd/frames
Als een curve ‘open’ eindigt, dan kun je automatisch een residual force laten genereren

Forces kunnen uiteraard ook vanuit code aangemaakt en/of gewijzigd worden. Een Callback setup biedt de mogelijkheid om te reageren op verschillende force events. Zo kunnen we bijvoorbeeld reageren op wanneer een bepaalde Force wordt geannuleerd of wanneer hij succesvol is afgerond.

We hebben properties aan de ForceBody toegevoegd, waaronder GravityScale, die verdere controle over de forces mogelijk maken.

We geloven dat onze aangepaste benadering van physics in Unity ons in staat stelt om een meer aangepaste en controleerbare ervaring te bieden voor onze spelers. Door het standaard rigidbody-systeem te vervangen door ons eigen Force System, hebben we meer grip op de fysieke interacties in onze game. Hiermee kunnen we een unieke en meeslepende gameplay-ervaring creëren die anders niet mogelijk zou zijn geweest met de standaard Unity Physics.

We blijven experimenteren en leren van dit proces, en hopen dat onze ervaringen andere game-ontwikkelaars kunnen inspireren om buiten de standaardgereedschappen te denken en hun eigen unieke systemen te bouwen.

Heb je nog vragen over ons ForceSystem? Er valt nog veel over te vertellen. Voel je altijd vrij om contact op te nemen.