Jump to content
Unity Insider Forum

Animation Problem i.V.m. NavMesh und RootMotion


Hellhound

Recommended Posts

Hallo zusammen,

 

ich bin mir nicht sicher, ob der Scripting-Thread der richtige Ort für das Thema ist oder ob es eigentlich eher zu dem Animationsbereich gehört ... In der Hoffnung das es skript baisert lösbar ist, poste ich es einmal hier.

 

Ich schreibe aktuell für mich einen click to move basierten Avatar Controller und nutze den NavMeshAgent für die Steuerung/Wegfindung. Besonderheit hierbei ist, das ich die Rotation des NavMeshAgent deaktiviert habe um eine Punktrotation vor der eigentlichen Bewegung zum Zielpunkt durchzuführen. Ausgeführt wird das ganze in mehreren Schritten mit einer Coroutine für die Bewegung:

  • Zunächst prüfe ob der Zielpunkt in einem größeren Winkel +/- 30 Grad zur Blickrichtung liegt. Ist dies der Fall wird durch eine weitere Coroutine zunächst die Bewegungsausführung unterbrochen, bis die Animation für die Rotation im Animator zu 75% abgeschlossen wurde.
  • Anschließend setze ich am NavMeshAgent die Bewegunsrelevanten Daten
  • Im letzten Schitt führe ich durch eine weitere Coroutine eine Korrektur der Rotation zum Zielpunkt durch, da diese i.d.R. durch das Blending nicht vollständig ist.

Hier einmal der Code für die Bewegungsausrichtung getriggert durch ein separates Click-Skript:

public IEnumerator Move(Vector3 target, float timeToWait){
  this.targetDirection = target - animator.rootPosition;
  this.targetDirection.y = 0f;
  this.targetPosition = target;

  Vector3 rootDirection = this.transform.forward;
  Vector3 axisSign = Vector3.Cross(targetDirection, rootDirection);
  this.signedAngle = Vector3.Angle(rootDirection, targetDirection) * (axisSign.y >= 0 ? -1f : 1f);
  // block until rotation animation is complete
  if (signedAngle > 30f || signedAngle < -30f) {
yield return StartCoroutine(OnCompleteRotationAnimation());
  }
  this.navMesh.destination = target;
  this.navMesh.speed = this.walkSpeed;
		this.navMesh.acceleration = this.walkAcceleration;

  this.forward = 0.5f;
  this.signedAngle = 0f;
  this.hasValidDirection = true;

  // make sure we're rotating to face the proper direction
  this.useCustomRotation = true;
  while (Vector3.Angle(targetDirection, this.transform.forward) >= 0.25f)
  {
Debug.DrawRay(this.transform.position, this.transform.forward * 5f, Color.blue);
Debug.DrawRay(this.transform.position, targetDirection * 5, Color.red);
yield return null;
  }

  this.useCustomRotation = false;
 }

 

Und hier der eigentliche Update Code, bei dem ich lediglich die Animationen auf Basis der Entfernung und NavMesh Geschwindigkeit setze und prüfe, ob ich den Zielpunkt erreicht habe, in dem Fall wird die Navigation zurückgesetzt:

void Update ()
 {
  // Calculate our distance from target
  float distance = Vector3.Distance(targetPosition, navMesh.transform.position);
  /* Update our speed based on our distance from the target to slow down speed
  reaching target point position */
  var speed = navMesh.desiredVelocity.magnitude * (distance >= 1.0f ? 1f : distance);
  animator.SetFloat(hashes.forward, speed, animationDampTime, Time.deltaTime);
  // only handle on active movement
  if (this.hasValidDirection)
  {
this.Rotate();  
if(distance < pathEndThreshold)
{
 this.hasValidDirection = false;
 this.forward = 0f;
 this.signedAngle = 0f;

 this.navMesh.velocity = Vector3.zero;
 this.navMesh.speed = 0f;
}
// finally blend rotation value
animator.SetFloat(hashes.angle, signedAngle, animationDampTime, Time.deltaTime);
  }
}				  

 

 

Das klappt auch soweit ganz gut, wie Ihr dem folgendem Video entnehmen könnt: https://vid.me/tVvC

 

Für die Rotation selbst nutze ich einen Blend Tree mit diversen Mixamo Animationen unter Berüksichtigung des erforderlichen Rotationswinkels. Für die Animation selbst habe ich in dem Fall die RootMotion aktiviert.

 

Aber genau die RootMotion scheint das Problem zu sein da die Animation scheinbar noch "nachläuft" nachdem der Agent gestoppt wurde und die RootMotion den Avatar über den Zielpunkt hinaus bewegt.

 

Deaktiviere ich die RootMotion, dann stoppt der Avatar zwar am konkreten Zielpunkt. Zuckt aber merkwürdig bevor die eigentliche Rotationsanimation beginnt (ich habe keine Idee wo dies her kommt) zudem macht er i.d.R. auch noch einzelne Schritte obwohl er bereits steht, wie man es diesem Video entnehmen kann: https://vid.me/Ewb4

 

Ich habe auch schon versucht die OnAnimatorMove Methode zu verwenden und hier die aktuelle transform.position des Avatars auf den Wert der NavMesh.nextPosition zu setzen. Dies führt aber lediglich zum gleichen Effekt, wie bei der deaktivierten RootMotion.

 

Ich bin mit meinem Latein inzwischen am Ende und finde zu diesem Thema auch nichts weiter im Netz. Daher bin ich äußerst dankbar für jede Hilfe, da mich dieses Problem schon gut 14 Tage beschäftigt.

 

Gruß

Hellhound

Link zu diesem Kommentar
Auf anderen Seiten teilen

Inzwischen habe ich herausgefunden, dass wenn ich die Methode OnAnimatorMove mit folgendem Setting nutze und zudem am NavMeshAgent die updatePosition auf false setze, er sich korrekt zum Zielpunkt bewegt und auch das merkwürdige Zucken vor Bewegungsbeginn verschwindet:

 

void OnAnimatorMove(){
  transform.rotation = animator.rootRotation;
  transform.position = navMesh.nextPosition;
}

 

Allerdings sind nun Animation und NavMeshAgent nicht synchron, d.h. der Avatar läuft noch eine Weile, obwohl der Zielpunkt erreicht wurde und sowohl der Forward Wert für das Laufen als auch die NavMeshAgent.Velocity auf 0 gesetzt wurden. Hat jemand eine Idee wie ich das in den Griff bekomme?

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...