Jump to content
Unity Insider Forum

#DEV-Log: Einblick in Dev-Life


John

Recommended Posts

Hallo Leute, 

heute hatte ich ein bisschen rumgespielt mit dem Mecanim-System. Ich hatte es zwar schon damals benutz, aber heute hatte ich wieder angefangen, wissen aufgefrischt und mit mehr Features gearbeitet, um so das Mecanim mehr kennen zu lernen. 

 

Ziel war eine Third-Person Control zu erstellen. Hier ist das Resultat :

 

Feedback ist Willkommen :D Mfg.

-John

Link zu diesem Kommentar
Auf anderen Seiten teilen

Schwer zu sagen. Farbe und Texturen sind ok! Ob aber der Shader mit Umrandung gut oder nötig ist, kann ich nicht beurteilen.
Ich persönlich würde die Umrandung nicht nutzen. Bzw. nur dann wenn es dazu dient, eine ausgewählte Figur kenntlich zu machen.
Natürlich hebt das insgesamt die Figur etwas hervor und gibt ihr einen gewissen Comic-look. Das kann somit auch ein Stilmittel sein.

Tja, schwer zu sagen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Jep, den gleichen Gedankengange habe ich auch Verfolgt und habe letzt endlich mich für die Umrandung entschieden als "Popup" der später klar auf den Bildschirm erkennbar ist. Das sich jeweils die Gegener vom Rest, also sprich den Environment, abheben.

Ich glaub vll. ist es nicht schlecht nen Art Prototype Level aufzubauen wo man den Unterschied bzw. der Effect dort ein bißchen mehr sichbar ist und man es anhand diesem besser abwägen kann.

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hio,

zurzeit bin ich an der UI am Planen und rumschieben damit sie am besten passt, hier ist ein Entwurf den ich aktuell gar nicht mal so schlecht finde :D

NiFEtXSb.jpg

 

Zu Erklärung:

Ich dachte mir das ganze so das es jeweils Traps gibt die man sich am anfang der runden zusammen stellen kann mit verschieden Effects und Fähigkeiten. Dan gibt es noch die Spells das sind Zauber die man jeweils mit seinen "Mana" (mir ist noch keine bessere bezeichnung eingefallen :D ) einsetzten kann zum Beispiel seine Trap über kurze Zeit verstärken oder gar irgendwelche Flächen-Damage skills die auf eine Reihe allen Gegnern schaden zusetzt. 

Die Traps kosten Gold-Punkte und die Spells-Skills jeweils "Mana"-Punkte.

 

Mfg.

-John

 

PS: *Hust* *Premium-Points haha 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hio,

zurzeit erstelle ich eine Generische Menu-Lösung wo ich einfach Menü-Elemente wiederverwenden kann ohne großen Aufwand. Ebenso habe ich ein bißchen mit der UI rumgespielt und jetzt endlich mal die neue UI besser verstanden :P

Hier ist ein kleiner Ausschnitt aus dem Main-Menu:

GKwcX7xV.png 

 

Mfg.

-John

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hello,

ich wollte meine neue Entscheidung was den UI-Workflow angeht in Unity zeigen. Führer habe ich immer Elemente in Black-/White angefertigt und die dann anschließend in Unity geladen und mit dem Color Parameter eingefärbt. Wenn man ein speziellen Comic-Look haben wollte habe ich in Photoshop immer noch ein Eben Modifierer drüber gelegt der das ganze Violett einfärbt. Nun habe ich mich dafür entschieden doch für jede Farbe einzeln eine Graphik anzufertigen, da Unity nur die Farbe drüberlegt und man dadurch eine Mono-Look bekommt. Mit Hilfe von der Strategie das man jeweils immer Grafiken importiert mit verschieden Farben z.b. im Bild unten zu sehen Blau hat man die Möglichkeit andere Farben noch rein zu mixen sodass es ein besonderer Look bekommt und nicht eine Einheitsfarbe.

mKn40SG4.png

 

Mfg.

-John

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 2 weeks later...

Heyo,

in der letzten Zeit bin ich ein Stück weit vorangekommen. Eine kleine Zusammenfassung:

Art:

Ich hatte bereits letzten anfangen das Main-Menu zu design. Hier ist der Zwischenstand der sich aus mehreren Versionen ergeben hat.

WKFztPXq.jpg

