Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

Unity3d - Optymalizacja


Gość henb

Rekomendowane odpowiedzi

Opublikowano

Cześć,

 

Nie będzie to tutorial, w którym wszystko jest podane na tacy. Tym razem będzie nieco inaczej. W każdym tygodniu (trwania tutoriala) będzie jedna zagadka dotycząca optymalizacji Unity. Tutaj mini regulamin:

 

1. Każda zagadka będzie miała ok. 8-10 błędów do wytknięcia.

2. Za każdy wytknięty błąd, pierwszy wytykający otrzymuje punkt.

3. Jeżeli wytykający doda jak poprawić błąd, o którym mówi dostaje dodatkowy punkt.

4. Zagadka trwa maksymalnie tydzień.

5. Jeżeli przez tydzień zagadka nie zostanie rozwiązana to ja lub ktoś z jury ją dokończy.

6. Jeżeli wystąpi powyższy punkt, przy następnej zagadce jest kumulacja.

7. Jeżeli jednak zagadka w danym tygodniu będzie rozwiązana, wygrywa osoba z największą liczbą punktów.

8. Nagrody polecą na PW.

9. Jeżeli wygrałeś w poprzednim tygodniu, to miło byłoby dać się wykazać kolejnym uczestnikom zabawy.

10. Jeżeli jednak nie chcą się wykazać przez kilka dni to śmiało bij po kolejne nagrody.

 

 

Wszelkie dodatkowe nieścisłości regulaminu postaram się wyjaśnić w tym temacie, jeżeli będą co do niego pytania.

 

Żeby nie być podejrzewanym o stronniczość przy ocenianiu i rozdawaniu punktów, poprosiłem dwójkę która zagląda do tego działu i ma pojęcie o programowaniu/unity, aby być szumnie zwanym Jury. Przywitajcie gromkimi brawami @lizus i @Sopelek997

 

A teraz... rozgrzewkowa zagadka numer 1.

 

Dwa skrypty:

 

 

using UnityEngine;
using System.Collections;
using System.IO;
using UnityEditor;
using System.Diagnostics;



public class Player : MonoBehaviour {
	private double amunicja = 15;
	public AudioClip boom;
	public AudioClip click;
	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
		GameObject ammoText = GameObject.Find ("ammo");
		AmmoGUI gui = ammoText.GetComponent<AmmoGUI>();
		if(Input.GetMouseButtonDown (0))
		{
			if(amunicja >= 0)
			{
				this.gameObject.GetComponent<AudioSource>().audio.clip = boom;
				this.gameObject.GetComponent<AudioSource>().audio.Play();
				amunicja = amunicja - 1;
				gui.UpdateGUI(amunicja);
			} else {
				audio.PlayOneShot(click);
			}
		}
	}
}

 

 

 

oraz 

 

 

 

using UnityEngine;
using System.Collections;

public class AmmoGUI : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}

	public void UpdateGUI(double wartosc) {
		this.gameObject.GetComponent<GUIText>().text = "ammo: "+wartosc;
	}
}
 

 

 

 

Do tego paczka z projektem:

https://www.dropbox.com/s/1oip1pb9nphkrrl/unity_optymalizacja1.unitypackage

Skan:

http://virusscan.jotti.org/pl/scanresult/0c5c1a081efa587108fe16661fec076faaf31f1f

GL&HF.

 

 

Jeżeli chodzi o nagrody to są nimi gry na steama.

Opublikowano

Szczerze to nwm nie wiedziałem co tu trzeba poprawić. (czy nwm ta kostka po strzale ma lecieć czy co.) Wiec naprawiłem co znalazłem i dodatkowo dodałem opcje reloadu pod R , gdyż mi sie nudziło xD.

 

using System.IO;
using UnityEditor;
using System.Diagnostics;
 
 
 
public class Player : MonoBehaviour {
private double amunicja = 15;
public AudioClip boom;
public AudioClip click;
// Use this for initialization
void Start () {
 
}
 
// Update is called once per frame
void Update () {
GameObject ammoText = GameObject.Find ("ammo");
AmmoGUI gui = ammoText.GetComponent<AmmoGUI>();
gui.UpdateGUI(amunicja);
if(Input.GetMouseButtonDown (0))
{
if(amunicja > 0)
{
this.gameObject.GetComponent<AudioSource>().audio.clip = boom;
this.gameObject.GetComponent<AudioSource>().audio.Play();
amunicja = amunicja + -1;
gui.UpdateGUI(amunicja);
} else if(amunicja ==0) {
audio.PlayOneShot(click);
}
}
if(Input.GetKey(KeyCode.R)){
amunicja = 15;
gui.UpdateGUI(amunicja);
}
 
}
}

