• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Camera Switch, dwoje postaci

Object Storage Arubacloud
0 głosów
113 wizyt
pytanie zadane 22 stycznia 2020 w OpenGL, Unity przez Alan Kruszyński Obywatel (1,410 p.)

Mam do zrobienia mały projekt na uczelnię, jednym z zagadnień jest przełączanie kamery między obiektami gracza 

Stworzyć komponent pozwalający na wybór obiektu, którym steruje gracz: klawisz 1 – pierwszy obiekt, 2 – drugi obiekt. Należy zwrócić uwagę na to, żeby po przełączeniu obieków, obiekt, którym gracz przestał sterować kontynuował lot aż do uderzenia w ziemię. Uwaga: Do każdej kamery przypięty jest komponent AudioListener. Domyślnie jest on aktywny. W grze może być jednak tylko jeden aktywny tego rodzaju komponent. Dlatego, przy przeączaniu kamer należy odpowienią instancję klasy AudioListener zrobić aktywną, a pozostałe nieaktywnymi (wyszukiwanie komponentu – GetComponent lub GetComponentInChildren);

Naskrobałem coś takiego podglądając trochę jak wygląda skrypt u kolegi z grupy

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraControl : MonoBehaviour
{
    public GameObject Camera;
    public GameObject Camera1;

    public GameObject Control;
    public GameObject Control2;
    // Start is called before the first frame update
    void Start()
    {


    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetButtonDown("v1"))
        {
            StartCoroutine(viewone());
        }
        if (Input.GetButtonDown("v2"))
        {
            StartCoroutine(viewtwo());
        }
    }

    IEnumerator viewone()
    {
        yield return new WaitForSeconds(0.01f);
        Camera.SetActive(true);
        Camera1.SetActive(false);

        Control.GetComponent<PlayerControler>().enabled = true;
        Camera.GetComponent<AudioListener>().enabled = true;
        Camera1.GetComponent<AudioListener>().enabled = false;
        Control2.GetComponent<RigidbodyControler>().enabled = false;
        //Control2.SetActive (false);
    }
    IEnumerator viewtwo()
    {
        yield return new WaitForSeconds(0.01f);
        Camera1.SetActive(true);
        Camera.SetActive(false);
        while (!Control.GetComponent<CharacterController>().isGrounded) { yield return new WaitForSeconds(0.01f); }
        Control.GetComponent<PlayerControler>().enabled = false;
        Camera.GetComponent<AudioListener>().enabled = false;
        Camera1.GetComponent<AudioListener>().enabled = true;
        Control2.GetComponent<RigidbodyControler>().enabled = true;
        //Control2.SetActive (true);
    }
}

Przypiąłem to do pustego obiektu w świecie gry, niestety to nie działa, a konkretnie nie reaguje wedle zamierzeń (klawisz 1 i 2 powinny przełączać między obiektami gracza), jedynie się kompiluje i podczepia bez problemu..
Mam dwa obiekty gracza:

1. Player1 - kontrolowany przez komponent Charater Controller z podpiętym skryptem PlayerControler

2. Player2 - kontrolowany przez komponent Rigidbody z podpiętym skryptem RigidbodyControler

Wiem z polecenia że przy przełączaniu kamery trzeba odpowiednie instancje obiektów uaktywniać, a inne deaktywować. Nie dopytałem kolegi jak rozróżnia kamery, ponieważ nie miał ich otagowanych czy nazwanych różnie, nie mogę się z nim skontaktować do weekendu. Nie mam pomysłu jak się za to zabrać skutecznie. 

Proszę o pomoc wskazanie błędów. Może jakieś linki do sprawdzonych tutoriali (oglądałem ich trochę, wszędzie skrypty są dość obszerne i niespecjalnie odpowiadają wymogom, a ten tutaj w oryginalnej wersji nie był ani znaku dłuższy i działął w projekcie kolegi). 

2 odpowiedzi

0 głosów
odpowiedź 23 stycznia 2020 przez MsMaciek123 Pasjonat (24,760 p.)

