2013-03-26 10 views
5

Ich schreibe einen 2D Platformer in Unity und ich versuche, den Spieler auf einer beweglichen Plattform zu halten. Ich habe jetzt ein oder zwei Tage damit verbracht, zu suchen und zu basteln, und ich habe kein Glück.Bleiben Sie auf beweglichen Plattformen

Grundsätzlich wurde mir gesagt, ich solle versuchen, den Charakter mit der Plattform in Bewegung zu halten, wenn sie sich berühren. Erstens, wenn ich etwas verwende, das mit OnTriggerEnter() verwandt ist, geht der Spieler direkt durch die Plattform. Wenn ich OnCollisionEnter() (mit einem CharacterController auf dem Player und einem BoxCollider auf der Plattform) mache, passiert gar nichts. Dies sind zwei Dinge, die ich am häufigsten vorgeschlagen habe. Der andere Elternteil ist der Spieler mit der Plattform, aber dies verursacht scheinbar "Probleme" (häufig gesagt, nie erklärt).

Also, wie kann ich den Spieler auf der beweglichen Plattform bleiben? Hier ist der Code für die bewegliche Plattform:

public class MovingPlatform : MonoBehaviour 
{ 
private float useSpeed; 
public float directionSpeed = 9.0f; 
float origY; 
public float distance = 10.0f; 

// Use this for initialization 
void Start() 
{ 
    origY = transform.position.y; 
    useSpeed = -directionSpeed; 
} 

// Update is called once per frame 
void Update() 
{ 
    if(origY - transform.position.y > distance) 
    { 
     useSpeed = directionSpeed; //flip direction 
    } 
    else if(origY - transform.position.y < -distance) 
    { 
     useSpeed = -directionSpeed; //flip direction 
    } 
    transform.Translate(0,useSpeed*Time.deltaTime,0); 
} 

und hier ist der Code für die Bewegung des Spielers (in Update):

CharacterController controller = GetComponent<CharacterController>(); 
    float rotation = Input.GetAxis("Horizontal"); 
    if(controller.isGrounded) 
    { 
     moveDirection.Set(rotation, 0, 0); //moveDirection = new Vector3(rotation, 0, 0); 
     moveDirection = transform.TransformDirection(moveDirection); 

     //running code 
     if(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) //check if shift is held 
     { running = true; } 
     else 
     { running = false; } 

     moveDirection *= running ? runningSpeed : walkingSpeed; //set speed 

     //jump code 
     if(Input.GetButtonDown("Jump")) 
     { 
      //moveDirection.y = jumpHeight; 
      jump(); 
     } 
    } 
    moveDirection.y -= gravity * Time.deltaTime; 
    controller.Move(moveDirection * Time.deltaTime); 

EDIT: Ich denke, es könnte mit dem zu tun hat, wie ich Ich definiere den Spieler und die Plattform, aber ich habe verschiedene Kombinationen ausprobiert. Wenn die Plattform ein Trigger ist (an ihrem Collider), durchläuft der Spieler sie durchgängig. Wenn nicht, kann ich keine OnTrigger-Funktionen verwenden. Ich habe einen starren Körper an den Player und die Plattform, aber es scheint nichts zu beeinflussen. Wenn der Spieler in einigen Setups auf die Plattform kommt, zittert er und fällt oft einfach durch.

+0

Ich habe noch nie Unity3D verwendet, aber ist es möglich, so etwas wie 'moveDirection + = thePlatform zu tun.moveDirection "wenn sich der Charakter auf einer Plattform befindet? – mbeckish

+0

Ich habe das versucht, aber ich habe Probleme mit den OnTrigger und OnCollision Funktionen, die für den "wenn Spieler auf der Plattform ist" Teil davon verantwortlich sein würde. Ich denke, es hat damit zu tun, wie ich meine Objekte definiere, aber ich bin mir nicht sicher, wie man sie so definieren soll, dass dies funktionieren kann. – muttley91

+0

Außerdem müssen Sie sicherstellen, dass die moveDirection.y des Charakters niemals kleiner ist als die der moveDirection.y Ihrer Plattform, sonst würden Sie durchfallen (es sei denn, das Unity3D-Framework handhabt das automatisch für Sie?) – mbeckish

Antwort

1

Was brauchen Sie scheint auf der Plattform ein zweiter Collider zu sein. Der Hauptcollider hat isTrigger = false, um sicherzustellen, dass dein Charakter-Controller funktioniert. Die zweite läuft mit isTrigger = true und ihre einzige Funktion ist zu erkennen, dass der Player an die Plattform angeschlossen ist, wenn OnTriggerEnter aufgerufen wird und die Plattform auf OnTriggerExit verlässt.

Da es nicht möglich ist, 2 Colliders desselben Typs zu verwenden (ich nehme an, Sie benötigen Box Collider), erstellen Sie ein leeres Kind unter Ihrem Plattform-Spielobjekt und weisen Sie ihm den Box Collider zu. Normalerweise nehme ich ein spezielles Physik-Material namens ActionMaterial, nur um meine Sachen sauber zu bekommen. Wenn Sie Layer verwenden und die Kollisionsmatrix optimiert haben, stellen Sie sicher, dass Ihre Kollision von physX gehandhabt wird.

+0

Könnte ich zwei verschiedene Collider (eine Box, eine Kapsel) für dasselbe Objekt auf demselben Objekt verwenden, anstatt zwei Objekte zu haben, und beide benötigen das Move-Script? Außerdem verwende ich keine Ebenen und habe keine optimierte Kollisionsmatrix. – muttley91

+0

Verschiedene Collider sind erlaubt. Bedenken Sie jedoch, dass ein Kapsel-Collider wesentlich teurer ist. Wenn Sie also eine Würfelform haben, verwenden Sie besser die Child-Objekt-Lösung. Keine Layer, keine Kollisionsmatrixmanipulation => keine erhöhte Komplexität;) Sie brauchen dieses Zeug nur, wenn Sie Leistungsprobleme haben. Ich entwickle für iOS, so dass Leistung immer ein Problem für mich ist – Kay