w AmmoGUI nic nie zmieniałem.

Jeżeli jest coś jeszcze to tell me.

ps. wgl jak dodać taki ładny spoiler z kodem bo mi sie on troche psuje przy kopiowaniu.

mirajane_tag_by_raaims-d4f56kb.png


Komp:


Procesor: i5-4670k , Karta: Asus GTX 780 Ti , Płyta: ASRock H97 Perf. Cooler CPU: Raijintek NEMESIS

Opublikowano

Dodam jedynie, że nie tyle chodzi o optymalizację i poprawę błędów co o dobre praktyki, rozsądne rozwiązania problemów. Więc nie szukajcie tylko po tym co działa źle.

Opublikowano

To mam to przerobić by działało jak najwydajniej(kod jak najkrótszy) czy tylko poprawić błąd (w teori dłuższe lub mniej logiczne rozwiązanie problemu nie jest błędem).

@edit. Jeszcze cos tu dałem by było czytelnie (troche zmieniłem UpdateGUI by pobierał var amunicja.(które zostało zmienione na publiczne.)

I zmieniłem by skrypt nie szukał componentu tylko miał odrazu podany.

 

 

using UnityEngine;
using System.Collections;
 
public class AmmoGUI : MonoBehaviour {
// Use this for initialization
void Start () {
 
}
 
// Update is called once per frame
void Update () {
}
 
public Component ammo;
 
public void UpdateGUI(int amunicja) {
ammo.GetComponent<GUIText>().text = "ammo: "+amunicja;
}
}

using UnityEngine;
using System.Collections;
using System.IO;
using UnityEditor;
using System.Diagnostics;
 
 
 
public class Player : MonoBehaviour {
public static int amunicja = 15;
public AudioClip boom;
public AudioClip click;
// Use this for initialization
void Start () {
 
}
 
// Update is called once per frame
void Update () {
GameObject ammoText = GameObject.Find ("ammo");
AmmoGUI gui = ammoText.GetComponent<AmmoGUI>();
gui.UpdateGUI(amunicja);
if(Input.GetMouseButtonDown (0))
{
if(amunicja > 0)
{
this.gameObject.GetComponent<AudioSource>().audio.clip = boom;
this.gameObject.GetComponent<AudioSource>().audio.Play();
amunicja = amunicja + -1;
gui.UpdateGUI(amunicja);
} else if(amunicja <= 0) {
audio.PlayOneShot(click);
amunicja = 0;  // na wszelki wypadek
}
}
 
}
}

mirajane_tag_by_raaims-d4f56kb.png


Komp:


Procesor: i5-4670k , Karta: Asus GTX 780 Ti , Płyta: ASRock H97 Perf. Cooler CPU: Raijintek NEMESIS

Opublikowano

A ja bym to zrobił tak:


 

using UnityEngine;
using System.Collections;
using System.IO;
using UnityEditor;
using System.Diagnostics;

public class Player : MonoBehaviour {
	public int amunicja;
	public AudioClip boom;
	public AudioClip click;
	// Use this for initialization
	void Start () {
		amunicja = 15;
	}
	
	// Update is called once per frame
	void Update () {
		if(Input.GetMouseButtonDown (0))
		{
			if(amunicja > 0)
			{
				this.gameObject.GetComponent<AudioSource>().audio.clip = boom;
				this.gameObject.GetComponent<AudioSource>().audio.Play();
				amunicja--;
			} else {
				audio.PlayOneShot(click);
			}
		}
	}
}

 



 

using UnityEngine;
using System.Collections;

public class AmmoGUI : MonoBehaviour {
	public GameObject Player;
	
	void Update () {
		gameObject.GetComponent<GUIText> ().text = "ammo: " + Player.GetComponent<Player> ().amunicja;
	}
}

 



Co zrobiłem?
-Zmienną z amunicją zmieniłem na publiczną i na Int, bo raczej nikt nie zamierzał korzystać z liczb zmiennoprzecinkowych oraz jej inicjacje przeniosłem do metody/funkcji (?) "Start", bo do tego chyba ona służy.
-Błędem w skrypcie był zły warunek sprawdzający liczbę amunicji.
-W skrypcie "AmmoGUI" zrobiłem zmienną publiczną GameObject do której przypisałem obiekt Playera i w funkcji Update automatycznie pobiera i odświeża liczbę amunicji.
-Nie wiem czy to coś zmienia, ale zawsze lepiej mi się czytało "amunicja--" zamiast "amunicja = amunicja = amunicja -1"
 

Opublikowano

Na chwilę obecną mamy rozwiązany problem z typem zmiennej amunicja i mamy "ludzką" dekrememtację.

Pierwsza podpowiedź: za dużo rzeczy, których się nie używa.

Opublikowano

Z tą podpowiedzią chciałbym się poprawić ;)

 