OJ, kolego, nie ładnie tak kopiować od innych.

 

którym gracz przestał sterować kontynuował lot aż do uderzenia w ziemię.

Gracz ma nim nadal sterować?

 

1. Działanie Input.GetButton Polega na tym, że w ustawieniach projektu wybierasz "Sterowanie" i tam mówisz jaki przycisk odpowiada "v1" oraz "v2". Znacznie lepszą metodą jest Input.GetKey

if(Input.GetKeyDown(KeyCode.Space))
{
    print("space key was pressed");
}

Spis wszystkich przycisków: docs.unity3d.com/ScriptReference/KeyCode
przykład: Input.GetKeyDown(KeyCode.Alpha1)

 

2. Funkcja Update() wykonuje się co klatkę, czyli co klatkę sprawdzasz, czy jakiś przycisk nie został naciśnięty.

Wpisywanie dwóch if'ów może spowodować lekkie problemy gdy ktoś naciśnie oba przyciski naraz.

if (warunek)
{
    //kod1
}
else if (warunek)
{
    //kod2
}

Jeżeli pierwszy warunek zostanie spełniony to wykona się tylko kod1, w przeciwnym razie sprawdzi drugi warunek, jeżeli będzie spełniony to wykona się kod2, jeżeli nic to nic sie nie wykona.

 

3. Używanie Coroutine ma swoje zalety i wady. W tym przypadku lepiej jest użyć zwykłych funkcji.

4. Publiczne zmienne jakie zadeklarujesz pojawią ci się w inspektorze, jeżeli masz zaznaczony obiekt w którym jest twój skrypt. Do tych zmiennych musisz przypisać wartość (wystarczy że przeciągniesz odpowiednie obiekty z hierarchii do inspektora do tych pól)

public GameObject Camera1;
public GameObject Camera2;

public GameObject Control1;
public GameObject Control2;

 

5. Ta linijka jest dla korutyn, bo one muszą coś zwracać

yield return new WaitForSeconds(0.01f); 

 

6. Kod

void viewOne()
{
	Camera1.SetActive(true); //aktywujemy pierwszą kamerę
	Camera2.SetActive(false); //dezaktywujemy drugą kamerę

	Control1.GetComponent<PlayerControler>().enabled = true; //aktywujemy w pierwszej postaci (chyba to jest postać) komponent PlayerControler
	Camera1.GetComponent<AudioListener>().enabled = true; //aktywujemy w pierwszej kamerze audiolistener
	
	Camera2.GetComponent<AudioListener>().enabled = false; //dezaktywujemy w drugiej kamerze audiolistener
	Control2.GetComponent<RigidbodyControler>().enabled = false; //dezaktywujemy w drugiej postaci komponent RigidbodyControler
}

void viewTwo()
{
	if(!Control1.GetComponent<CharacterController>().isGrounded) { return; } //jeżeli pierwsza postać nie jest na ziemi to tutaj kończymy wykonywanie funkcji

	Camera2.SetActive(true); //aktywujemy drugą kamerę
	Camera1.SetActive(false); //dezaktywujemy pierwszą kamerę
	
	Control1.GetComponent<PlayerControler>().enabled = false; //dezaktywujemy w pierwszej postaci komponent PlayerControler
	Camera1.GetComponent<AudioListener>().enabled = false; //dezaktywujemy w pierwszej kamerze audiolistener
	
	Camera2.GetComponent<AudioListener>().enabled = true; //aktywujemy w drugiej kamerze audiolistener
	Control2.GetComponent<RigidbodyControler>().enabled = true;  //aktywujemy w drugiej postaci komponent RigidbodyControler
}

 

7. Co do linijki

if(!Control1.GetComponent<CharacterController>().isGrounded) { return; }

// \/ to jest to samo /\

if(!Control1.GetComponent<CharacterController>().isGrounded)
{
    return;
}

//  \/ to jest to samo /\

if(Control1.GetComponent<CharacterController>().isGrounded == false)
{
    return;
}

 