+0

Ah fair genug! Um es klar zu sagen, du hast zwei Spielobjekte in der Szene? Wie machen Sie ein Objekt spezifisch zum Kind eines anderen? – muttley91

1

Dies ist nicht der beste Weg, aber Sie könnten einen RayCast vom Spieler auf die bewegliche Plattform durchführen. Wenn der RayCast auf "MovingPlatform" trifft, können Sie die Differenz auf der Y-Achse prüfen, um festzustellen, ob der Spieler nah genug ist, um als "OnThePlatform" betrachtet zu werden. Dann kannst du einfach die Position des Spielers normal anpassen.

wäre ein Beispiel:

private bool isOnMovingPlatform; 
private float offsetToKeepPlayerAbovePlatform = 2.2f; 
private float min = 0.2f; 
private float max = 1.2f; 

private void Update() 
{ 
RaycastHit hit; 
if(Physics.Raycast (player.position, player.TransformDirection(Vector3.down), out hit)) 
{ 
    if(hit.transform.name.Contains("MovingPlatform")) 
    { 
     Transform movingPlatform = hit.collider.transform; 

     if(movingPlatform.position.y - player.position.y <= min && movingPlatform.position.y - player.position.y >= max) 
     { 
      isOnMovingPlatform = true; 
     } 
     else 
     { 
      isOnMovingPlatform = false; 
     } 
    } 

    if(isOnMovingPlatform) 
    { 
     player.position = new Vector3(hit.transform.x, hit.transform.y + offsetToKeepPlayerAbovePlatform, 0); 
    } 
} 
} 
+0

Nur neugierig, wie ich es versuche, Min, Max und Offset, beziehen sie sich überhaupt auf die Größe der Plattform? – muttley91

+0

Nicht unbedingt. Min und Max sind nur Bereiche, sodass Sie wissen, wo der Player für die Plattform relevant ist. Wenn der Y-Wert des Spielers beispielsweise 5 über dem Maximum liegt, ist klar, dass er nicht auf der Plattform ist und umgekehrt. Ändern Sie die Bereiche, bis Sie ein gutes Paar Schwimmer erhalten. Theoretisch könnten sie sich aus der Höhe der Plattform ergeben, müssen aber nicht. –

0

This Unity Answers page könnte helfen.

+0

Es ist in der Tat ziemlich gut. Aber Sie sollten es als Kommentar posten oder weitere Informationen bereitstellen. Antworten, die nur einen Link enthalten, werden auf SO gelöscht (ich habe gerade einige verloren) – Kay

0

Sie können auch einfach den Player Spielobjekte transformieren Eltern gleich der Transformation der Plattform. Dies ermöglicht es dem Spieler, sich weiter zu bewegen, während er dabei ist. Was die Erkennung betrifft, ist ein Raycast ein wenig langsam, aber erledigt die Arbeit.

Verwandte Themen