BI-PGA Programování grafických aplikací
Jdi na navigaci předmětu

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.

magicTable

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.

createSphere
setupSphere
rigidbody

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.

createScript

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.

fillScript

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.

magicTableSetup
  • 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).

addTriggerScript

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ů.

result

Hotovo! Vyzkoušejte, jak trigger reaguje na klíče různych barev.