0 głosów
odpowiedź 23 stycznia 2020 przez Alan Kruszyński Obywatel (1,410 p.)

Czyli finalnie mamy to w takiej postaci

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraControl : MonoBehaviour
{
    public GameObject Camera1;
    public GameObject Camera2;

    public GameObject Control1;
    public GameObject Control2;
    // Start is called before the first frame update
    void Start()
    {


    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetButtonDown("v1"))
        {
            StartCoroutine(viewOne());
        }
        if (Input.GetButtonDown("v2"))
        {
            StartCoroutine(viewTwo());
        }
    }

    void viewOne()
    {
        Camera1.SetActive(true); //aktywujemy pierwszą kamerę
        Camera2.SetActive(false); //dezaktywujemy drugą kamerę

        Control1.GetComponent<PlayerControler>().enabled = true; //aktywujemy w pierwszej postaci (chyba to jest postać) komponent PlayerControler
        Camera1.GetComponent<AudioListener>().enabled = true; //aktywujemy w pierwszej kamerze audiolistener

        Camera2.GetComponent<AudioListener>().enabled = false; //dezaktywujemy w drugiej kamerze audiolistener
        Control2.GetComponent<RigidbodyControler>().enabled = false; //dezaktywujemy w drugiej postaci komponent RigidbodyControler
    }
    void viewTwo()
    {
        if (!Control1.GetComponent<CharacterController>().isGrounded) { return; } //jeżeli pierwsza postać nie jest na ziemi to tutaj kończymy wykonywanie funkcji

        Camera2.SetActive(true); //aktywujemy drugą kamerę
        Camera1.SetActive(false); //dezaktywujemy pierwszą kamerę

        Control1.GetComponent<PlayerControler>().enabled = false; //dezaktywujemy w pierwszej postaci komponent PlayerControler
        Camera1.GetComponent<AudioListener>().enabled = false; //dezaktywujemy w pierwszej kamerze audiolistener

        Camera2.GetComponent<AudioListener>().enabled = true; //aktywujemy w drugiej kamerze audiolistener
        Control2.GetComponent<RigidbodyControler>().enabled = true;  //aktywujemy w drugiej postaci komponent RigidbodyControler
    }
}

Niestety nie mogę pozbyć się błędów w miejscu StartCoroutine(viewOne()) i StartCoroutine(viewTwo()) na początku funkcji Update(), w Visual Studio błąd CS1503. Argument "1": nie można przekonwertować z void na string. Podejrzałem jak wygląda surowy nagłówek

public Coroutine StartCoroutine(string methodName, object value = null);

Nie bardzo rozumiem sedno błędu. Argument ma być typu string ale wedle definicji to nazwa metody, więc nie ma związku chyba z faktycznym typem funkcji (co wydaje mi się jednak niemożliwe). Jednak zawsze mi wpajano że zdefiniowany argument ma być zawsze zgodny typem z tym podawanym przy wywołaniu. Za to jak zmienię void-y na IEnumerator jak podejrzałem tutaj, kompilator zwraca błąd CS0161 "Nie wszystkie linie kodu zwracają wartość". Dopisanie return-a na końcu funkcji powoduje znów błąd CS0029. Dalej już nie eksperymentowałem. Podejrzewam że zaraz ktoś potraktuje mnie dobrze znanym "weź se tutorial obczaj" ale niestety termin mija w weekend a ja wojuję z tym od początku tygodnia. Bardzo proszę o pomoc.

Podobne pytania

0 głosów
1 odpowiedź 163 wizyt
pytanie zadane 13 października 2019 w OpenGL, Unity przez Skipto Początkujący (300 p.)
0 głosów
0 odpowiedzi 154 wizyt
pytanie zadane 13 maja 2019 w C# przez cyrus33 Użytkownik (680 p.)
0 głosów
1 odpowiedź 103 wizyt
pytanie zadane 30 stycznia 2019 w PHP przez Greeenone Pasjonat (16,100 p.)

92,555 zapytań

141,403 odpowiedzi

319,560 komentarzy

61,941 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...