Main Battle-Menu:

  • Game-Session kann man hier starten
  • Seine Quests kann man hier jeweils aufrufen
  • Schatztruhen die man aus Game-Session bekommt kann man hier öffnen und den Process verfolgen
  • Ebenfalls kann man hier die Daily-Pirate Chest öffnen
  • Man hat unterandern Obenhalb des Screens seine Resource in einem überblick (Left: Exp/Level, Middle: Gold, Right: Beads)
  • Unterhalb des Screens hat man eine Navigations-bar mit der man in andere Kategorien wechseln kann wie z.B. Shop, Deck

Programming:

Ich arbeite zurzeit an einer Grundbasic von Core-System die als fundamental für das Front- und Backend dient. 

Cache-Package

Das Cache-Package collected jeweils bestimmte Typen und du kannst dir jeweils egal wo du sie grade brauchst holen und damit arbeiten.

Ein Beispiel wäre man möchte alle Units in einem Cache speichern dazu legt man wie folgt eine neue Klasse erbt jeweils von der abstract-base-class Cache<T> und gibt jeweils einen Typen an dem man in diesem Cache speichern möchte. Das könnten GameObjects, Scriptable-Objects, Scripts, ints... egal wovon du grade eine Collection benötigst. Dan kann man den jeweiligen Cache im CacheContainer hinterlegen und später sich wieder holen oder den jeweiligen gewünschten cache removen.

//... Custome Class that extends form abstract Cach<T> Class
public class UnitCache : Cache<UnitComponent>
{
  //... you custome filter methode
}

//... Also, you have a Cache Container that store all Cache so you can easily inject this class over Dependency Injection and you have access to all Caches or inject your specific Cache
//... Add
  _cacheContainer.Add<UnitCache, UnitComponent>(_unitCache);
//... Get
  UnitCache unitCache = _cacheContainer.Get<UnitCache, UnitComponent>();
//... Remove
  _cacheContainer.Remove<UnitCache, UnitComponent>(_unitCache);
//...
  


  

 

Game-Architecture:

Ich habe schon bereits ein paar Projekte davor mir eine gut Scalable Feature Archtiecture überlegt die man für Spiele einsetzten kann. Die ebenfalls die Dependency zu Unity auf das geringste minimiert. 

xf5TrY4j.png

  • Model

Das Model ist ein Ort zum Speichern von Daten (nur speichern / keine Modifizierung oder Konvertierung) Was du setzt ist was du bekommst! Wen sich was ändert das Benachrichtig.

  • View / Display: 

View-Display ist nur für die Grafische Darstellung auf dem Screen oder Output vom Spieler z.B. Audio (Keine Modifizierungen oder Input Lister)

  • View / Input: 

View Input ist hört auf den Input vom User und Push anschließend direkt das Event. (Keine Modifizierungen oder graphische Darstellung)

  • Command:

Command reagiert auf events von der View oder von einem Model Change und führt jeweils danach die Services aus (Keine Modifizierungen, Services-Logic oder Änderungen auf das Model)

  • Service:

Ein Service führt jeweils eine bestimmte Modifizierungen auf Models durch. Es kann auf Model zugreifen und diese jeweils verändern. (Falls man Größere Prozesse hat kann man die ruhig in kleiner services unterteilen)

Signal-Package

Das Signal Package ist ein Event-System. Man kann sich jeweils auf bestimmte Ereignisse Subscriben oder unsubscriben. Man kann jeweils Signale auch mit Guards versehen, dass heißt fals dieses Signal published wird der jeweilige Guard vorher ausgeführt und falls er fehl schlägt wird das Signal jeweils nicht gefeuert und die subscribe bekommen jeweils nichts mit.

//...
public class PlayerLevelUpSignal : Signal<int>
{
}
//..
  
//... SignalConfig.cs
	  _playerLevelUpSignal.Add(_resourceBarVfxHandler.LevelUp)
  						  .Add(_postProcessVfxHandler.LevelUp);
//...
//...PlayerResourceHandler.cs
  private void AddExp(int amount)
  {
  	_expAmount += amount;
  	if(IsPlayerLevelUp())
  	{
  		_playerLevelUpSignal.Signal(_playerLvl)
  	}
  }
//...
//...ResourceBarVfxHandler.cs
	public void LevelUp(int level)
  	{
  		//play LevelUp-Vfx
  	}
//...

ASP.Net Backend

Ich habe mich dazu entschieden das Backend jeweils auf ASP.Net Core aufzubauen. Ich hatte bereits die ersten kleinen Tests damit gemacht und bin positiv davon überrascht. Ebenfalls finde ich den Fakt sehr gut das ich meine Front- und Backend jeweils in C# schreiben kann was mir die Arbeit erleichtert und ich manche Prozesse nicht neue schreiben muss in einer anderen Sprache, sondern das bereits vorhanden wiederverwenden kann.

ToDo Current Task:

Die Registrierung von einem User und Login mit einer Public/Private-Key-Verschlüsselung.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Heyo, 

ich hatte heute eine coole Sache gelernt was Game-Design/UX angeht.

"Weniger ist oftmals besser!"

Es kommt schnell vor das man sehr viel in sein Game reinbauen möchte wie z.b. ich mit meinen Traps und Spells. Ich hatte mir gedacht das es echt cool wäre noch gleichzeitig zu den Fallen Spells zu haben die natürlich eine eigene InGame Ressourcen braucht die sich Aufladet... und schnell kommt man dazu viel mehr logic bzw. Funktionen einzubauen. Um das alles zu kommunizieren und dem Spieler zu verstehen zu geben was etwas ist ist sehr schwer und wirkt schnell negativ auf den User. Der User fühlt sich dabei schnell überfordert, zwar macht es für uns Entwickler alles Sinn da wir es entwickeln und uns öfters damit beschäftigen, aber für außenstehende person ist das genau das Gegeteil.

Aus diesen Grund habe ich mein Game-Design nochmal überdacht und angepasst.

m860zzsl.jpg

Die Spells wurden komplett rausgenommen und die Resourcen die man collecten muss auch.

Der Spieler geniert die Coins (unterhalb die blaue bar) über Zeit mit der er dann die traps (von seinem Deck) setzten kann die sich in seinen Slots befinden.

Oberhalb sieht der Player jeweils wann die nächste Wave kommt und bei welcher er aktuell ist (zurzeit mit mockup hüten gekennzeichnet "rechts")

Auf der linken Seite sieht er jeweils sein Leben (zurzeit mockups heart graphics) falls ein Gegner es durch schafft zieht es im ein Leben ab.

In der Version ist das UI auch nicht mehr so noise und gut lesbar auf dem ersten Blick. Oftmals ist weniger mehr! ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Heyo :)

am Wochenende bin ich auf eine spannende Architecture gestoßen, die ein Spiel gut Configurable macht. Wo ich mit Hilfe dieses Flow später gut neuen Content hinzustöpseln kann oder Änderungen ohne Probleme vornehmen kann.

Der Ansatz für ein solches System liegt im "ScriptableObject". Man mag es gar nicht auf den ersten Blick glauben, aber dieses kleine Schmuckstück erleichtert dir in vielen Hinsichten das Dev.-Leben und auch das abändern von Value geht super schnell von der Hand.

Doch wie sieht das ganze aus?

HCrj0Upj.png

Auf den ersten Blick mag diese Grafik unverständlich sein bzw. man kann sich schwer was darunter Vorstellen deshalb gehen wir kurz durch jedes einzelne Element durch und klären deren Funktion und anschließend wen wir wieder zurück zu dieser Grafik springen wird sie einem hoffentlich besser schlüssig.

Fangen wir mit einer Generellen Frage an: Was sind Models und Components

Models

Sind reine Daten-holder sie halten in unserem Beispiel eine Card die von uns Definiert wird:

CardModel:

    - Type					<- Eine definition welche Type es ist (Block/Trigger)
	- Cost 					<- Die kosten um diese Card zu erzeugen... 
	- BattleObjectStates	<- Wichtige Informationen über das Object (Health/Damage)
	- DisplayContent		<- Ein Bundle an Display Information (Rendermesh/Name)
	- Rarity				<- Ebenfalls eine defintion welche Rarity diese Card hat (Common, Rare, Epic, Legendary)
	- Ability				<- Eine Ability die wir jeweils der Karte geben können (z.B. Verlangsamt Units um 15%)
	- ObjectBehaviours		<- Hier können wir jeweils defenieren was die Card alles kann (Shooten, Movement...)

Components

Sind jeweils Elemente die für uns Information halten oder auch Behaviour. Was genau bedeutet das? Greifen wir wieder das Card Beispiel auf wir besitzen im CardModel eine Field das nennt sich ObjectBehaviours. Dieses Field in eine Collection von Behaviours die wir der Card hinzufügen können.
 

Ein ObjectBehaviour ist eine Component wo wir definieren können wie sich jeweils diese Card verhält. Wen diese Karte ein bestimmtes Behaviour haben sollte erstellen wir dieses Behaviour unabhängig von dieser Card damit wir ggf. dieses Behaviour wo anderes wiederverwenden können. Im Grund das gleiche Component Prinzip von Unity, nur ein wenig spezifizierter.

Ein Beispiel wäre dafür ein Shoot-Behaviour das in einem Regelmäßigen Intervall ein Schuss in eine Richtung abgibt.

//...
public class ObjectBehaviour : ScriptableObject, IObjectBehaviour
{
  public virtual void Execute()
  {
    //...
  }
}
//...

//...
public class ShootDirectionComponent : ObjectBehaviour
{
	IFloatComponent Time { get { return _time; } }
	VectorDirection Direction { get { return _direction; } }

	[SerializeField]
	FloatComponent _time;
	[SerializeField]
	VectorDirection _direction;
    
  	public override void Execute()
  	{
      base.Invoke(); //... Here we invoke the default Behaviour that for example track actions or log something
      //... execute ShootDirection Behaviour
    }
//...

Die Idee ist dabei diese Shoot-Behaviour (ObjectBehviour) später auch einer Unit zu verweisen ohne direkt für die Unit nochmal das Ganze zu schreiben.

Die Frage ist inwiefern dieses Konstrukt einem Hilft in Verbindung mit ScriptableObject sein Game gut Configurable zu machen. Die Lösung sitzt direkt in dem ScriptableObject-Prinzip mit diesem ich in der Lage bin mir jeweils verschiedene Variationen anzulegen und diese jeweils weiter zu verwenden.

Let's jump in Code:

Wir haben jeweils hier das ICardModel-Interface dieses wir an die Außenwelt geben womit andere Klassen damit arbeiten können.

namespace Pwhh.Game.Model
{
	public interface ICardModel : IModel
	{
		IConstantIntComponent Cost { get; }
		//...
	}
}

Hier haben wir jeweils die Base Implementation wir extends jeweils vom ScriptableObject und von dem ICardModel.

Wichtig: Da Unity nicht mit Interface-Typen (Getter und Setter) im Inspector umgehen kann benutzen wir jeweils hier einen Trick. Wir nutzen die Base Implementation von unserem gewünschten Objekt und setzen dieses jeweils auf private damit wir keinen Zugriff von außen drauf haben und weisen das jeweils dem Getter von dem Interface zu. Zu guter Letzt setzten wir über das private Field das [SerializeField]-Attribute das uns erlaubt im Editor diese Value zu verändern.

namespace Pwhh.Game.Model
{
	[CreateAssetMenu(menuName = "Models/Player/Card", fileName = "Card")]
	public class CardModel : ScriptableObject, ICardModel
	{
		public IConstantIntComponent Cost { get { return _cost; } }

