Odwołanie się do obiektu

Ogólne pytania na temat Unity3D

Odwołanie się do obiektu

Postprzez rubesom » 02 Cze 2019, 13:53

Hej

Jak to działa w Unity, że kiedy chcę zrobić poruszanie się obiektu to muszę publicznie udostępnić obiekt
Kod: Zaznacz wszystko
Rigidbody
i przypisać do niego jakiś obiekt w Unity. A dla
Kod: Zaznacz wszystko
Transform.rotation
wystarczy, że dany kod jest przypisany do obiektu i nie muszę tworzyć osobnego obiektupublicznego?
rubesom
 
Posty: 25
Rejestracja: 23 Paź 2013, 18:27
Has thanked: 0 time
Been thanked: 0 time

Re: Odwołanie się do obiektu

Postprzez Ether_141 » 02 Cze 2019, 14:12

Klasa GameObject, zawiera odwołanie do Transform już sama w sobie. Jak wiesz każdy GameObject musi mieć Transform, więc żeby ułatwić zdobycie referencji do tej klasy Transform no to jest już zmienna .transform w klasie GameObject. Możesz też zrobić oczywiście zmienną Transform i przypisać do niej gameObject.GetComponent<Transform>(), ale po co? GameObject musi zawierać klasę Transform, ale już nie musi mieć Rigidbody, więc jeśli klasa GameObject miała by referencje do rigidbody już sama w sobie, to gdyby GameObject nie miał Rigdbody, to ta zmienna (np. gameObject.rigidbody), zwracała by null. Możesz sobie napisać samemu taką zmienną, która będzie rozszerzeniem klasy GameObject i w której będzie się znajdować Rigidbody z tego game objectu, jeśli będzie nałożony na ten game object rigidbody, żeby sobie zobaczyć na czym to polega. To chyba takie podstawy programowania obiektowego.
Awatar użytkownika
Ether_141
 
Posty: 427
Rejestracja: 29 Sie 2015, 11:47
Has thanked: 0 time
Been thanked: 0 time

Re: Odwołanie się do obiektu

Postprzez Hostur » 02 Cze 2019, 17:07

Odwołanie do "transform" wewnątrz game objectu jest wywołaniem propercji która wygląda tak:
Kod: Zaznacz wszystko
protected Transform transform => GetComponent<Transform>();

Każde odwołanie do transforma bez cachowania go
Kod: Zaznacz wszystko
var _transform = transform;

Będzie więc wołaniem GetComponent, jeśli masz dużo obiektów, które operują na transformie to zapisuj go w jakiejś zmiennej.