using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {
	public int amunicja;
	public AudioClip boom;
	public AudioClip click;
	// Use this for initialization
	void Start () {
		amunicja = 15;
	}
	
	// Update is called once per frame
	void Update () {
		if(Input.GetMouseButtonDown (0))
		{
			if(amunicja > 0)
			{
				audio.PlayOneShot(boom);
				amunicja--;
			} else {
				audio.PlayOneShot(click);
			}
		}
	}
}

 

 

 

 

using UnityEngine;
using System.Collections;

public class AmmoGUI : MonoBehaviour {
	public GameObject Player;
	
	void Update () {
		gameObject.GetComponent<GUIText> ().text = "ammo: " + Player.GetComponent<Player> ().amunicja;
	}
}

 



Poprawiłem co nieco w Player.cs, a dokładniej zmiana wywoływania Audio, oraz usunięcie niepotrzebnych usingów.

Opublikowano

@RJ45 Jesteś już blisko ideału :D Właściwie to została jedna rzecz do ulepszenia w Player.cs, AmmoGUI trochę pogorszyłeś :P 

 

Druga podpowiedź: Nie tylko w kodzie.

Opublikowano

Jutro wrzucę pełną odpowiedź. W tej rundzie najlepiej poradził sobie @RJ45 , a @Smaczek za chęci dostaje nagrodę pocieszenia ;)

Opublikowano

Rozwiązanie pierwszej zagadki:

1. Za dużo niepotrzebnych bibliotek.

2. Zły typ zmiennej amunicja.

3. Za dużo GetComponent i GameObject.Find.

4. Źle skonstruowany warunek, który sprawdza amunicję.

5. Rigidbody na GUIText.

6. Jeden skrypt za dużo.

7. Taki sobie sposób odtwarzania dźwięku strzału.

8. Player.cs raczej ciężko będzie bezproblemowo rozwijać.

 

Teraz trochę więcej detali:

 

 

using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {
	private int amunicja = 15;
	public GUIText ammo;	
	public AudioClip boom;
	public AudioClip click;

	// Use this for initialization
	void Start () {
		UpdateAmmo();
	}
	
	// Update is called once per frame
	void Update () {
		if(Input.GetMouseButtonDown (0))
		{
			Fire();
		}
	}

	void Fire()
	{
		if(amunicja > 0)
		{
			audio.PlayOneShot(boom);
			amunicja--;
			UpdateAmmo();
		} else {
			audio.PlayOneShot(click);
		}
	}

	void UpdateAmmo()
	{
		ammo.text = "ammo: "+amunicja;
	}
} 

 

 

 

Jeżeli mamy możliwość to ograniczamy liczbę Monobehaviourów do minimum. Skrypt Ammo jest zupełnie zbędny, ponieważ robi tylko jedną rzecz i na dodatek powiązaną z innym skryptem. Jeżeli jeden skrypt możesz zastąpić metodą w innym skrypcie, który w jakiś sposób łączy się z tym co masz zrobić, to zastąp :)

Żeby to zrobić, użyłem zmiennej publicznej GUIText i w te miejsce w inspektorze dodałem obiekt GUIText. Następnie stworzyłem metodę UpdateAmmo(), która zaktualizuje wyświetlany tekst. Wywołuję ją po strzale i dekrementacji. W przyszłości można tą metodę wywołać po przeładowaniu broni. Odpadł tym samym problem z GameObject.Find i GetComponent.

Jeżeli na jakimś obiekcie jest skrypt, to bez sensu jest w nim korzystanie z GetComponent aby dobrać się do komponentów na tym obiekcie. Wystarczy this.gameObject.audio... (w większości przypadków). A tak było w pierwszej wersji, gdzie podmieniałem ciągle Audio.Clip na ten sam dźwięk. Dodatkowo jak już podmieniłem i strzelało się dalej to dźwięk był przerwany i odtworzony jeszcze raz.

W takim przypadku wygodniej jest zastosować audio.PlayOneShot(AudioClip).

Dlaczego dodałem metodę Fire()? Żeby można było strzelać również z innych miejsc w kodzie. Dodatkowo im mniej obliczeń/warunków w Update() tym lepiej.

Najgorszą rzeczą były jednak GameObject.Find i GetComponent w Update(). Wyobraź sobie, że z każdą wyświetloną klatką szukasz obiektu na scenie z dokładnie taką nazwą jaka jest podana w Stringu, dodatkowo bierzesz od tego obiektu jakieś komponenty. Nie ważne czy potrzebujesz ich czy nie. Po prostu, z każdą klatką robisz bezsensowną robotę.

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...