Snapování pomocí triggerů
Snapování pomocí triggerů
Když už jsme si popsali, jak fungují triggery, jedno z hlavních využití může být snapování objektů
tzn. při přiblížení objektu do určité oblasti se uzamkne v chtěné poloze (např. na souřadnicích triggeru) a možnost vyvolat nějakou akci. Příklady, kdy se toto může hodit:
- Možnost si vyskládat objekty na nějaké ploše (např. poličce)
- Oblékání postavy
- V únikové hře jako mechanismus pro řešení hádanky
a další
Princip
Snapování funguje na základě, že dostaneme objekt do triggeru a ten zareaguje transformací souřadnic daného objektu na místo, kde ho chceme, nastaví správnou rotaci a nastaví vlastnosti objektu, aby se nehybal a v dané pozici zůstal.
Další detaily, co se má stát, jsou ve vaší moci a právě vlastní implementace vám dává tuto možnost. Například:
- Pokud s objektem manipulujete, tak jestli se akce vykoná ihned nebo po puštění objektu
- Fixní/relativní cíl snapování
- Pro jaké objekty tento snapper funguje
- Kontrola nad dodatečnými/návaznými akcemi
Příklad
Naimplementujeme si kouzelný podstavec, který bude umět reagovat na přítomnost speciálních klíčů a pokud obdrží ten správný, tak se klíč připevní a vypíše se 3D textem tajné heslo, jinak se zabarví na červenou.
Kouzelné klíče
Začneme nejdřív implementací kouzelných klíčů. Aby nebylo třeba externích modelů můžeme si vzít např. 3D Sphere. Vytvoříme si 3 stejně velké a odlyšíme je od sebe různě barevnými materiály. Zároveň je potřeba přidat klíči komponentu RigidBody pro zapojení fyziky.
K ní vytvoříme script komponentu Key
, která bude obsahovat potřebné informace a bude zároveň sloužit jako typový identifikátor, na který bude trigger reagovat.
Obsah skriptu Key
:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Key : MonoBehaviour
{
//color of the key
[SerializeField] public string color;
//message that is hidden in the key, to be displayed
[SerializeField] public string secretMessage;
//bool if this key is being held, this is being set up by grabbing object - hand in VR
//find this interaction and you can change this bool by:
//objectToBePickedUp.GetComponent<Key>().isHeld = true/false;
[HideInInspector] public bool isHeld;
//Snaps key to specified position and freezing it
public void Snap(Vector3 pos)
{
//getting rigid body of key object, gameObject refers to object that is script attached to
Rigidbody rb = gameObject.GetComponent<Rigidbody>();
//"freezing" the object
rb.velocity = Vector3.zero;
rb.useGravity = false;
rb.isKinematic = true;
//snapping to position given by trigger
gameObject.transform.position = pos;
}
//unfreezing
public void Free()
{
Rigidbody rb = gameObject.GetComponent<Rigidbody>();
rb.useGravity = true;
rb.isKinematic = false;
}
}
zkontrolujte komentáře, je třeba něco nastavit bokem
Nesmíme zapomenout nastavit hodnoty v inspektorovi.
Kouzelný podstavec
Abychom si opět vystačili bez extreních assetů, tak použijeme Cube jako základ, nad ním Sphere, který bude reprezentovat trigger, a 3D Text pro zobrazení tajného hesla.
- Trigger materiál nakonec není důležitý, můžete nechat na default
- Trigger nastavíme o trošičku menší než klíče, aby se nám klíč nemohl v triggeru schovat + nezapomenout na zakliknulí
Is Trigger
!
Když už máme stolek připravený nezbývá nic jiného, než naimplementovat snapovací trigger. Opět vytvoříme novou skript komponentu - KeyTrigger
k objektu KeyTrigger(Sphere nad podstavcem).
Obsah skriptu KeyTrigger
:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class KeyTrigger : MonoBehaviour
{
//determines which key is the correct one and bears the secret message
[SerializeField] public string correctKeyColor;
//this object will show the secret message when correct key is attached
[SerializeField] public GameObject textObject;
//highlight materials that can be setup in inspector
[SerializeField] public Material correctHighlightedMaterial;
[SerializeField] public Material wrongHighlightedMaterial;
[SerializeField] public Material unhighlightedMaterial;
//if correct key is snapped, disable this trigger
[HideInInspector] public bool hasSnapped = false;
private Key triggeringKey;
void OnTriggerEnter(Collider other)
{
//if none key is attached
if(hasSnapped == false)
{
triggeringKey = other.GetComponent<Key>();
//if key enters trigger and none key is currently snapped
if (triggeringKey != null)
{
//checking key color
if (triggeringKey.color == correctKeyColor)
{
//mark trigger green that object can be snapped
gameObject.GetComponent<MeshRenderer>().material = correctHighlightedMaterial;
//if we drop it inside the trigger, snap it
if (triggeringKey.isHeld == false)
{
Vector3 snapPosition = gameObject.transform.position;
triggeringKey.Snap(snapPosition);
hasSnapped = true;
//show the secret text
textObject.GetComponent<TextMesh>().text = triggeringKey.secretMessage;
}
}
//else highlight this trigger wrong
else
{
gameObject.GetComponent<MeshRenderer>().material = wrongHighlightedMaterial;
}
}
}
}
void OnTriggerExit(Collider other)
{
Key exitter = other.GetComponent<Key>();
if (exitter != null)
{
//if attached key exits the trigger
if (exitter == triggeringKey)
{
textObject.GetComponent<TextMesh>().text = "";
hasSnapped = false;
}
exitter.Free();
gameObject.GetComponent<MeshRenderer>().material = unhighlightedMaterial;
triggeringKey = null;
}
}
}
A na závěr ještě nastavit hodnoty v inspektoru. Correct Key Color
můžeme nastavit na libovolnou barvu správného klíče. Text Object
je reference na 3D text objekt, doplníme zde, že z Hierarchy drag’n’dropem přetáhneme instanci 3D textu. A v poslední řadě doplníme materiály (já jsem zde doplnil sytě zelenou pro correct a sytě červenou pro incorrect) opět drag’n’dropem z Asset složky s materiály nebo rozklikem a vybráním ze seznamů materiálů.
Hotovo! Vyzkoušejte, jak trigger reaguje na klíče různych barev.