Jeśli masz klasy o wspólnych cechach, takich jak posiadanie rigidbody, to w programowaniu obiektowym dobrym wyjściem będzie stworzenie klasy pochodnej
Kod: Zaznacz wszystko
[RequireComponent(typeof(Rigidbody)]
public abstract class PhysicsBehaviour : MonoBehaviour
{
  internal Rigidbody rigidbody => GetComponent<Rigidbody>();
  // Lub lepiej
  internal Tranfrom _transform;
  internal Rigidbody _rigidbody;

  private void Awake()
  {
    _transform = transform;
    _rigidbody = GetComponent<Rigidbody>();
    OnAwake();
  }

  protected virtual void OnAwake()
  {
  }
}


Publicznie udostępniasz Rigidbody kiedy używasz go "z zewnątrz".
Pytanie jest takie, czy jesteś pewien, że nie da się tego zrobić lepiej z zachowaniem prywatnego rigidbody dla obiektu?

Zawsze możesz wystawić funkcję
Kod: Zaznacz wszystko
public void ApplyForce(Vector3 force) => _rigidbody.AddForce(force);


lub bardziej abstrakcyjnie jak już chcemy boiektow

Kod: Zaznacz wszystko
public interface IForceVulnerable
{
  void ApplyForce(Vector3 force);
}

public void Ball : PhysicsBehaviour, IForceVulnerable
{
  public void ApplyForce(Vector3 force)
  {
    _rigidbody.AddForce(force);
  }
}
Hostur
 
Posty: 707
Rejestracja: 05 Sie 2015, 07:36
Has thanked: 0 time
Been thanked: 0 time

Re: Odwołanie się do obiektu

Postprzez rubesom » 03 Cze 2019, 11:09

Brakuje mi wiedzy o typach generycznych i przez to nie rozumiem zapisu ze strony https://docs.unity3d.com/ScriptReference/Rigidbody-velocity.html

Kod: Zaznacz wszystko
public Rigidbody rb;
rb = GetComponent<Rigidbody>();
rb.velocity = new Vector3(0, 10, 0);

Pierwsza linijka to referejncja do obiektu klasy Rigidbody. Druga to użycie metody GetComponent z zadeklarowanym typem Rigidbody bez podania żadnych parametrów?
I nie rozumiem czemu trzeba było zrobić w ten sposób, żeby w trzeciej linijce zadeklarować użycie metody Velocity z konkretnym konstruktorem.
Da się to przedstawić na jakimś prostym przykładzie co się pod tym kryje?
rubesom
 
Posty: 25
Rejestracja: 23 Paź 2013, 18:27
Has thanked: 0 time
Been thanked: 0 time

Re: Odwołanie się do obiektu

Postprzez lozaf2002 » 03 Cze 2019, 11:55

Nie musisz robić w ten sposób.

Możesz po prostu zrobić GetComponent<Rigibody>().velocity = (...). Jednak lepiej sobie gdzięs ten komponent zapisać jeśli velocity będziemy zmieniac czesciej (tak jak jest zapisany do zmiennej rb w twoim przykladzie).

I .velocity to nie metoda. Jest to wartość pędu (?) w konkretnych osiach - dlatego jest podany Vector3 (w twoim przykladzie w osi Y jest 10 czyli obiekt bedzie sie poruszal w górę.
lozaf2002
 
Posty: 3
Rejestracja: 07 Lut 2019, 09:46
Has thanked: 0 time
Been thanked: 0 time

Re: Odwołanie się do obiektu

Postprzez rubesom » 03 Cze 2019, 12:00

lozaf2002 napisał(a):Nie musisz robić w ten sposób.

Możesz po prostu zrobić GetComponent<Rigibody>().velocity = (...). Jednak lepiej sobie gdzięs ten komponent zapisać jeśli velocity będziemy zmieniac czesciej (tak jak jest zapisany do zmiennej rb w twoim przykladzie).

I .velocity to nie metoda. Jest to wartość pędu (?) w konkretnych osiach - dlatego jest podany Vector3 (w twoim przykladzie w osi Y jest 10 czyli obiekt bedzie sie poruszal w górę.


Ale mi chodzi o sam kod, którego nie rozumiem, nie wiem co robi ta linijka:
Kod: Zaznacz wszystko
rb = GetComponent<Rigidbody>();

Do zmiennej referencyjnej przypisuję wynik metody GetComponent o typie parametru Rigidbody bez podania żadnego parametru? Co robi ta linijka kodu, po co ona jest?
rubesom
 
Posty: 25
Rejestracja: 23 Paź 2013, 18:27
Has thanked: 0 time
Been thanked: 0 time

Re: Odwołanie się do obiektu

Postprzez lozaf2002 » 03 Cze 2019, 12:08

Metoda GetComponent<>() wyciąga komponent podpięty pod obiekt na któym jest ten konkretny skrypt. Ona nie generuje tego rigibody tylko pobiera istniejacy.

Czyli masz obiekt z Rigidbody i twoim skryptem. W nim wywolujesz metode GetComponent<Rigidbody>() i ona zwraca wlasnie ten komponent.
lozaf2002
 
Posty: 3
Rejestracja: 07 Lut 2019, 09:46
Has thanked: 0 time
Been thanked: 0 time

Re: Odwołanie się do obiektu

Postprzez Hostur » 03 Cze 2019, 12:13

Jest wymienna z GetComponent(typeof(Rigidbody));
Ona szuka na tym obiekcie (dziedziczysz ją z MonoBehaviour) innego skryptu także dziedziczącego z MonoBehaviour i jeśli takowy znajdzie to przypisze go do zmiennej.

To to samo co "this.GetComponent<Rigidbody>()" lub "this.GetComponent(typeof(Rigidbody))"
Nie pisałeś wcześniej w C#? Generic jest tak powszechny że ciężko go już tłumaczyć.

Konstruktory tablic, list itp są generyczne inaczej musiałbyś deklarować nową klasę dla każdego rodzaju typu jaki np tablica może przyjąć.
Zamiast
Kod: Zaznacz wszystko
public class ListOfIntegers
{
  private int[] _values;
  public int this[int index] { get => _values[index]; set => _values[index] = value }
  // itp
}


masz
Kod: Zaznacz wszystko
public class List<T>
{
  private T[] _values;
  ...
}


Typ jest określany w trakcie kompilacji dużo by o tym pisać zamiast tego napisz sobie jakieś generyczne metody/klasy to się przyzwyczaisz.


Edit:
Metoda GetComponent jest publiczna więc możesz jej użyć też na innym obiekcie
Ten przykład jest paskudny pod względem architektury kodu ale..
FindObjectOfType<SomeClass>().GetComponent<OtherClass>().SetValueFromEther(5);
Hostur
 
Posty: 707
Rejestracja: 05 Sie 2015, 07:36
Has thanked: 0 time
Been thanked: 0 time


Wróć do Wsparcie Unity

Kto jest na forum

Użytkownicy przeglądający to forum: Brak zarejestrowanych użytkowników oraz 2 gości