niedziela, 9 kwietnia 2017

[DSP2017] 12# Holowizja - rzut piłką w pokoju

Weekend, najwyższy czas już coś napisać. Mam na tapecie jeszcze co najmniej parę koncepcji związanych z HoloLens czy Unity, które chciałbym tutaj w najbliższym czasie wypróbować. Nie ukrywam, że z fizycznymi okularami tych rzeczy byłoby więcej i mogłyby być jeszcze ciekawsze jak choćby  na blogu https://mtaulty.com/ prosto z UK. Tym niemniej podziałamy wszędzie tam, gdzie będzie to możliwe.

Dziś przyszło mi do głowy, by porzucać sobie piłką po pokoju. W Unity możemy związać siłę z wybranym przedmiotem, nie musi to być grawitacja, o której kiedyś już wspominałem.

Na warsztat wziąłem scenę z HoloVision7, która zamieniła się dziś w HoloVision9. Jednak zanim do tego doszło miałem problem z załadowaniem projektu do Unity, zresztą nie tylko tego. Stało się to pobraniu moich źródeł z githuba. Przy każdym skrypcie w inspektorze pojawił się żołty trójkąt informujący o jego niezaładowaniu. Koniec końców zrobiłem sobie na boku nowy projekt w Unity, zaimportowałem do niego HoloToolkit (dla kompatybilności HoloToolkit-Unity-v1.5.5.0.unitypackage, ale wiem jest już nowszy) i okazało się, że w pobranych z githuba źródłach nie było wszystkich plików z HoloToolkit (plugin dla x64 i x86), a także plików *.rsp w katalogu Assets. Po ich przegraniu mogłem dalej działać.

Kamera na scenie otrzymała wcześniej używany już skrypt SetGlobalListener, a także nowy o nazwie ThrowBall, który został przedstawiony poniżej:

public class ThrowBall : MonoBehaviour, IInputClickHandler
{
    public float ForceMagnitude = 300f;   

    public void OnInputClicked(InputEventData eventData)
    {
        Throw();
    }

    private void Throw()
    {
        var ball = GameObject.CreatePrimitive(PrimitiveType.Sphere);
        ball.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);

        var rigidBody = ball.AddComponent<Rigidbody>();
        rigidBody.mass = 0.5f;
        rigidBody.position = transform.position;

        var transformForward = transform.forward;
        transformForward = Quaternion.AngleAxis(-10, transform.right) * transformForward;

        rigidBody.AddForce(transformForward * ForceMagnitude);
    }
}

Każde “kliknięcie” użytkownika (air tap) powoduje wyrzucanie piłki. Tworzony jest dynamicznie obiekt typu sfera, do którego dodawany jest element rigid body. Do niego przykładamy siłę o określonej wartości i kierunku. Piłka ma masę i może się zderzać z innymi przedmiotami lub ścianami pokoju.

Zamiast sześcianu i kuli stworzyłem trzy sześciany, tak że na dwóch stoi trzeci. Do każdego z nich także dodałem rigid body. Niestety sześciany po uruchomieniu aplikacji spadały w nicość zanim siatka pokoju się rysowała. W związku z tym opadnięcie sześcianów na podłogę wyzwalam 10 sekund po starcie.  Do każdego z nich przypiąłem taki skrypt:

public class GravityAfterSeconds: MonoBehaviour
{

    void Start()
    {
        StartCoroutine(Shoot());
    }

    IEnumerator Shoot()
    {

        yield return new WaitForSeconds(10);
        OnShoot();
    }

    public void OnShoot()
    {
        if (!this.GetComponent<Rigidbody>())
        {
            var rigidbody = this.gameObject.AddComponent<Rigidbody>();
            rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous;
        }
    }
}

Aha, zapomniałem dodać, że zmieniłem sobie czerwony materiał siatki pokoju na zielony, ale nie jest to bardzo istotne w tym scenariuszu. Na “dzień dobry” otrzymujemy widok:

Capture7

Klikam (prawy przycisk myszy lub Enter na emulatorze), wylatuje kula, uderza w “misterną” konstrukcję sześcianów, która się rozpada. Oto co z niej pozostało:

Capture8

Można uznać to za pierwszy mały krok w kierunku gry opartej o strzelanie. Nie wykluczam, że będzie jakaś kontunuacja tego wątku. Bo kto nie chciałby postrzelać sobie do postaci wychodzących ze ścian pokoju?

Do następnego razu.

Brak komentarzy: