Jump to content
Unity Insider Forum

SimpleMove will nicht Simple sein


oci300

Recommended Posts

Hallo miteinander !

 

Bestimmt ist mein Problem ganz einfach, aber da ich mit der Sprache noch nicht so vertraut bin, weiß ich leider nicht, ob der Code korrekt ist.

 

Da ich Videos nicht so mag, habe ich mir zu Unity und C# ein Buch besorgt und arbeite das gerade ab. Ich hänge jetzt an einer Stelle:

 

Mein Player soll sich mit WASD bewegen, soweit, so typisch.

 

Dafür wurde mir folgender Code vorgegeben

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour {

public float moveSpeed = 5.0F;
public float rotationSpeed = 300.0F;

[HideInInspector]
public bool gameEnded = false;

private Vector3 moveDirection = Vector3.zero;
private CharacterController controller;
private PlayerHealth playerHealth;
private Quaternion destRotation;


void Start() {
 playerHealth = GetComponent<PlayerHealth>();
 controller = GetComponent<CharacterController>();
 destRotation = transform.rotation;
}
void Update() {
 if(playerHealth.health > 0 && !gameEnded)
 {
  moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
  moveDirection = transform.TransformDirection(moveDirection);
  moveDirection = moveDirection * moveSpeed;
  controller.SimpleMove(moveDirection);

  if(Input.GetButtonDown("Left"))
destRotation.eulerAngles = destRotation.eulerAngles - new Vector3(0,90,0);
  if(Input.GetButtonDown("Right"))
destRotation.eulerAngles = destRotation.eulerAngles + new Vector3(0,90,0);

  float step = rotationSpeed * Time.deltaTime;

  transform.rotation = Quaternion.RotateTowards(transform.rotation, destRotation, step);
 }
 else
 {
  controller.SimpleMove(Vector3.zero);
 }
}
}

 

Das drehen funktioniert auch(Mit den Tasten Q und E...Also hat nix mit dem Laufen an sich zu tun), nur leider das laufen nicht.

Ich hab dann fix gegooglet, mir anderen Code rausgesucht und siehe da, es funktioniert.

 

Dann hab ich mich natürlich auf die Suche nach dem Fehler in meinem Code gemacht, hab dann den Internetcode entsprechend meiner Variablen und allem angepasst: Spieler läuft immer noch. Super. Daran liegt es also nicht. An den Project Settings liegt es also auch nicht. An den Variablen auch nicht. An der IF-Abfrage auch nicht, die hab ich mit dem anderen Code auch gestetet = läuft (Im wahrsten Sinne des Wortes ^^ )

Da blieben dann nur noch folgende Zeilen als Übeltäter:

moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
  moveDirection = transform.TransformDirection(moveDirection);
  moveDirection = moveDirection * moveSpeed;
  controller.SimpleMove(moveDirection);

 

Wenn ich es so schreibe:

public float speed = 3.0F;
public float rotateSpeed = 3.0F;

void Update() {

	CharacterController controller = GetComponent<CharacterController>();

	transform.Rotate(0, Input.GetAxis("Horizontal") * rotateSpeed, 0);

	Vector3 forward = transform.TransformDirection(Vector3.forward);

	float curSpeed = speed * Input.GetAxis("Vertical");

	controller.SimpleMove(forward * curSpeed);
}

 

funktioniert es.

Und hier gerate ich ins stocken. Ist "mein" Code einfach schlichtweg falsch? Ich könnte natürlich die funktionierenden Varianten machen, aber wozu hat man ein Buch, wenn man es nicht erstmal befolgt bis zum Ziel bevor man selber Hand anlegt? ^^

 

Ich hoffe, ich hab es nicht zu unverständlich dargelegt und ihr könnt mir helfen.

 

Liebe Grüße,

 

Oci !

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ok, vielleicht doch etwas unübersichtlich.

Zusammengefasst, ist hier ein Fehler drin?

moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
  moveDirection = transform.TransformDirection(moveDirection);
  moveDirection = moveDirection * moveSpeed;
  controller.SimpleMove(moveDirection);

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi.

Ich habe mal deinen Code rausgenommen, da man den Fehler einfacher sieht.

 

void Update() {
// Wenn der Player Health größer 0 ist und gameEnded false ist.
 if(playerHealth.health > 0 && !gameEnded)
 {
// Hier fragst Du den Input ab und überschreibst die Vectoren
 }
 else
 {
  // Hier bewegst Du die Figur
 }
}

 

"Controller.SimpleMove(moveDirection);" muss mit in die If-Anweisung.

 

Also:

 

void Update() {
 if(playerHealth.health > 0 && !gameEnded)
 {
  moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
  moveDirection = transform.TransformDirection(moveDirection);
  moveDirection = moveDirection * moveSpeed;
  controller.SimpleMove(moveDirection);
  if(Input.GetButtonDown("Left"))
	destRotation.eulerAngles = destRotation.eulerAngles - new Vector3(0,90,0);
  if(Input.GetButtonDown("Right"))
	destRotation.eulerAngles = destRotation.eulerAngles + new Vector3(0,90,0);
  float step = rotationSpeed * Time.deltaTime;
  transform.rotation = Quaternion.RotateTowards(transform.rotation, destRotation, step);
  controller.SimpleMove(Vector3.zero);
 }
 else
 {
// Hier wird Code abgearbeitet, wenn Player Health kleiner 0 ist und gameEnded true ist.
 }
}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hey, danke für die Antwort. Leider bewegt er sich immer noch nicht, wenn ich die Zeile nach oben packe.

 

Bedeutet (Vector3.zero) nicht, dass er sich dann nicht mehr bewegen kann?

In else wird ja das abgespielt, wenn er "tot" ist, meines Wissens nach ^^

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi.

Der Vector3 moveDirection wird ja in der Update wieder mit einem neuen Vector3 überschrieben. Das passt schon so.

 

Welchen Wert hat denn Player.Health und gameEnded?

  • Der Code wird nur ausgeführt, wenn Player.Health größer als 0 ist, also mindestens 0.1, falls Player.Health ein "float" ist oder
  • mindestens einen Wert von 1 hat, wenn er ein "integer" ist und
  • gameEnded true ist.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hey !

 

PlayerHealth ist 200 und gameEnded is false. Muss auch false sein wegen "!gameEnded". Also die Abfrage passt, er kann sich ja auch drehen mit

if(Input.GetButtonDown("Left"))
			destRotation.eulerAngles = destRotation.eulerAngles - new Vector3(0,90,0);
  if(Input.GetButtonDown("Right"))
			destRotation.eulerAngles = destRotation.eulerAngles + new Vector3(0,90,0);
  float step = rotationSpeed * Time.deltaTime;
  transform.rotation = Quaternion.RotateTowards(transform.rotation, destRotation, step);

 

Das ist ja auch in der Abfrage. Hatte auch den anderen "Laufcode" aus dem Internet in die selbe IFabfrage gepackt, da lief er auch. Also daran liegt es nicht.

 

//Edit: Hab grade das Ausrufezeichen von gameEnded weggemacht, dann dreht er sich auch nicht mehr. Also das passt so ^^

 

Wie gesagt, hab alles getestet, nur die paar Zeilen

moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
  moveDirection = transform.TransformDirection(moveDirection);
  moveDirection = moveDirection * moveSpeed;
  controller.SimpleMove(moveDirection);

 

tuns einfach nicht ^^ Ist der Code denn an sich korrekt? Das wäre meine einzige Vermutung noch, dass der einfach Murks ist ^^

 

 

Edit2: So, ich bin endgültig verwirrt... Wenn ich gameEnded auf true setze, kann er zwar immer noch nicht laufen, aber er kann sich immer noch drehen. Wenn ich das Ausrufezeichen vor gameEnded in der IF-Abfrage wegmache, dreht er sich nicht mehr, egal ob false oder true.... Kann mir das jemand erklären? Vielleicht trägt es ja irgendwie zur Lauflösung bei...Im ersten Post seht ihr ja den gesamten Code...

Link zu diesem Kommentar
Auf anderen Seiten teilen

Erstmal muss ich Benny widersprechen, denn controller.SimpleMove() ist in der ersten If Abfrage drin. Also eigentlich sollte der Bewegungswert übergeben werden.

 

Jetzt zu den Zeilen, die nicht gehen, aber meiner Meinung nach gehen müssten (hab es aber jetzt nicht getestet).

Zuerst erzeugst du ja einen neuen Vector3 mit den beiden Inputs. Wenn du jetzt z.B. nach links und auch nach oben drücken würdest, müsste im Vector3 jetzt (-1,0,1) drin stehen. Das kannst du ja mal mit ner Printausgabe in der Console überprüfen.

Danach wandelst du den lokalen Wert in einen Welt-Wert um. Sollte der Player also nicht in Welt Z Richtung gucken sondern in Richtung Welt X so sollte jetzt der Vector3 so verändert sein, dass die Direction zur Welt passt.

Das kannst du auch mal in der Console ausgeben lassen.

Ja und dann multiplizierst du das Ergebnis mit deinem MoveSpeed. Aus den -1,0,1 wird dann -5,0,5 wenn der Speed immernoch die 5 hat, die du in der public Var als Grundwert hatte.

Auch das einfach mal überprüfen.

Ja und dann übergibst du den neuen Vector3 Wert an deinen Controller.

Da muss also etwas ankommen, wenn du nicht z.B. mit 0 als Speed multiplizierst.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Guten Morgen.

 

Hast du auch eine Lösung zu meinem Edit2 ? Das verwirrt mich etwas stark :blink::D

 

Also: Es tut sich was. Wenn ich nach

vorne drücke 0.0,0.0,1.0

nach hinten 0.0,0.0,-1.0

nach links -1.0,0.0,0.0

nach rechts 1.0,0.0,0.0

 

bzw wenn ich den moveSpeed mit einbeziehe 5 statt 1.

 

Das bedeutet, die Tastenanschläge werden registriert.

 

Also liegt es vllt an meinem Player, dass er durch irgendwas "festgehalten" wird, stimmts?

 

--Aber warum bewegt er sich dann, wenn ich anderen Code verwende?--

 

Edit: Er bewegt sich jetzt auch nicht mehr mit dem anderen Code. Er dreht sich, aber er geht nicht vor und zurück...Gestern tat er das noch. Ich glaub, ich mach ein Moorhuhn...Da reicht mir das drehen :lol:

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich hatte den Code gestern vor'm Schlafengehen angeguckt und konnte auch kein Problem feststellen.

Die if-Abfrage scheint okay zu sein (man dreht sich ja) und der Move-Code selbst sieht auch gut aus.

Dein gekürzter Code entspricht sogar vom Aufbau her dem aus der Scripting Reference.

 

Ich vermute daher auch, dass das Problem von irgendetwas anderem kommt als dem geposteten Code.

Erstelle ein neues GameObject mit nichts weiter als einem CharacterController und diesem Script, und nimm die Referenzen auf andere Scripts raus. Teste damit noch einmal.

 

Und, nur zur Sicherheit, weil du dich selbst als Anfänger bezeichnet hast: Hast du Unitys Konsole nach Fehlermeldungen durchsucht?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Jau, das bewegt sich !

 

Edit: Und ich weiß jetzt auch, woran es liegt.

Gott, mir ist das jetzt peinlich. Das Playerobject war zu tief und hing somit im Boden drin. Hab den jetzt etwas nach oben gezogen....jetzt gehts mit allem drum und dran.... :unsure:

 

Ich danke dir und euch! Manchmal denkt man einfach zu kompliziert...

 

Schönen Sonntag noch und ich hoffe, dass ich bald auch soweit bin, anderen helfen zu können :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Haha, sehr gut!

 

Da das Problem dann ja gelöst ist, kann ich den anderen Kram ansprechen, ohne das es nervt :)

  • Ersetze Start() durch Awake(), denn da gehören Initialisierungen wie GetComponent hin.
  • Ersetze Update() durch FixedUpdate(), sonst wird dein Spiel Framerate-abhängig.

Bei Fragen gerne fragen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wird gemacht.

Immer sofort ansprechen! Lernen nervt nicht =) Dafür bin ich ja hier.

 

Achja, kurze Frage nebenbei. Ist kein richtiger Fehler:

ich hab ne AudioSource in meinem PlayerHealth-Script gemacht

private AudioSource audioSource;

 

die wird dann in die Funktion (Oder Methode heißt das glaub ich in c# oder ?)

public override void Dying()
{
 audioSource.clip = deathClip;
 audioSource.Play();
 UpdateView();
 lifePointController.LifePoints -= 1;
 if (lifePointController.LifePoints > 0)
  Invoke ("Restart", 1);
 else
  messageText.text = "Game Over, Tschüss! Beispieltext";
}

 

gepackt. Die werde ich dann ja später in nem anderen Script aufrufen. Jetzt sagt er mir zur "Field 'PlayerHealth.audioSource' is never assigned to, and will always have its default value null". Das kann ich aber ignorieren oder? Und die Fehlermeldung wird verschwinden, wenn ich Dying() irgendwo verwendet habe, korrekt?

 

Das wärs dann auch erstmal. Danke nochmal :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi.

Gut das es gelöst ist. In seinem ersten Beispiel wird die SimpleMove trotzdem unter else ausgeführt.

Oder funktioniert der Code, bzw läuft deine Figur, wie Du ihn ursprünglich hattest?

 

Hey! Ja, sie läuft wie ursprünglich gedacht. Ich hab ja 2x Simplemove. einmal im IF und einmal im ELSE ^^

 

void Update() {
 if(playerHealth.health > 0 && !gameEnded)
 {
  moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
  moveDirection = transform.TransformDirection(moveDirection);
  moveDirection = moveDirection * moveSpeed;
  controller.SimpleMove(moveDirection);

Link zu diesem Kommentar
Auf anderen Seiten teilen

Immer sofort ansprechen! Lernen nervt nicht =)

Naja, ich finde es nervt schon, solange das Thema noch ein ganz anderes ist :)

 

Deine Warnung besagt jedenfalls, dass audioSource nie einen Wert bekommt. Deine Dying-Methode weist auch keinen zu, von daher hilft die auch nicht; denn gemeint ist nicht der AudioClip, sondern die Referenz auf die Komponente selbst.

Manchmal kommt diese Warnung bei Unity fälschlicherweise, aber ich glaube nicht, dass das hier der Fall ist. Überprüfe daher mal, wo der Wert für audioSource gesetzt wird.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das Script ist auch meinem Player zugeteilt und im Inspector hab ich dann die AudioClips reingepackt.Deshalb ja als public... Meintest du das? ^^

Deine AudioSource-Variable ist aber als private deklariert, und um die geht es in der Warnung auch.

Du solltest vermutlich in Awake ein GetComponent drin haben, dann geht die Warnung weg.

 

Hi. Aus der else kannst Du sie eigentlich raus nehmen, da Du ja nicht mehr laufen willst wenn die Figur tot ist. Okay, außer Du hast was anderes vorgesehen :D .

Du vergisst, das SimpleMove auch Gravitation beinhaltet.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi. Aus der else kannst Du sie eigentlich raus nehmen, da Du ja nicht mehr laufen willst wenn die Figur tot ist. Okay, außer Du hast was anderes vorgesehen :D .

 

Das weiß ich noch nicht, das wird mir das Buch verraten. ^^ Ich bin zwar schon kribbelig, hab viel im Kopf, aber ich möchte das erstmal streng nach Vorlage abschließen und dann erst laienhaft drin rumpfuschen :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Mhh, wird hier

public override void Damaging()
{
 audioSource.clip = hurtClip;
 audioSource.Play();
 UpdateView ();
}

 

nicht audioSource von hurtClip den Inhalt? ^^ Und in hurtClip hab ich ja über den Inspector den Sound reingepackt.

 

Edit: Ok, Start() zu Awake() gemacht und die Fehlermeldung ist weg!

Soll ich also immer Awake() statt Start() machen oder nur wenn ein .GetComponent<> drin vor kommt?

 

Und nochmal Danke :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Edit: Ok, Start() zu Awake() gemacht und die Fehlermeldung ist weg!

Die Fehlermeldung kann dadurch nicht weg gegangen sein - dass du GetComponent in Awake haben willst hat eine semantische Motivation und es anders zu machen erzeugt niemals eine Fehlermeldung.

 

Mhh, wird hier

[...]

nicht audioSource von hurtClip den Inhalt?

Doch. Aber audioSource selbst wird laut Fehlermeldung nicht gesetzt.

Das ist, als ob du eine Musik-CD in dein Autoradio einlegen willst, aber gar keinen CD-Schlitz in deinem Autioradio hast.

Die Musik-CD ist vorhanden, aber der Player halt nicht.

Irgendwo muss halt

audioSource = xy;

stehen, oder du serialisierst das Feld "audioSource".

Das wäre dieses "Ich mache es public und dann kann ich im Editor was reinziehen".

Da dein Feld aber nicht public ist und vermutlich nicht [serlializeField] drüber stehen hat, ist das scheinbar nicht der Fall.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ne, hast Recht. Die Fehlermeldung kam wieder. Vielleicht geht sie ja weg, wenn ich die AudioSource brauche. Bisher hab ich den Teil, wo man Schaden bekommt und der entsprechende Sound abgespielt wird, noch nicht drin.

 

Warten wir am besten erstmal ab, würde ich sagen :)

 

Achja, wenn ich noch Fragen zu diesem Projekt habe,aber halt andere Fehler, soll ich dann einen neuen Thread erstellen oder diesen hier nutzen? Einen neuen, oder? =)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...