		[SerializeField]
		private ConstantIntComponent _cost;
	}
}

Hier sehen wir noch ein Use-Case wo wir jeweils das ICardModel verwenden. Das gute ist das wir nur mit dem jeweiligen Interface arbeiten können ohne eine direkte Verbindung zum Objekt. So ist es im Grunde egal welche Version wir verwenden es bleibt immer gleich, aufgrund des interfaces.

namespace Assets.Source.Serivces.CardLoader
{
	public class CardLoader : IService
	{
		public void Load(ICardModel[] cards)
		{
			SetupUICard(cards);
			//...
		}
     //...

( Unity Training | Unity Docu )

Advantages Technics

Da ScriptableObjects im Inspector angezeigt werden und wir mit dem SerializeField einfach im Editor values abändern oder hinzufügen können ist das schon mal ein großer Vorteil. Um diesen Vorteil noch zu vergrößern und die Benutzbarkeit des System so einfach wie möglich zu gestalten kann man auf [CustomeEditor(typeof(type)] zurückgreifen.

Wie sieht das ganze aus?

Dazu möchte ich gerne ein Situation aufgreifen womit ich am Wochenende konfrontiert wurde.

Ich hatte jeweils anhand dieses design-flow den wir oberhalb besprochen haben mein GameSession aufgebaut. Diese beinhaltet alle relevanten Daten die wichtig sind für meine Levels. Das bedeutet wen ich ein neues Level hinzufügen möchte erstelle ich ein GameSession Object (ScriptableObject) und konfiguriere jeweils meine Level. Für uns ist jetzt speziell der Wave Aspekt interessant anzuschauen.

Hier ist ein Überblick über den Aufbaue meines GameSession Objektes:

J2T0iG26.png

Zu Erklärung was Wave sind:

Ein Level besteht aus eine Anzahl aus Unit Wave die kommen und du musst jeweils diese Waves bekämpfen. Eine Wave hat jeweils eine bestimmte Zeit und jeweils Angaben zu welcher Zeit welche Units  in dieser Wave spawnen.

IWaveModel
	- Time					<- Ist jeweils dauerer diese Wave bis die nächste Wave kommt
	- UnitSpawnComponent	<- Beinhaltet welche Unit und zu welcher Zeit diese gespawnt wird

So jetzt stellt sich nur folgende Frage wen ich jeweils in meiner Liste mehrere Wave Objecte reingezogen habe habe ich leider kein Überblick darüber wie lang die ganze GameSession dauert. Hier kommt unser CustomeEditor zum Einsatz mit dem ich jeweils die ganze Liste durchgehen kann und mir die GameSession Zeit zusammenrechnen kann.

[CustomEditor(typeof(GameSessionModel))]
public class GameSessionModelEditor : Editor
{
	private int _totalGameSessionTime;

	private void OnEnable()
	{
		_totalGameSessionTime = GetTotalWaveTime();
	}

	public override void OnInspectorGUI()
	{
		base.OnInspectorGUI();
		EditorGUILayout.LabelField("Total Game-Wave Time:" + _totalGameSessionTime);
	}
    //...

( Unity Training | Unity Docu )

Mit dieser Hilfe kann mit sich ein sehr gutes Inspector-UI-System zusammenbasteln das einen schnell Information darüber gibt was alles abgeht ohne sich durch die ganzen ScriptableObjects zu clicken und sich diese heraus zu suchen. Ebenfalls ein Überlegung für später ist ggf. sich die Units per Icon in der GameSession anzeigen zu lassen um ein schnellen Überblick zu bekommen welche Units in dieser Session verwendet werden.

:rolleyes:

Ich hoffe ihr habt ein Einblick bekommen in den Flow mit ScriptableObject und vll. für euch ein Use-Case entdeckt. :)

Mfg.

-John

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Heyo :) ,

ich brauche euer Feedback zu meiner Game-Idee von Pirate with Huge Hats.

Gerne: Tower Defense

Du als Spieler musst deinen Rum gegen bösartige Piraten verteidigen. Die Piraten kommen jeweils auf 5 Lines in Wellen um dein Rum zu stehlen. Du als Spieler hast die Möglichkeit sie mit deinen Fallen daran zu hindern bevor Sie zu deinen Rum-Vorrat kommen. Falls es jedoch ein Pirate schafft zu deinen Rum-Vorrat vorzukommen trägt er jeweils diese Rum-fass zurück zu seiner Base falls er auf dem Weg zurück sterben sollte lässt er das Rum-fass an der Stelle fallen wo er gestorben ist und so besteht aber noch die Gefahr das andere Piraten das Rum-fass von dem Ort aufheben und zurück tragen. Falls ein Rum-fass die Grenze Überschreitet ist das Spiel vorbei und du hast verloren, aber wen du alle Wave durchhaltest ohne das ein Rum-fass gestohlen wird hast du gewonnen.

XEqTfDfQ.jpg

Würde mich über Feedback/Bedenken oder Anregungen sehr freuen

Mfg.

-John

Link zu diesem Kommentar
Auf anderen Seiten teilen

Cr5zScKi.png
 
Graphic-Weekend
 
  • Environment-White-Blocking
Ich hatte am Wochenende eine Idee jeweils für ein Level gehabt ein Beach/Steg
X9viFcMy.png
(White-Blocking)
 
aPznVD4i.gif
 
(White-Blocking integriert in die Scene um die Max-Borders zu überprüfen, sprich wen man ein Größeren Screen hat sieht man nur mehr vom Level)
 
  • Unit Captain Pirate Update

Ich hatte angefangen jeweils zu überlegen ob ich bei jeder Unit Augen hinzufüge und mehr Detail rein packe soll. Hier ist ein zwischen Ergebnis

id7Spa4V.png

(Augen, Arme, Augenbrauen hinzugefügt)

 

  • Trap Prototypen

Ebenfalls hatte ich begonnen die ersten Prototypen für Traps zu designen und zu blocken die man als Player jeweils auf seine Felder setzten kann.

gSa1dYWZ.png

 

Summary:

Dieses Wochenende hab ich mehr Graphic's gemacht. Aber habe auch eine sehr interessante Möglichkeit gefunden sein Game sehr Pluggable zu machen, sodass man sein Spiel mit jeweiligen Features zusammen stöpselt kann. Dazu nächste Woche mehr :)

Mfg.

-John

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Lädt...
×
×
  • Neu erstellen...